diff --git a/.cirrus.yml b/.cirrus.yml new file mode 100644 index 00000000000..98088aa6e02 --- /dev/null +++ b/.cirrus.yml @@ -0,0 +1,44 @@ +freebsd_instance: + image_family: freebsd-12-1-snap + +test_task: + name: "Tests / FreeBSD / " + env: + matrix: + - PYTHON: python2.7 + - PYTHON: python3.5 + - PYTHON: python3.6 + - PYTHON: python3.7 + - PYTHON: python3.8 + python_script: + - PYPACKAGE=$(printf '%s' $PYTHON | tr -d '.') + - SQLPACKAGE=$(printf '%s-sqlite3' $PYPACKAGE | sed 's/thon//') + - pkg install -y git-lite $PYPACKAGE $SQLPACKAGE + pip_script: + - $PYTHON -m ensurepip + - $PYTHON -m pip install -U pip tox poetry + - poetry config virtualenvs.in-project true + tox_script: $PYTHON -m tox -e py -- -q --junitxml=junit.xml tests + on_failure: + annotate_failure_artifacts: + path: junit.xml + format: junit + type: text/xml + +release_task: + name: "Release / FreeBSD" + only_if: $CIRRUS_TAG != '' + freebsd_instance: + matrix: + - image_family: freebsd-12-1-snap + - image_family: freebsd-11-3-snap + python_script: pkg install -y python3 python27 python35 python36 python37 python38 + pip_script: + - python2.7 -m ensurepip + - python3.5 -m ensurepip + - python3.6 -m ensurepip + - python3.7 -m ensurepip + - python3.8 -m ensurepip + build_script: ./make-nix-release.sh + archive_artifacts: + path: "releases/*" diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cb541c562b7..30d8f5fde21 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,121 +7,64 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - - name: Set up Python 3.7 + - uses: actions/checkout@v2 + - name: Set up Python 3.8 uses: actions/setup-python@v1 with: - python-version: 3.7 + python-version: 3.8 - name: Linting run: | pip install pre-commit pre-commit run --all-files - Linux: + Tests: needs: Linting - runs-on: ubuntu-latest + name: ${{ matrix.os }} / ${{ matrix.python-version }} + runs-on: ${{ matrix.os }}-latest strategy: matrix: + os: [Ubuntu, MacOS, Windows] python-version: [2.7, 3.5, 3.6, 3.7, 3.8] - steps: - - uses: actions/checkout@v1 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 - with: - python-version: ${{ matrix.python-version }} - - name: Get full python version - id: full-python-version - run: | - echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))") - - name: Install and set up Poetry - run: | - python get-poetry.py --preview -y - source $HOME/.poetry/env - poetry config virtualenvs.in-project true - - name: Set up cache - uses: actions/cache@v1 - with: - path: .venv - key: venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} - - name: Install dependencies - run: | - source $HOME/.poetry/env - poetry install - - name: Test - run: | - source $HOME/.poetry/env - poetry run pytest -q tests + - uses: actions/checkout@v2 - MacOS: - needs: Linting - runs-on: macos-latest - strategy: - matrix: - python-version: [2.7, 3.5, 3.6, 3.7, 3.8] + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} - steps: - - uses: actions/checkout@v1 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 - with: - python-version: ${{ matrix.python-version }} - - name: Get full python version - id: full-python-version - run: | - echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))") - - name: Install and set up Poetry - run: | - python get-poetry.py --preview -y - source $HOME/.poetry/env - poetry config virtualenvs.in-project true - - name: Set up cache - uses: actions/cache@v1 - with: - path: .venv - key: venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} - - name: Install dependencies - run: | - source $HOME/.poetry/env - poetry install - - name: Test - run: | - source $HOME/.poetry/env - .venv/bin/pytest -q tests + - name: Get full python version + id: full-python-version + shell: bash + run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))") - Windows: - needs: Linting - runs-on: windows-latest - strategy: - matrix: - python-version: [2.7, 3.5, 3.6, 3.7, 3.8] + - name: Install poetry + shell: bash + run: | + curl -fsS -o get-poetry.py https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py + python get-poetry.py -y + echo "::set-env name=PATH::$HOME/.poetry/bin:$PATH" - steps: - - uses: actions/checkout@v1 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 - with: - python-version: ${{ matrix.python-version }} - - name: Get full python version - id: full-python-version - shell: bash - run: | - echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))") - - name: Install and setup Poetry - run: | - python get-poetry.py --preview -y - $env:Path += ";$env:Userprofile\.poetry\bin" - poetry config virtualenvs.in-project true - - name: Set up cache - uses: actions/cache@v1 - with: - path: .venv - key: venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} - - name: Install dependencies - run: | - $env:Path += ";$env:Userprofile\.poetry\bin" - poetry install - - name: Test - run: | - $env:Path += ";$env:Userprofile\.poetry\bin" - poetry run pytest -q tests + - name: Configure poetry + shell: bash + run: poetry config virtualenvs.in-project true + + - name: Set up cache + uses: actions/cache@v1 + id: cache + with: + path: .venv + key: venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} + + - name: Ensure cache is healthy + if: steps.cache.outputs.cache-hit == 'true' + shell: bash + run: poetry run pip --version >/dev/null 2>&1 || rm -rf .venv + + - name: Install dependencies + shell: bash + run: poetry install + + - name: Run pytest + shell: bash + run: poetry run pytest -q tests diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f107c3b5eae..9802901713a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Get tag id: tag run: | @@ -34,7 +34,7 @@ jobs: runs-on: macos-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Get tag id: tag run: | @@ -54,21 +54,19 @@ jobs: - name: Preparing Python executables run: | curl -L https://github.com/sdispater/python-binaries/releases/download/2.7.17/python-2.7.17.macos.tar.xz -o python-2.7.17.tar.xz - curl -L https://github.com/sdispater/python-binaries/releases/download/3.4.10/python-3.4.10.macos.tar.xz -o python-3.4.10.tar.xz curl -L https://github.com/sdispater/python-binaries/releases/download/3.5.9/python-3.5.9.macos.tar.xz -o python-3.5.9.tar.xz curl -L https://github.com/sdispater/python-binaries/releases/download/3.6.8/python-3.6.8.macos.tar.xz -o python-3.6.8.tar.xz - curl -L https://github.com/sdispater/python-binaries/releases/download/3.7.5/python-3.7.5.macos.tar.xz -o python-3.7.5.tar.xz - curl -L https://github.com/sdispater/python-binaries/releases/download/3.8.0/python-3.8.0.macos.tar.xz -o python-3.8.0.tar.xz + curl -L https://github.com/sdispater/python-binaries/releases/download/3.7.6/python-3.7.6.macos.tar.xz -o python-3.7.6.tar.xz + curl -L https://github.com/sdispater/python-binaries/releases/download/3.8.2/python-3.8.2.macos.tar.xz -o python-3.8.2.tar.xz tar -zxf python-2.7.17.tar.xz - tar -zxf python-3.4.10.tar.xz tar -zxf python-3.5.9.tar.xz tar -zxf python-3.6.8.tar.xz - tar -zxf python-3.7.5.tar.xz - tar -zxf python-3.8.0.tar.xz + tar -zxf python-3.7.6.tar.xz + tar -zxf python-3.8.2.tar.xz - name: Build specific release run: | source $HOME/.poetry/env - poetry run python sonnet make release --ansi -P "2.7:python-2.7.17/bin/python" -P "3.4:python-3.4.10/bin/python" -P "3.5:python-3.5.9/bin/python" -P "3.6:python-3.6.8/bin/python" -P "3.7:python-3.7.5/bin/python" -P "3.8:python-3.8.0/bin/python" + poetry run python sonnet make release --ansi -P "2.7:python-2.7.17/bin/python" -P "3.5:python-3.5.9/bin/python" -P "3.6:python-3.6.8/bin/python" -P "3.7:python-3.7.6/bin/python" -P "3.8:python-3.8.2/bin/python" - name: Upload release file uses: actions/upload-artifact@v1 with: @@ -84,7 +82,7 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Get tag id: tag shell: bash @@ -105,27 +103,25 @@ jobs: - name: Preparing Python executables run: | Invoke-WebRequest https://github.com/sdispater/python-binaries/releases/download/2.7.17/python-2.7.17.windows.tar.xz -O python-2.7.17.tar.xz - Invoke-WebRequest https://github.com/sdispater/python-binaries/releases/download/3.4.4/python-3.4.4.windows.tar.xz -O python-3.4.4.tar.xz Invoke-WebRequest https://github.com/sdispater/python-binaries/releases/download/3.5.4/python-3.5.4.windows.tar.xz -O python-3.5.4.tar.xz Invoke-WebRequest https://github.com/sdispater/python-binaries/releases/download/3.6.8/python-3.6.8.windows.tar.xz -O python-3.6.8.tar.xz - Invoke-WebRequest https://github.com/sdispater/python-binaries/releases/download/3.7.5/python-3.7.5.windows.tar.xz -O python-3.7.5.tar.xz - Invoke-WebRequest https://github.com/sdispater/python-binaries/releases/download/3.8.0/python-3.8.0.windows.tar.xz -O python-3.8.0.tar.xz + Invoke-WebRequest https://github.com/sdispater/python-binaries/releases/download/3.7.6/python-3.7.6.windows.tar.xz -O python-3.7.6.tar.xz + Invoke-WebRequest https://github.com/sdispater/python-binaries/releases/download/3.8.2/python-3.8.2.windows.tar.xz -O python-3.8.2.tar.xz 7z x python-2.7.17.tar.xz - 7z x python-3.4.4.tar.xz 7z x python-3.5.4.tar.xz 7z x python-3.6.8.tar.xz - 7z x python-3.7.5.tar.xz - 7z x python-3.8.0.tar.xz + 7z x python-3.7.6.tar.xz + 7z x python-3.8.2.tar.xz 7z x python-2.7.17.tar 7z x python-3.4.4.tar 7z x python-3.5.4.tar 7z x python-3.6.8.tar - 7z x python-3.7.5.tar - 7z x python-3.8.0.tar + 7z x python-3.7.6.tar + 7z x python-3.8.2.tar - name: Build specific release run: | $env:Path += ";$env:Userprofile\.poetry\bin" - poetry run python sonnet make release --ansi -P "2.7:python-2.7.17\python.exe" -P "3.4:python-3.4.4\python.exe" -P "3.5:python-3.5.4\python.exe" -P "3.6:python-3.6.8\python.exe" -P "3.7:python-3.7.5\python.exe" -P "3.8:python-3.8.0\python.exe" + poetry run python sonnet make release --ansi -P "2.7:python-2.7.17\python.exe" -P "3.5:python-3.5.4\python.exe" -P "3.6:python-3.6.8\python.exe" -P "3.7:python-3.7.6\python.exe" -P "3.8:python-3.8.2\python.exe" - name: Upload release file uses: actions/upload-artifact@v1 with: @@ -143,7 +139,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@master + uses: actions/checkout@v2 - name: Get tag id: tag run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index e70d1c8effd..c0fe2ebe814 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,47 @@ # Change Log +## [1.1.0a1] - 2020-03-27 + +This release **must** be downloaded via the `get-poetry.py` script and not via the `self update` command. + +### Added + +- Added a new `--dry-run` option to the `publish` command ([#2199](https://github.com/python-poetry/poetry/pull/2199)). + +### Changed + +- The core features of Poetry have been extracted in to a separate library: `poetry-core` ([#2212](https://github.com/python-poetry/poetry/pull/2212)). +- The build backend is no longer `poetry.masonry.api` but `poetry.core.masonry.api` which requires `poetry-core>=1.0.0a5` ([#2212](https://github.com/python-poetry/poetry/pull/2212)). +- The exceptions are now beautifully displayed in the terminal with various level of details depending on the verbosity ([2230](https://github.com/python-poetry/poetry/pull/2230)). + + +## [1.0.5] - 2020-02-29 + +### Fixed + +- Fixed an error when building distributions if the `git` executable was not found ([#2105](https://github.com/python-poetry/poetry/pull/2105)). +- Fixed various errors when reading Poetry's TOML files by upgrading [tomlkit](https://github.com/sdispater/tomlkit). + + +## [1.0.4] - 2020-02-28 + +### Fixed + +- Fixed the PyPI URL used when installing packages ([#2099](https://github.com/python-poetry/poetry/pull/2099)). +- Fixed errors when the author's name contains special characters ([#2006](https://github.com/python-poetry/poetry/pull/2006)). +- Fixed VCS excluded files detection when building wheels ([#1947](https://github.com/python-poetry/poetry/pull/1947)). +- Fixed packages detection when building sdists ([#1626](https://github.com/python-poetry/poetry/pull/1626)). +- Fixed the local `.venv` virtual environment not being displayed in `env list` ([#1762](https://github.com/python-poetry/poetry/pull/1762)). +- Fixed incompatibilities with the most recent versions of `virtualenv` ([#2096](https://github.com/python-poetry/poetry/pull/2096)). +- Fixed Poetry's own vendor dependencies being retrieved when updating dependencies ([#1981](https://github.com/python-poetry/poetry/pull/1981)). +- Fixed encoding of credentials in URLs ([#1911](https://github.com/python-poetry/poetry/pull/1911)). +- Fixed url constraints not being accepted in multi-constraints dependencies ([#2035](https://github.com/python-poetry/poetry/pull/2035)). +- Fixed an error where credentials specified via environment variables were not retrieved ([#2061](https://github.com/python-poetry/poetry/pull/2061)). +- Fixed an error where git dependencies referencing tags were not locked to the corresponding commit ([#1948](https://github.com/python-poetry/poetry/pull/1948)). +- Fixed an error when parsing packages `setup.py` files ([#2041](https://github.com/python-poetry/poetry/pull/2041)). +- Fixed an error when parsing some git URLs ([#2018](https://github.com/python-poetry/poetry/pull/2018)). + + ## [1.0.3] - 2020-01-31 ### Fixed @@ -796,7 +838,10 @@ Initial release -[Unreleased]: https://github.com/python-poetry/poetry/compare/1.0.3...master +[Unreleased]: https://github.com/python-poetry/poetry/compare/1.1.0a1...develop +[1.1.0a1]: https://github.com/python-poetry/poetry/releases/tag/1.1.0a1 +[1.0.5]: https://github.com/python-poetry/poetry/releases/tag/1.0.5 +[1.0.4]: https://github.com/python-poetry/poetry/releases/tag/1.0.4 [1.0.3]: https://github.com/python-poetry/poetry/releases/tag/1.0.3 [1.0.2]: https://github.com/python-poetry/poetry/releases/tag/1.0.2 [1.0.1]: https://github.com/python-poetry/poetry/releases/tag/1.0.1 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cb9417a50c1..d03da34c186 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,7 +26,7 @@ Before creating bug reports, please check [this list](#before-submitting-a-bug-r #### Before submitting a bug report -* **Check the [FAQs on the official website](https://python-poetry.org)** for a list of common questions and problems. +* **Check the [FAQs on the official website](https://python-poetry.org/docs/faq)** for a list of common questions and problems. * **Check that your issue does not already exist in the [issue tracker](https://github.com/python-poetry/poetry/issues)**. #### How do I submit a bug report? @@ -64,8 +64,8 @@ Before creating enhancement suggestions, please check [this list](#before-submit #### Before submitting an enhancement suggestion -* **Check the [FAQs on the official website](https://python-poetry.org) for a list of common questions and problems. -* **Check that your issue does not already exist in the [issue tracker](https://github.com/python-poetry/poetry/issues). +* **Check the [FAQs on the official website](https://python-poetry.org/docs/faq)** for a list of common questions and problems. +* **Check that your issue does not already exist in the [issue tracker](https://github.com/python-poetry/poetry/issues)**. #### How do I submit an Enhancement suggestion? @@ -99,7 +99,7 @@ $ poetry install $ poetry run pytest tests/ ``` -Poetry uses the [black](https://github.com/ambv/black) coding style and you must ensure that your +Poetry uses the [black](https://github.com/psf/black) coding style and you must ensure that your code follows it. If not, the CI will fail and your Pull Request will not be merged. Similarly, the import statements are sorted with [isort](https://github.com/timothycrosley/isort) diff --git a/Makefile b/Makefile index 2e57c3b947c..ccb529f1f0a 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,14 @@ wheel: linux_release: docker pull quay.io/pypa/manylinux2010_x86_64 - docker run --rm -i -v `pwd`:/io quay.io/pypa/manylinux2010_x86_64 /io/make-linux-release.sh + docker run --rm -i -v `pwd`:/io \ + -e PYTHON=/opt/python/cp37-cp37m/bin/python \ + -e PYTHON27=/opt/python/cp27-cp27m/bin/python \ + -e PYTHON35=/opt/python/cp35-cp35m/bin/python \ + -e PYTHON36=/opt/python/cp36-cp36m/bin/python \ + -e PYTHON37=/opt/python/cp37-cp37m/bin/python \ + -e PYTHON38=/opt/python/cp38-cp38/bin/python \ + quay.io/pypa/manylinux2010_x86_64 sh -c "cd /io && ./make-nix-release.sh" # run tests against all supported python versions tox: diff --git a/README.md b/README.md index 7bea3955c96..ea0df8ded25 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ ensuring you have the right stack everywhere. It supports Python 2.7 and 3.4+. -![Tests Status](https://github.com/python-poetry/poetry/workflows/Tests/badge.svg) +[![Tests Status](https://github.com/python-poetry/poetry/workflows/Tests/badge.svg?branch=master&event=push)](https://github.com/python-poetry/poetry/actions?query=workflow%3ATests+branch%3Amaster+event%3Apush) The [complete documentation](https://python-poetry.org/docs/) is available on the [official website](https://python-poetry.org). diff --git a/docs/docs/cli.md b/docs/docs/cli.md index 63d63fbc990..f025c4f15f5 100644 --- a/docs/docs/cli.md +++ b/docs/docs/cli.md @@ -245,6 +245,7 @@ poetry add "git+https://github.com/pallets/flask.git@1.1.1[dotenv,dev]" * `--path`: The path to a dependency. * `--optional` : Add as an optional dependency. * `--dry-run` : Outputs the operations but will not execute anything (implicitly enables --verbose). +* `--lock` : Do not perform install (only update the lockfile). ## remove @@ -325,6 +326,7 @@ It can also build the package if you pass it the `--build` option. Should match a repository name set by the [`config`](#config) command. * `--username (-u)`: The username to access the repository. * `--password (-p)`: The password to access the repository. +* `--dry-run`: Perform all actions except upload the package. ## config @@ -422,6 +424,9 @@ bump rule is provided. The new version should ideally be a valid semver string or a valid bump rule: `patch`, `minor`, `major`, `prepatch`, `preminor`, `premajor`, `prerelease`. +## Options + +* `--short (-s)`: Output the version number only. ## export @@ -437,8 +442,8 @@ poetry export -f requirements.txt > requirements.txt ### Options -* `--format (-f)`: The format to export to. Currently, only - `requirements.txt` is supported. +* `--format (-f)`: The format to export to (default: `requirements.txt`). + Currently, only `requirements.txt` is supported. * `--output (-o)`: The name of the output file. If omitted, print to standard output. * `--dev`: Include development dependencies. diff --git a/docs/docs/faq.md b/docs/docs/faq.md index 1568143327e..4d464d7ebc0 100644 --- a/docs/docs/faq.md +++ b/docs/docs/faq.md @@ -42,8 +42,8 @@ So, in your `pyproject.toml` file, add this section if it does not already exist ```toml [build-system] -requires = ["poetry>=0.12"] -build-backend = "poetry.masonry.api" +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" ``` And use a `tox.ini` configuration file similar to this: diff --git a/docs/docs/managing-environments.md b/docs/docs/managing-environments.md index 51e2a68e7a0..47e8ede4047 100644 --- a/docs/docs/managing-environments.md +++ b/docs/docs/managing-environments.md @@ -1,6 +1,6 @@ # Managing environments -Poetry makes project environment isolation one of its core feature. +Poetry makes project environment isolation one of its core features. What this means is that it will always work isolated from your global Python installation. To achieve this, it will first check if it's currently running inside a virtual environment. diff --git a/docs/docs/pyproject.md b/docs/docs/pyproject.md index b6bcbe318f1..004fa5c1b22 100644 --- a/docs/docs/pyproject.md +++ b/docs/docs/pyproject.md @@ -274,16 +274,22 @@ If you publish you package on PyPI, they will appear in the `Project Links` sect [PEP-517](https://www.python.org/dev/peps/pep-0517/) introduces a standard way to define alternative build systems to build a Python project. -Poetry is compliant with PEP-517 so if you use Poetry to manage your Python -project you should reference it in the `build-system` section of the `pyproject.toml` -file like so: +Poetry is compliant with PEP-517, by providing a lightweight core library, +so if you use Poetry to manage your Python project you should reference +it in the `build-system` section of the `pyproject.toml` file like so: ```toml [build-system] -requires = ["poetry>=0.12"] -build-backend = "poetry.masonry.api" +requires = ["poetry_core>=1.0.0"] +build-backend = "poetry.core.masonry.api" ``` !!!note When using the `new` or `init` command this section will be automatically added. + + +!!!note + + If your `pyproject.toml` file still references `poetry` directly as a build backend, + you should update it to reference `poetry_core` instead. diff --git a/get-poetry.py b/get-poetry.py index 7a2b18d3997..898d55946a5 100644 --- a/get-poetry.py +++ b/get-poetry.py @@ -204,8 +204,13 @@ def expanduser(path): import os lib = os.path.normpath(os.path.join(os.path.realpath(__file__), "../..", "lib")) +vendors = os.path.join(lib, "poetry", "_vendor") +current_vendors = os.path.join( + vendors, "py{}".format(".".join(str(v) for v in sys.version_info[:2])) +) sys.path.insert(0, lib) +sys.path.insert(0, current_vendors) if __name__ == "__main__": from poetry.console import main @@ -328,14 +333,17 @@ def __init__( version=None, preview=False, force=False, + modify_path=True, accept_all=False, + file=None, base_url=BASE_URL, ): self._version = version self._preview = preview self._force = force - self._modify_path = True + self._modify_path = modify_path self._accept_all = accept_all + self._offline_file = file self._base_url = base_url def allows_prereleases(self): @@ -352,7 +360,9 @@ def run(self): self.ensure_home() try: - self.install(version, upgrade=current_version is not None) + self.install( + version, upgrade=current_version is not None, file=self._offline_file + ) except subprocess.CalledProcessError as e: print(colorize("error", "An error has occured: {}".format(str(e)))) print(e.output.decode()) @@ -373,6 +383,34 @@ def uninstall(self): self.remove_from_path() def get_version(self): + current_version = None + if os.path.exists(POETRY_LIB): + with open( + os.path.join(POETRY_LIB, "poetry", "__version__.py"), encoding="utf-8" + ) as f: + version_content = f.read() + + current_version_re = re.match( + '(?ms).*__version__ = "(.+)".*', version_content + ) + if not current_version_re: + print( + colorize( + "warning", + "Unable to get the current Poetry version. Assuming None", + ) + ) + else: + current_version = current_version_re.group(1) + + # Skip retrieving online release versions if install file is specified + if self._offline_file is not None: + if current_version is not None and not self._force: + print("There is a version of Poetry already installed.") + return None, current_version + + return "from an offline file", current_version + print(colorize("info", "Retrieving Poetry metadata")) metadata = json.loads(self._get(self.METADATA_URL).decode()) @@ -412,26 +450,6 @@ def _compare_versions(x, y): break - current_version = None - if os.path.exists(POETRY_LIB): - with open( - os.path.join(POETRY_LIB, "poetry", "__version__.py"), encoding="utf-8" - ) as f: - version_content = f.read() - - current_version_re = re.match( - '(?ms).*__version__ = "(.+)".*', version_content - ) - if not current_version_re: - print( - colorize( - "warning", - "Unable to get the current Poetry version. Assuming None", - ) - ) - else: - current_version = current_version_re.group(1) - if current_version == version and not self._force: print("Latest version already installed.") return None, current_version @@ -479,11 +497,14 @@ def remove_home(self): shutil.rmtree(POETRY_HOME) - def install(self, version, upgrade=False): + def install(self, version, upgrade=False, file=None): """ Installs Poetry in $POETRY_HOME. """ - print("Installing version: " + colorize("info", version)) + if file is not None: + print("Attempting to install from file: " + colorize("info", file)) + else: + print("Installing version: " + colorize("info", version)) self.make_lib(version) self.make_bin() @@ -519,6 +540,14 @@ def make_lib(self, version): shutil.rmtree(POETRY_LIB_BACKUP) def _make_lib(self, version): + # Check if an offline installer file has been specified + if self._offline_file is not None: + try: + self.extract_lib(self._offline_file) + return + except Exception: + raise RuntimeError("Could not install from offline file.") + # We get the payload from the remote host platform = sys.platform if platform == "linux2": @@ -578,12 +607,15 @@ def _make_lib(self, version): ) ) - gz = GzipFile(tar, mode="rb") - try: - with tarfile.TarFile(tar, fileobj=gz, format=tarfile.PAX_FORMAT) as f: - f.extractall(POETRY_LIB) - finally: - gz.close() + self.extract_lib(tar) + + def extract_lib(self, filename): + gz = GzipFile(filename, mode="rb") + try: + with tarfile.TarFile(filename, fileobj=gz, format=tarfile.PAX_FORMAT) as f: + f.extractall(POETRY_LIB) + finally: + gz.close() def make_bin(self): if not os.path.exists(POETRY_BIN): @@ -914,37 +946,74 @@ def main(): description="Installs the latest (or given) version of poetry" ) parser.add_argument( - "-p", "--preview", dest="preview", action="store_true", default=False + "-p", + "--preview", + help="install preview version", + dest="preview", + action="store_true", + default=False, + ) + parser.add_argument("--version", help="install named version", dest="version") + parser.add_argument( + "-f", + "--force", + help="install on top of existing version", + dest="force", + action="store_true", + default=False, ) - parser.add_argument("--version", dest="version") parser.add_argument( - "-f", "--force", dest="force", action="store_true", default=False + "--no-modify-path", + help="do not modify $PATH", + dest="no_modify_path", + action="store_true", + default=False, ) parser.add_argument( - "-y", "--yes", dest="accept_all", action="store_true", default=False + "-y", + "--yes", + help="accept all prompts", + dest="accept_all", + action="store_true", + default=False, ) parser.add_argument( - "--uninstall", dest="uninstall", action="store_true", default=False + "--uninstall", + help="uninstall poetry", + dest="uninstall", + action="store_true", + default=False, + ) + parser.add_argument( + "--file", + dest="file", + action="store", + help="Install from a local file instead of fetching the latest version " + "of Poetry available online.", ) args = parser.parse_args() base_url = Installer.BASE_URL - try: - urlopen(Installer.REPOSITORY_URL) - except HTTPError as e: - if e.code == 404: - base_url = Installer.FALLBACK_BASE_URL - else: - raise + + if args.file is None: + try: + urlopen(Installer.REPOSITORY_URL) + except HTTPError as e: + if e.code == 404: + base_url = Installer.FALLBACK_BASE_URL + else: + raise installer = Installer( version=args.version or os.getenv("POETRY_VERSION"), preview=args.preview or string_to_bool(os.getenv("POETRY_PREVIEW", "0")), force=args.force, + modify_path=not args.no_modify_path, accept_all=args.accept_all or string_to_bool(os.getenv("POETRY_ACCEPT", "0")) or not is_interactive(), + file=args.file, base_url=base_url, ) diff --git a/make-linux-release.sh b/make-linux-release.sh deleted file mode 100755 index 474202af3f8..00000000000 --- a/make-linux-release.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -PYTHON_VERSIONS="cp27-cp27m cp34-cp34m cp35-cp35m cp36-cp36m cp37-cp37m cp38-cp38" - -cd /io -/opt/python/cp37-cp37m/bin/pip install pip -U -/opt/python/cp37-cp37m/bin/pip install poetry -U --pre -/opt/python/cp37-cp37m/bin/poetry config virtualenvs.create false -/opt/python/cp37-cp37m/bin/poetry install --no-dev -/opt/python/cp37-cp37m/bin/python sonnet make release --ansi \ - -P "2.7:/opt/python/cp27-cp27m/bin/python" \ - -P "3.4:/opt/python/cp34-cp34m/bin/python" \ - -P "3.5:/opt/python/cp35-cp35m/bin/python" \ - -P "3.6:/opt/python/cp36-cp36m/bin/python" \ - -P "3.7:/opt/python/cp37-cp37m/bin/python" \ - -P "3.8:/opt/python/cp38-cp38/bin/python" -cd - diff --git a/make-nix-release.sh b/make-nix-release.sh new file mode 100755 index 00000000000..e5a368002bc --- /dev/null +++ b/make-nix-release.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +set -e + +test -n "$PYTHON" || PYTHON="python3" +$PYTHON -m pip install pip -U +$PYTHON -m pip install poetry -U --pre +$PYTHON -m poetry config virtualenvs.create false +$PYTHON -m poetry install --no-dev +$PYTHON sonnet make release \ + ${PYTHON27:+-P "2.7:$PYTHON27"} \ + ${PYTHON35:+-P "3.5:$PYTHON35"} \ + ${PYTHON36:+-P "3.6:$PYTHON36"} \ + ${PYTHON37:+-P "3.7:$PYTHON37"} \ + ${PYTHON38:+-P "3.8:$PYTHON38"} diff --git a/poetry.lock b/poetry.lock index 8cc55799405..d2ab97bd590 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,7 +1,7 @@ [[package]] -category = "dev" +category = "main" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -marker = "python_version >= \"3.6\" and python_version < \"4.0\"" +marker = "python_version >= \"2.7\" and python_version < \"2.8\" or python_version >= \"3.6\" and python_version < \"4.0\"" name = "appdirs" optional = false python-versions = "*" @@ -27,7 +27,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "1.3.0" [[package]] -category = "main" +category = "dev" description = "Classes Without Boilerplate" name = "attrs" optional = false @@ -100,16 +100,16 @@ description = "Python package for providing Mozilla's CA Bundle." name = "certifi" optional = false python-versions = "*" -version = "2019.11.28" +version = "2020.4.5.1" [[package]] category = "main" description = "Foreign Function Interface for Python calling C code." -marker = "python_version >= \"2.7\" and python_version < \"2.8\" and (sys_platform == \"linux2\" or sys_platform == \"linux\") or python_version >= \"3.4\" and python_version < \"3.5\" and (sys_platform == \"linux2\" or sys_platform == \"linux\") or python_version >= \"3.5\" and python_version < \"4.0\" and sys_platform == \"linux\"" +marker = "python_version >= \"2.7\" and python_version < \"2.8\" and (sys_platform == \"linux2\" or sys_platform == \"linux\") or python_version >= \"3.5\" and python_version < \"3.6\" and sys_platform == \"linux\" or python_version >= \"3.6\" and python_version < \"4.0\" and sys_platform == \"linux\"" name = "cffi" optional = false python-versions = "*" -version = "1.13.2" +version = "1.14.0" [package.dependencies] pycparser = "*" @@ -139,10 +139,10 @@ description = "Cleo allows you to create beautiful and testable command-line int name = "cleo" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.7.6" +version = "0.8.0" [package.dependencies] -clikit = ">=0.4.0,<0.5.0" +clikit = ">=0.5.0,<0.6.0" [[package]] category = "dev" @@ -150,8 +150,8 @@ description = "Composable command line interface toolkit" marker = "python_version >= \"2.7.9\" and python_version < \"2.8.0\" or python_version >= \"3.4\" and python_version < \"4.0\" or python_version >= \"3.6\" and python_version < \"4.0\"" name = "click" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "7.0" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "7.1.1" [[package]] category = "main" @@ -159,10 +159,10 @@ description = "CliKit is a group of utilities to build beautiful and testable co name = "clikit" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.4.1" +version = "0.5.1" [package.dependencies] -pastel = ">=0.1.0,<0.2.0" +pastel = ">=0.2.0,<0.3.0" pylev = ">=1.3,<2.0" [package.dependencies.enum34] @@ -173,14 +173,13 @@ version = ">=1.1,<2.0" python = ">=2.7,<2.8 || >=3.4,<3.5" version = ">=3.6,<4.0" -[[package]] -category = "dev" -description = "Cross-platform colored terminal text." -marker = "sys_platform == \"win32\" and python_version == \"3.4\"" -name = "colorama" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.4.1" +[package.dependencies.typing-extensions] +python = ">=3.5.0,<3.5.4" +version = ">=3.6,<4.0" + +[package.dependencies.woops] +python = ">=3.6,<4.0" +version = ">=0.2.1,<0.3.0" [[package]] category = "dev" @@ -194,7 +193,7 @@ version = "0.4.3" [[package]] category = "main" description = "Updated configparser from Python 3.7 for Python 2.6+." -marker = "python_version == \"2.7\" and python_version == \"2.7\" or python_version < \"3\"" +marker = "python_version >= \"2.7\" and python_version < \"2.8\" or python_version == \"2.7\" and python_version == \"2.7\" or python_version < \"3\"" name = "configparser" optional = false python-versions = ">=2.6" @@ -207,27 +206,19 @@ testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2)", "pytes [[package]] category = "main" description = "Backports and enhancements for the contextlib module" -marker = "python_version < \"3.4\"" +marker = "python_version >= \"2.7\" and python_version < \"2.8\" or python_version < \"3.4\"" name = "contextlib2" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "0.6.0.post1" -[[package]] -category = "dev" -description = "Code coverage measurement for Python" -name = "coverage" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, <4" -version = "4.5.4" - [[package]] category = "dev" description = "Code coverage measurement for Python" name = "coverage" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" -version = "5.0.3" +version = "5.1" [package.extras] toml = ["toml"] @@ -235,11 +226,11 @@ toml = ["toml"] [[package]] category = "main" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -marker = "python_version >= \"2.7\" and python_version < \"2.8\" and (sys_platform == \"linux2\" or sys_platform == \"linux\") or python_version >= \"3.4\" and python_version < \"3.5\" and (sys_platform == \"linux2\" or sys_platform == \"linux\") or python_version >= \"3.5\" and python_version < \"4.0\" and sys_platform == \"linux\"" +marker = "python_version >= \"2.7\" and python_version < \"2.8\" and (sys_platform == \"linux2\" or sys_platform == \"linux\") or python_version >= \"3.5\" and python_version < \"3.6\" and sys_platform == \"linux\" or python_version >= \"3.6\" and python_version < \"4.0\" and sys_platform == \"linux\"" name = "cryptography" optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" -version = "2.8" +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" +version = "2.9.2" [package.dependencies] cffi = ">=1.8,<1.11.3 || >1.11.3" @@ -260,10 +251,19 @@ idna = ["idna (>=2.1)"] pep8test = ["flake8", "flake8-import-order", "pep8-naming"] test = ["pytest (>=3.6.0,<3.9.0 || >3.9.0,<3.9.1 || >3.9.1,<3.9.2 || >3.9.2)", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,<3.79.2 || >3.79.2)"] +[[package]] +category = "main" +description = "Distribution utilities" +marker = "python_version >= \"2.7\" and python_version < \"2.8\"" +name = "distlib" +optional = false +python-versions = "*" +version = "0.3.0" + [[package]] category = "main" description = "Discover and load entry points from installed packages." -marker = "python_version >= \"2.7\" and python_version < \"2.8\" or python_version >= \"3.4\" and python_version < \"3.5\"" +marker = "python_version >= \"2.7\" and python_version < \"2.8\"" name = "entrypoints" optional = false python-versions = ">=2.7" @@ -281,10 +281,10 @@ marker = "python_version >= \"2.7\" and python_version < \"2.8\" or python_versi name = "enum34" optional = false python-versions = "*" -version = "1.1.6" +version = "1.1.10" [[package]] -category = "dev" +category = "main" description = "A platform independent file lock." name = "filelock" optional = false @@ -303,7 +303,7 @@ version = "1.0.2" [[package]] category = "main" description = "Backport of the functools module from Python 3.2.3 for use on 2.7 and PyPy." -marker = "python_version >= \"2.7\" and python_version < \"2.8\" or python_version < \"3\"" +marker = "python_version >= \"2.7\" and python_version < \"2.8\"" name = "functools32" optional = false python-versions = "*" @@ -311,17 +311,17 @@ version = "3.2.3-2" [[package]] category = "dev" -description = "Backport of the concurrent.futures package from Python 3" +description = "Backport of the concurrent.futures package from Python 3.2" marker = "python_version < \"3.2\"" name = "futures" optional = false -python-versions = ">=2.6, <3" -version = "3.3.0" +python-versions = "*" +version = "3.1.1" [[package]] category = "main" description = "Version of the glob module that can capture patterns and supports recursive wildcards" -marker = "python_version >= \"2.7\" and python_version < \"2.8\" or python_version >= \"3.4\" and python_version < \"3.5\"" +marker = "python_version >= \"2.7\" and python_version < \"2.8\"" name = "glob2" optional = false python-versions = "*" @@ -363,7 +363,7 @@ description = "File identification library for Python" name = "identify" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -version = "1.4.11" +version = "1.4.15" [package.extras] license = ["editdistance"] @@ -374,15 +374,16 @@ description = "Internationalized Domain Names in Applications (IDNA)" name = "idna" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.8" +version = "2.9" [[package]] category = "main" description = "Read metadata from Python packages" +marker = "python_version >= \"2.7\" and python_version < \"2.8\" or python_version < \"3.8\" or python_version >= \"3.5\" and python_version < \"3.6\" or python_version >= \"3.6\" and python_version < \"3.8\"" name = "importlib-metadata" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -version = "1.1.3" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +version = "1.6.0" [package.dependencies] zipp = ">=0.5" @@ -395,28 +396,51 @@ version = ">=3.5" python = "<3" version = "*" +[package.dependencies.pathlib2] +python = "<3" +version = "*" + [package.extras] docs = ["sphinx", "rst.linker"] testing = ["packaging", "importlib-resources"] [[package]] -category = "dev" +category = "main" description = "Read resources from Python packages" -marker = "python_version < \"3.7\"" +marker = "python_version >= \"2.7\" and python_version < \"2.8\" or python_version < \"3.7\"" name = "importlib-resources" optional = false -python-versions = ">=2.7,!=3.0,!=3.1,!=3.2,!=3.3" -version = "1.0.2" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +version = "1.4.0" [package.dependencies] +[package.dependencies.contextlib2] +python = "<3" +version = "*" + +[package.dependencies.importlib-metadata] +python = "<3.8" +version = "*" + [package.dependencies.pathlib2] python = "<3" version = "*" +[package.dependencies.singledispatch] +python = "<3.4" +version = "*" + [package.dependencies.typing] python = "<3.5" version = "*" +[package.dependencies.zipp] +python = "<3.8" +version = ">=0.4" + +[package.extras] +docs = ["sphinx", "rst.linker", "jaraco.packaging"] + [[package]] category = "main" description = "IPv4/IPv6 manipulation library" @@ -429,30 +453,15 @@ version = "1.0.23" [[package]] category = "main" description = "Low-level, pure Python DBus protocol wrapper." -marker = "python_version >= \"3.5\" and python_version < \"4.0\" and sys_platform == \"linux\"" +marker = "python_version >= \"3.5\" and python_version < \"3.6\" and sys_platform == \"linux\" or python_version >= \"3.6\" and python_version < \"4.0\" and sys_platform == \"linux\"" name = "jeepney" optional = false python-versions = ">=3.5" -version = "0.4.2" +version = "0.4.3" [package.extras] dev = ["testpath"] -[[package]] -category = "dev" -description = "A very fast and expressive template engine." -marker = "python_version >= \"2.7.9\" and python_version < \"2.8.0\" or python_version >= \"3.4\" and python_version < \"4.0\"" -name = "jinja2" -optional = false -python-versions = "*" -version = "2.10.3" - -[package.dependencies] -MarkupSafe = ">=0.23" - -[package.extras] -i18n = ["Babel (>=0.8)"] - [[package]] category = "dev" description = "A very fast and expressive template engine." @@ -460,7 +469,7 @@ marker = "python_version >= \"2.7.9\" and python_version < \"2.8.0\" or python_v name = "jinja2" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.11.1" +version = "2.11.2" [package.dependencies] MarkupSafe = ">=0.23" @@ -468,36 +477,10 @@ MarkupSafe = ">=0.23" [package.extras] i18n = ["Babel (>=0.8)"] -[[package]] -category = "main" -description = "An implementation of JSON Schema validation for Python" -name = "jsonschema" -optional = false -python-versions = "*" -version = "3.2.0" - -[package.dependencies] -attrs = ">=17.4.0" -pyrsistent = ">=0.14.0" -setuptools = "*" -six = ">=1.11.0" - -[package.dependencies.functools32] -python = "<3" -version = "*" - -[package.dependencies.importlib-metadata] -python = "<3.8" -version = "*" - -[package.extras] -format = ["idna", "jsonpointer (>1.13)", "rfc3987", "strict-rfc3339", "webcolors"] -format_nongpl = ["idna", "jsonpointer (>1.13)", "webcolors", "rfc3986-validator (>0.1.0)", "rfc3339-validator"] - [[package]] category = "main" description = "Store and access your passwords safely." -marker = "python_version >= \"2.7\" and python_version < \"2.8\" or python_version >= \"3.4\" and python_version < \"3.5\"" +marker = "python_version >= \"2.7\" and python_version < \"2.8\"" name = "keyring" optional = false python-versions = ">=2.7" @@ -518,7 +501,7 @@ testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs", "pytest-flake8 [[package]] category = "main" description = "Store and access your passwords safely." -marker = "python_version >= \"3.5\" and python_version < \"4.0\"" +marker = "python_version >= \"3.5\" and python_version < \"3.6\"" name = "keyring" optional = false python-versions = ">=3.5" @@ -536,6 +519,28 @@ version = "*" docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-black-multipy", "pytest-cov"] +[[package]] +category = "main" +description = "Store and access your passwords safely." +marker = "python_version >= \"3.6\" and python_version < \"4.0\"" +name = "keyring" +optional = false +python-versions = ">=3.6" +version = "21.2.0" + +[package.dependencies] +SecretStorage = ">=3" +jeepney = ">=0.4.2" +pywin32-ctypes = "<0.1.0 || >0.1.0,<0.1.1 || >0.1.1" + +[package.dependencies.importlib-metadata] +python = "<3.8" +version = "*" + +[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.3)", "pytest-flake8", "pytest-black-multipy", "pytest-cov"] + [[package]] category = "dev" description = "Python LiveReload is an awesome tool for web developers" @@ -557,14 +562,6 @@ optional = false python-versions = "*" version = "0.12.2" -[[package]] -category = "dev" -description = "Python implementation of Markdown." -name = "markdown" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" -version = "3.0.1" - [[package]] category = "dev" description = "Python implementation of Markdown." @@ -573,9 +570,6 @@ optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" version = "3.1.1" -[package.dependencies] -setuptools = ">=36" - [package.extras] testing = ["coverage", "pyyaml"] @@ -640,7 +634,6 @@ test = ["pytest", "pytest-cov"] [[package]] category = "dev" description = "More routines for operating on iterables, beyond itertools" -marker = "python_version <= \"2.7\"" name = "more-itertools" optional = false python-versions = "*" @@ -649,31 +642,13 @@ version = "5.0.0" [package.dependencies] six = ">=1.0.0,<2.0.0" -[[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.2.0" - -[[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.5" -version = "8.2.0" - [[package]] category = "main" description = "MessagePack (de)serializer." name = "msgpack" optional = false python-versions = "*" -version = "0.6.2" +version = "1.0.0" [[package]] category = "dev" @@ -681,7 +656,7 @@ description = "Node.js virtual environment builder" name = "nodeenv" optional = false python-versions = "*" -version = "1.3.4" +version = "1.3.5" [[package]] category = "dev" @@ -689,7 +664,7 @@ description = "Core utilities for Python packages" name = "packaging" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "20.1" +version = "20.3" [package.dependencies] pyparsing = ">=2.0.2" @@ -701,12 +676,12 @@ description = "Bring colors to your terminal." name = "pastel" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.1.1" +version = "0.2.0" [[package]] category = "main" description = "Object-oriented filesystem paths" -marker = "python_version >= \"2.7\" and python_version < \"2.8\" or python_version >= \"3.4\" and python_version < \"3.5\" or python_version < \"3.6\"" +marker = "python_version >= \"2.7\" and python_version < \"2.8\" and sys_platform != \"win32\" or python_version >= \"2.7\" and python_version < \"2.8\" or python_version < \"3.6\"" name = "pathlib2" optional = false python-versions = "*" @@ -726,7 +701,7 @@ marker = "python_version >= \"3.6\" and python_version < \"4.0\"" name = "pathspec" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.7.0" +version = "0.8.0" [[package]] category = "dev" @@ -775,27 +750,29 @@ version = ">=0.12" dev = ["pre-commit", "tox"] [[package]] -category = "dev" -description = "A framework for managing and maintaining multi-language pre-commit hooks." -name = "pre-commit" +category = "main" +description = "Core utilities for Poetry" +name = "poetry-core" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.18.3" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "1.0.0a6" [package.dependencies] -"aspy.yaml" = "*" -cfgv = ">=2.0.0" -identify = ">=1.0.0" -importlib-metadata = "*" -nodeenv = ">=0.11.1" -pyyaml = "*" -six = "*" -toml = "*" -virtualenv = ">=15.2" +[package.dependencies.enum34] +python = ">=2.7,<2.8" +version = ">=1.1.10,<2.0.0" -[package.dependencies.importlib-resources] -python = "<3.7" -version = "*" +[package.dependencies.functools32] +python = ">=2.7,<2.8" +version = ">=3.2.3-2,<4.0.0" + +[package.dependencies.pathlib2] +python = ">=2.7,<2.8" +version = ">=2.3.5,<3.0.0" + +[package.dependencies.typing] +python = ">=2.7,<2.8" +version = ">=3.7.4.1,<4.0.0.0" [[package]] category = "dev" @@ -846,19 +823,11 @@ version = "1.8.1" [[package]] category = "main" description = "C parser in Python" -marker = "python_version >= \"2.7\" and python_version < \"2.8\" and (sys_platform == \"linux2\" or sys_platform == \"linux\") or python_version >= \"3.4\" and python_version < \"3.5\" and (sys_platform == \"linux2\" or sys_platform == \"linux\") or python_version >= \"3.5\" and python_version < \"4.0\" and sys_platform == \"linux\"" +marker = "python_version >= \"2.7\" and python_version < \"2.8\" and (sys_platform == \"linux2\" or sys_platform == \"linux\") or python_version >= \"3.5\" and python_version < \"3.6\" and sys_platform == \"linux\" or python_version >= \"3.6\" and python_version < \"4.0\" and sys_platform == \"linux\"" name = "pycparser" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.19" - -[[package]] -category = "dev" -description = "Pygments is a syntax highlighting package written in Python." -name = "pygments" -optional = false -python-versions = "*" -version = "2.3.1" +version = "2.20" [[package]] category = "dev" @@ -887,17 +856,6 @@ optional = false python-versions = "*" version = "1.3.0" -[[package]] -category = "dev" -description = "Extension pack for Python Markdown." -name = "pymdown-extensions" -optional = false -python-versions = "*" -version = "6.0" - -[package.dependencies] -Markdown = ">=3.0.1" - [[package]] category = "dev" description = "Extension pack for Python Markdown." @@ -911,23 +869,12 @@ Markdown = ">=3.0.1" pep562 = "*" [[package]] -category = "main" +category = "dev" description = "Python parsing module" name = "pyparsing" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -version = "2.4.6" - -[[package]] -category = "main" -description = "Persistent/Functional/Immutable data structures" -name = "pyrsistent" -optional = false -python-versions = "*" -version = "0.14.11" - -[package.dependencies] -six = "*" +version = "2.4.7" [[package]] category = "dev" @@ -946,14 +893,6 @@ py = ">=1.5.0" six = ">=1.10.0" wcwidth = "*" -[[package.dependencies.colorama]] -python = "<3.4.0 || >=3.5.0" -version = "*" - -[[package.dependencies.colorama]] -python = ">=3.4,<3.5" -version = "<=0.4.1" - [[package.dependencies.more-itertools]] python = "<2.8" version = ">=4.0.0,<6.0.0" @@ -962,6 +901,10 @@ version = ">=4.0.0,<6.0.0" python = ">=2.8" version = ">=4.0.0" +[package.dependencies.colorama] +python = "<3.4.0 || >=3.5.0" +version = "*" + [package.dependencies.funcsigs] python = "<3.0" version = ">=1.0" @@ -1026,27 +969,19 @@ termcolor = ">=1.1.0" [[package]] category = "main" description = "" -marker = "python_version >= \"2.7\" and python_version < \"2.8\" and sys_platform == \"win32\" or python_version >= \"3.4\" and python_version < \"3.5\" and sys_platform == \"win32\" or python_version >= \"3.5\" and python_version < \"4.0\" and sys_platform == \"win32\"" +marker = "python_version >= \"2.7\" and python_version < \"2.8\" and sys_platform == \"win32\" or python_version >= \"3.5\" and python_version < \"3.6\" and sys_platform == \"win32\" or python_version >= \"3.6\" and python_version < \"4.0\" and sys_platform == \"win32\"" name = "pywin32-ctypes" optional = false python-versions = "*" version = "0.2.0" -[[package]] -category = "dev" -description = "YAML parser and emitter for Python" -name = "pyyaml" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "5.2" - [[package]] category = "dev" description = "YAML parser and emitter for Python" name = "pyyaml" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "5.3" +version = "5.3.1" [[package]] category = "dev" @@ -1055,25 +990,7 @@ marker = "python_version >= \"3.6\" and python_version < \"4.0\"" name = "regex" optional = false python-versions = "*" -version = "2020.1.8" - -[[package]] -category = "main" -description = "Python HTTP for Humans." -name = "requests" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.21.0" - -[package.dependencies] -certifi = ">=2017.4.17" -chardet = ">=3.0.2,<3.1.0" -idna = ">=2.5,<2.9" -urllib3 = ">=1.21.1,<1.25" - -[package.extras] -security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)"] -socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] +version = "2020.4.4" [[package]] category = "main" @@ -1081,16 +998,16 @@ description = "Python HTTP for Humans." name = "requests" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.22.0" +version = "2.23.0" [package.dependencies] certifi = ">=2017.4.17" -chardet = ">=3.0.2,<3.1.0" -idna = ">=2.5,<2.9" +chardet = ">=3.0.2,<4" +idna = ">=2.5,<3" urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" [package.extras] -security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)"] +security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] [[package]] @@ -1107,7 +1024,7 @@ requests = ">=2.0.1,<3.0.0" [[package]] category = "main" description = "scandir, a better directory iterator and faster os.walk()" -marker = "python_version >= \"2.7\" and python_version < \"2.8\" or python_version >= \"3.4\" and python_version < \"3.5\"" +marker = "python_version >= \"2.7\" and python_version < \"2.8\" and sys_platform != \"win32\" or python_version >= \"2.7\" and python_version < \"2.8\"" name = "scandir" optional = false python-versions = "*" @@ -1116,7 +1033,7 @@ version = "1.10.0" [[package]] category = "main" description = "Python bindings to FreeDesktop.org Secret Service API" -marker = "python_version >= \"2.7\" and python_version < \"2.8\" and (sys_platform == \"linux2\" or sys_platform == \"linux\") or python_version >= \"3.4\" and python_version < \"3.5\" and (sys_platform == \"linux2\" or sys_platform == \"linux\")" +marker = "python_version >= \"2.7\" and python_version < \"2.8\" and (sys_platform == \"linux2\" or sys_platform == \"linux\")" name = "secretstorage" optional = false python-versions = "*" @@ -1131,7 +1048,7 @@ dbus-python = ["dbus-python"] [[package]] category = "main" description = "Python bindings to FreeDesktop.org Secret Service API" -marker = "python_version >= \"3.5\" and python_version < \"4.0\" and sys_platform == \"linux\"" +marker = "python_version >= \"3.5\" and python_version < \"3.6\" and sys_platform == \"linux\" or python_version >= \"3.6\" and python_version < \"4.0\" and sys_platform == \"linux\"" name = "secretstorage" optional = false python-versions = ">=3.5" @@ -1146,8 +1063,20 @@ category = "main" description = "Tool to Detect Surrounding Shell" name = "shellingham" optional = false -python-versions = ">=2.6,!=3.0,!=3.1,!=3.2,!=3.3" -version = "1.3.1" +python-versions = "!=3.0,!=3.1,!=3.2,!=3.3,>=2.6" +version = "1.3.2" + +[[package]] +category = "main" +description = "This library brings functools.singledispatch from Python 3.4 to Python 2.6-3.3." +marker = "python_version >= \"2.7\" and python_version < \"2.8\"" +name = "singledispatch" +optional = false +python-versions = "*" +version = "3.4.0.3" + +[package.dependencies] +six = "*" [[package]] category = "main" @@ -1160,7 +1089,7 @@ version = "1.14.0" [[package]] category = "main" description = "A backport of the subprocess module from Python 3 for use on 2.x." -marker = "python_version >= \"2.7\" and python_version < \"2.8\" or python_version >= \"3.4\" and python_version < \"3.5\"" +marker = "python_version >= \"2.7\" and python_version < \"2.8\"" name = "subprocess32" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, <4" @@ -1188,7 +1117,7 @@ description = "Style preserving TOML library" name = "tomlkit" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.5.8" +version = "0.5.11" [package.dependencies] [package.dependencies.enum34] @@ -1212,43 +1141,13 @@ optional = false python-versions = ">= 2.7, !=3.0.*, !=3.1.*, !=3.2.*, != 3.3.*" version = "5.1.1" -[[package]] -category = "dev" -description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." -marker = "python_version >= \"2.7.9\" and python_version < \"2.8.0\" or python_version >= \"3.4\" and python_version < \"4.0\"" -name = "tornado" -optional = false -python-versions = ">= 3.5" -version = "6.0.3" - -[[package]] -category = "dev" -description = "tox is a generic virtualenv management and test command line tool" -name = "tox" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.12.1" - -[package.dependencies] -filelock = ">=3.0.0,<4" -pluggy = ">=0.3.0,<1" -py = ">=1.4.17,<2" -setuptools = ">=30.0.0" -six = ">=1.0.0,<2" -toml = ">=0.9.4" -virtualenv = ">=14.0.0" - -[package.extras] -docs = ["sphinx (>=2.0.0,<3)", "towncrier (>=18.5.0)", "pygments-github-lexers (>=0.0.5)", "sphinxcontrib-autoprogram (>=0.1.5)"] -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-xdist (>=1.22.2,<2)", "pytest-randomly (>=1.2.3,<2)", "flaky (>=3.4.0,<4)", "psutil (>=5.6.1,<6)"] - [[package]] category = "dev" description = "tox is a generic virtualenv management and test command line tool" name = "tox" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -version = "3.14.3" +version = "3.14.6" [package.dependencies] colorama = ">=0.4.1" @@ -1256,9 +1155,9 @@ filelock = ">=3.0.0,<4" packaging = ">=14" pluggy = ">=0.12.0,<1" py = ">=1.4.17,<2" -six = ">=1.0.0,<2" +six = ">=1.14.0,<2" toml = ">=0.9.4" -virtualenv = ">=16.0.0" +virtualenv = ">=16.0.0,<20.0.0 || >20.0.0,<20.0.1 || >20.0.1,<20.0.2 || >20.0.2,<20.0.3 || >20.0.3,<20.0.4 || >20.0.4,<20.0.5 || >20.0.5,<20.0.6 || >20.0.6,<20.0.7 || >20.0.7" [package.dependencies.importlib-metadata] python = "<3.8" @@ -1280,7 +1179,7 @@ version = "1.4.1" [[package]] category = "main" description = "Type Hints for Python" -marker = "python_version >= \"2.7\" and python_version < \"2.8\" or python_version >= \"3.4\" and python_version < \"3.5\" or python_version < \"3.5\"" +marker = "python_version >= \"2.7\" and python_version < \"2.8\" or python_version >= \"3.4\" and python_version < \"3.5\"" name = "typing" optional = false python-versions = "*" @@ -1288,15 +1187,12 @@ version = "3.7.4.1" [[package]] category = "main" -description = "HTTP library with thread-safe connection pooling, file post, and more." -name = "urllib3" +description = "Backported and Experimental Type Hints for Python 3.5+" +marker = "python_version >= \"3.5.0\" and python_version < \"3.5.4\"" +name = "typing-extensions" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4" -version = "1.24.3" - -[package.extras] -secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] -socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] +python-versions = "*" +version = "3.7.4.2" [[package]] category = "main" @@ -1304,11 +1200,11 @@ description = "HTTP library with thread-safe connection pooling, file post, and name = "urllib3" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" -version = "1.25.8" +version = "1.25.9" [package.extras] brotli = ["brotlipy (>=0.6.0)"] -secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)", "ipaddress"] socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] [[package]] @@ -1317,11 +1213,33 @@ description = "Virtual Python Environment builder" name = "virtualenv" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -version = "16.7.9" +version = "20.0.18" + +[package.dependencies] +appdirs = ">=1.4.3,<2" +distlib = ">=0.3.0,<1" +filelock = ">=3.0.0,<4" +six = ">=1.9.0,<2" + +[package.dependencies.contextlib2] +python = "<3.3" +version = ">=0.6.0,<1" + +[package.dependencies.importlib-metadata] +python = "<3.8" +version = ">=0.12,<2" + +[package.dependencies.importlib-resources] +python = "<3.7" +version = ">=1.0,<2" + +[package.dependencies.pathlib2] +python = "<3.4" +version = ">=2.3.3,<3" [package.extras] -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)", "pytest-timeout (>=1.3.0,<2)", "six (>=1.10.0,<2)", "pytest-xdist", "pytest-localserver", "pypiserver", "mock", "xonsh"] +docs = ["sphinx (>=2.0.0,<3)", "sphinx-argparse (>=0.2.5,<1)", "sphinx-rtd-theme (>=0.4.3,<1)", "towncrier (>=19.9.0rc1)", "proselint (>=0.10.2,<1)"] +testing = ["pytest (>=4.0.0,<6)", "coverage (>=4.5.1,<6)", "pytest-mock (>=2.0.0,<3)", "pytest-env (>=0.6.2,<1)", "pytest-timeout (>=1.3.4,<2)", "packaging (>=20.0)", "xonsh (>=0.9.16,<1)"] [[package]] category = "dev" @@ -1329,7 +1247,7 @@ description = "Measures number of Terminal column cells of wide-character codes" name = "wcwidth" optional = false python-versions = "*" -version = "0.1.8" +version = "0.1.9" [[package]] category = "main" @@ -1339,14 +1257,23 @@ optional = false python-versions = "*" version = "0.5.1" +[[package]] +category = "main" +description = "Handle and manage Python errors with ease" +marker = "python_version >= \"3.6\" and python_version < \"4.0\"" +name = "woops" +optional = false +python-versions = ">=3.6,<4.0" +version = "0.2.1" + [[package]] category = "main" description = "Backport of pathlib-compatible object wrapper for zip files" -marker = "python_version >= \"3.5\" and python_version < \"3.8\" or python_version < \"3.8\"" +marker = "python_version >= \"2.7\" and python_version < \"2.8\" or python_version < \"3.8\" or python_version >= \"3.5\" and python_version < \"3.6\" or python_version >= \"3.6\" and python_version < \"3.8\"" name = "zipp" optional = false python-versions = ">=2.7" -version = "1.1.0" +version = "1.2.0" [package.dependencies] [package.dependencies.contextlib2] @@ -1355,11 +1282,11 @@ version = "*" [package.extras] docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] -testing = ["pathlib2", "unittest2", "jaraco.itertools"] +testing = ["pathlib2", "unittest2", "jaraco.itertools", "func-timeout"] [metadata] -content-hash = "e0b632d8363fdf9f70d93901ff537714611bfc31705a897f6d2fb3bc010bca0a" -python-versions = "~2.7 || ^3.4" +content-hash = "a451c3dc97c7797be12c637b9827087489eddd2e181946ef95c5f2a4bd710fb8" +python-versions = "~2.7 || ^3.5" [metadata.files] appdirs = [ @@ -1391,43 +1318,38 @@ cachy = [ {file = "cachy-0.3.0.tar.gz", hash = "sha256:186581f4ceb42a0bbe040c407da73c14092379b1e4c0e327fdb72ae4a9b269b1"}, ] certifi = [ - {file = "certifi-2019.11.28-py2.py3-none-any.whl", hash = "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3"}, - {file = "certifi-2019.11.28.tar.gz", hash = "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"}, + {file = "certifi-2020.4.5.1-py2.py3-none-any.whl", hash = "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304"}, + {file = "certifi-2020.4.5.1.tar.gz", hash = "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519"}, ] cffi = [ - {file = "cffi-1.13.2-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:3c9fff570f13480b201e9ab69453108f6d98244a7f495e91b6c654a47486ba43"}, - {file = "cffi-1.13.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:2c5e309ec482556397cb21ede0350c5e82f0eb2621de04b2633588d118da4396"}, - {file = "cffi-1.13.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:19db0cdd6e516f13329cba4903368bff9bb5a9331d3410b1b448daaadc495e54"}, - {file = "cffi-1.13.2-cp27-cp27m-win32.whl", hash = "sha256:5c4fae4e9cdd18c82ba3a134be256e98dc0596af1e7285a3d2602c97dcfa5159"}, - {file = "cffi-1.13.2-cp27-cp27m-win_amd64.whl", hash = "sha256:32a262e2b90ffcfdd97c7a5e24a6012a43c61f1f5a57789ad80af1d26c6acd97"}, - {file = "cffi-1.13.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:4a43c91840bda5f55249413037b7a9b79c90b1184ed504883b72c4df70778579"}, - {file = "cffi-1.13.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:8169cf44dd8f9071b2b9248c35fc35e8677451c52f795daa2bb4643f32a540bc"}, - {file = "cffi-1.13.2-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:71a608532ab3bd26223c8d841dde43f3516aa5d2bf37b50ac410bb5e99053e8f"}, - {file = "cffi-1.13.2-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:7f627141a26b551bdebbc4855c1157feeef18241b4b8366ed22a5c7d672ef858"}, - {file = "cffi-1.13.2-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:0b49274afc941c626b605fb59b59c3485c17dc776dc3cc7cc14aca74cc19cc42"}, - {file = "cffi-1.13.2-cp34-cp34m-win32.whl", hash = "sha256:4424e42199e86b21fc4db83bd76909a6fc2a2aefb352cb5414833c030f6ed71b"}, - {file = "cffi-1.13.2-cp34-cp34m-win_amd64.whl", hash = "sha256:7d4751da932caaec419d514eaa4215eaf14b612cff66398dd51129ac22680b20"}, - {file = "cffi-1.13.2-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:ccb032fda0873254380aa2bfad2582aedc2959186cce61e3a17abc1a55ff89c3"}, - {file = "cffi-1.13.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:dcd65317dd15bc0451f3e01c80da2216a31916bdcffd6221ca1202d96584aa25"}, - {file = "cffi-1.13.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:135f69aecbf4517d5b3d6429207b2dff49c876be724ac0c8bf8e1ea99df3d7e5"}, - {file = "cffi-1.13.2-cp35-cp35m-win32.whl", hash = "sha256:7b93a885bb13073afb0aa73ad82059a4c41f4b7d8eb8368980448b52d4c7dc2c"}, - {file = "cffi-1.13.2-cp35-cp35m-win_amd64.whl", hash = "sha256:e570d3ab32e2c2861c4ebe6ffcad6a8abf9347432a37608fe1fbd157b3f0036b"}, - {file = "cffi-1.13.2-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:0e3ea92942cb1168e38c05c1d56b0527ce31f1a370f6117f1d490b8dcd6b3a04"}, - {file = "cffi-1.13.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5ecfa867dea6fabe2a58f03ac9186ea64da1386af2159196da51c4904e11d652"}, - {file = "cffi-1.13.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:291f7c42e21d72144bb1c1b2e825ec60f46d0a7468f5346841860454c7aa8f57"}, - {file = "cffi-1.13.2-cp36-cp36m-win32.whl", hash = "sha256:62f2578358d3a92e4ab2d830cd1c2049c9c0d0e6d3c58322993cc341bdeac22e"}, - {file = "cffi-1.13.2-cp36-cp36m-win_amd64.whl", hash = "sha256:fd43a88e045cf992ed09fa724b5315b790525f2676883a6ea64e3263bae6549d"}, - {file = "cffi-1.13.2-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:d75c461e20e29afc0aee7172a0950157c704ff0dd51613506bd7d82b718e7410"}, - {file = "cffi-1.13.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:aa00d66c0fab27373ae44ae26a66a9e43ff2a678bf63a9c7c1a9a4d61172827a"}, - {file = "cffi-1.13.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:2e9c80a8c3344a92cb04661115898a9129c074f7ab82011ef4b612f645939f12"}, - {file = "cffi-1.13.2-cp37-cp37m-win32.whl", hash = "sha256:d754f39e0d1603b5b24a7f8484b22d2904fa551fe865fd0d4c3332f078d20d4e"}, - {file = "cffi-1.13.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6471a82d5abea994e38d2c2abc77164b4f7fbaaf80261cb98394d5793f11b12a"}, - {file = "cffi-1.13.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:74a1d8c85fb6ff0b30fbfa8ad0ac23cd601a138f7509dc617ebc65ef305bb98d"}, - {file = "cffi-1.13.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:42194f54c11abc8583417a7cf4eaff544ce0de8187abaf5d29029c91b1725ad3"}, - {file = "cffi-1.13.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:415bdc7ca8c1c634a6d7163d43fb0ea885a07e9618a64bda407e04b04333b7db"}, - {file = "cffi-1.13.2-cp38-cp38-win32.whl", hash = "sha256:6d4f18483d040e18546108eb13b1dfa1000a089bcf8529e30346116ea6240506"}, - {file = "cffi-1.13.2-cp38-cp38-win_amd64.whl", hash = "sha256:2781e9ad0e9d47173c0093321bb5435a9dfae0ed6a762aabafa13108f5f7b2ba"}, - {file = "cffi-1.13.2.tar.gz", hash = "sha256:599a1e8ff057ac530c9ad1778293c665cb81a791421f46922d80a86473c13346"}, + {file = "cffi-1.14.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384"}, + {file = "cffi-1.14.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30"}, + {file = "cffi-1.14.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:f2b0fa0c01d8a0c7483afd9f31d7ecf2d71760ca24499c8697aeb5ca37dc090c"}, + {file = "cffi-1.14.0-cp27-cp27m-win32.whl", hash = "sha256:99f748a7e71ff382613b4e1acc0ac83bf7ad167fb3802e35e90d9763daba4d78"}, + {file = "cffi-1.14.0-cp27-cp27m-win_amd64.whl", hash = "sha256:c420917b188a5582a56d8b93bdd8e0f6eca08c84ff623a4c16e809152cd35793"}, + {file = "cffi-1.14.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:399aed636c7d3749bbed55bc907c3288cb43c65c4389964ad5ff849b6370603e"}, + {file = "cffi-1.14.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:cab50b8c2250b46fe738c77dbd25ce017d5e6fb35d3407606e7a4180656a5a6a"}, + {file = "cffi-1.14.0-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:001bf3242a1bb04d985d63e138230802c6c8d4db3668fb545fb5005ddf5bb5ff"}, + {file = "cffi-1.14.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:e56c744aa6ff427a607763346e4170629caf7e48ead6921745986db3692f987f"}, + {file = "cffi-1.14.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b8c78301cefcf5fd914aad35d3c04c2b21ce8629b5e4f4e45ae6812e461910fa"}, + {file = "cffi-1.14.0-cp35-cp35m-win32.whl", hash = "sha256:8c0ffc886aea5df6a1762d0019e9cb05f825d0eec1f520c51be9d198701daee5"}, + {file = "cffi-1.14.0-cp35-cp35m-win_amd64.whl", hash = "sha256:8a6c688fefb4e1cd56feb6c511984a6c4f7ec7d2a1ff31a10254f3c817054ae4"}, + {file = "cffi-1.14.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:95cd16d3dee553f882540c1ffe331d085c9e629499ceadfbda4d4fde635f4b7d"}, + {file = "cffi-1.14.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:66e41db66b47d0d8672d8ed2708ba91b2f2524ece3dee48b5dfb36be8c2f21dc"}, + {file = "cffi-1.14.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:028a579fc9aed3af38f4892bdcc7390508adabc30c6af4a6e4f611b0c680e6ac"}, + {file = "cffi-1.14.0-cp36-cp36m-win32.whl", hash = "sha256:cef128cb4d5e0b3493f058f10ce32365972c554572ff821e175dbc6f8ff6924f"}, + {file = "cffi-1.14.0-cp36-cp36m-win_amd64.whl", hash = "sha256:337d448e5a725bba2d8293c48d9353fc68d0e9e4088d62a9571def317797522b"}, + {file = "cffi-1.14.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3"}, + {file = "cffi-1.14.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66"}, + {file = "cffi-1.14.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0"}, + {file = "cffi-1.14.0-cp37-cp37m-win32.whl", hash = "sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f"}, + {file = "cffi-1.14.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26"}, + {file = "cffi-1.14.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3b911c2dbd4f423b4c4fcca138cadde747abdb20d196c4a48708b8a2d32b16dd"}, + {file = "cffi-1.14.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:7e63cbcf2429a8dbfe48dcc2322d5f2220b77b2e17b7ba023d6166d84655da55"}, + {file = "cffi-1.14.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:3d311bcc4a41408cf5854f06ef2c5cab88f9fded37a3b95936c9879c1640d4c2"}, + {file = "cffi-1.14.0-cp38-cp38-win32.whl", hash = "sha256:675686925a9fb403edba0114db74e741d8181683dcf216be697d208857e04ca8"}, + {file = "cffi-1.14.0-cp38-cp38-win_amd64.whl", hash = "sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b"}, + {file = "cffi-1.14.0.tar.gz", hash = "sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6"}, ] cfgv = [ {file = "cfgv-2.0.1-py2.py3-none-any.whl", hash = "sha256:fbd93c9ab0a523bf7daec408f3be2ed99a980e20b2d19b50fc184ca6b820d289"}, @@ -1438,20 +1360,18 @@ chardet = [ {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, ] cleo = [ - {file = "cleo-0.7.6-py2.py3-none-any.whl", hash = "sha256:9443d67e5b2da79b32d820ae41758dd6a25618345cb10b9a022a695e26b291b9"}, - {file = "cleo-0.7.6.tar.gz", hash = "sha256:99cf342406f3499cec43270fcfaf93c126c5164092eca201dfef0f623360b409"}, + {file = "cleo-0.8.0-py2.py3-none-any.whl", hash = "sha256:dcb791b246c02d59ea8eaf05a05d986e547dbe8ba2496ed59048e5d4ab93b537"}, + {file = "cleo-0.8.0.tar.gz", hash = "sha256:b2d56e93b182358591d0ec46c4f787736378a6a8adf4a6512f72aeb0506de981"}, ] click = [ - {file = "Click-7.0-py2.py3-none-any.whl", hash = "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13"}, - {file = "Click-7.0.tar.gz", hash = "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"}, + {file = "click-7.1.1-py2.py3-none-any.whl", hash = "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"}, + {file = "click-7.1.1.tar.gz", hash = "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc"}, ] clikit = [ - {file = "clikit-0.4.1-py2.py3-none-any.whl", hash = "sha256:80b0bfee42310a715773dded69590c4c33fa9fc9a351fa7c262cb67f21d0758f"}, - {file = "clikit-0.4.1.tar.gz", hash = "sha256:8ae4766b974d7b1983e39d501da9a0aadf118a907a0c9b50714d027c8b59ea81"}, + {file = "clikit-0.5.1-py2.py3-none-any.whl", hash = "sha256:f697b6e3125cf4bdc6394184c687f52fe3323152ca6bb99db444201f32904a64"}, + {file = "clikit-0.5.1.tar.gz", hash = "sha256:2e9cd4c87539d9a0f0275b26e3e50d2d531d7bfbcf4f91909aaa013cfac9d0e1"}, ] colorama = [ - {file = "colorama-0.4.1-py2.py3-none-any.whl", hash = "sha256:f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"}, - {file = "colorama-0.4.1.tar.gz", hash = "sha256:05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d"}, {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"}, {file = "colorama-0.4.3.tar.gz", hash = "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"}, ] @@ -1464,102 +1384,70 @@ contextlib2 = [ {file = "contextlib2-0.6.0.post1.tar.gz", hash = "sha256:01f490098c18b19d2bd5bb5dc445b2054d2fa97f09a4280ba2c5f3c394c8162e"}, ] coverage = [ - {file = "coverage-4.5.4-cp26-cp26m-macosx_10_12_x86_64.whl", hash = "sha256:eee64c616adeff7db37cc37da4180a3a5b6177f5c46b187894e633f088fb5b28"}, - {file = "coverage-4.5.4-cp27-cp27m-macosx_10_12_x86_64.whl", hash = "sha256:ef824cad1f980d27f26166f86856efe11eff9912c4fed97d3804820d43fa550c"}, - {file = "coverage-4.5.4-cp27-cp27m-macosx_10_13_intel.whl", hash = "sha256:9a334d6c83dfeadae576b4d633a71620d40d1c379129d587faa42ee3e2a85cce"}, - {file = "coverage-4.5.4-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:7494b0b0274c5072bddbfd5b4a6c6f18fbbe1ab1d22a41e99cd2d00c8f96ecfe"}, - {file = "coverage-4.5.4-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:826f32b9547c8091679ff292a82aca9c7b9650f9fda3e2ca6bf2ac905b7ce888"}, - {file = "coverage-4.5.4-cp27-cp27m-win32.whl", hash = "sha256:63a9a5fc43b58735f65ed63d2cf43508f462dc49857da70b8980ad78d41d52fc"}, - {file = "coverage-4.5.4-cp27-cp27m-win_amd64.whl", hash = "sha256:e2ede7c1d45e65e209d6093b762e98e8318ddeff95317d07a27a2140b80cfd24"}, - {file = "coverage-4.5.4-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:dd579709a87092c6dbee09d1b7cfa81831040705ffa12a1b248935274aee0437"}, - {file = "coverage-4.5.4-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:08907593569fe59baca0bf152c43f3863201efb6113ecb38ce7e97ce339805a6"}, - {file = "coverage-4.5.4-cp33-cp33m-macosx_10_10_x86_64.whl", hash = "sha256:6b62544bb68106e3f00b21c8930e83e584fdca005d4fffd29bb39fb3ffa03cb5"}, - {file = "coverage-4.5.4-cp34-cp34m-macosx_10_12_x86_64.whl", hash = "sha256:331cb5115673a20fb131dadd22f5bcaf7677ef758741312bee4937d71a14b2ef"}, - {file = "coverage-4.5.4-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:bf1ef9eb901113a9805287e090452c05547578eaab1b62e4ad456fcc049a9b7e"}, - {file = "coverage-4.5.4-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:386e2e4090f0bc5df274e720105c342263423e77ee8826002dcffe0c9533dbca"}, - {file = "coverage-4.5.4-cp34-cp34m-win32.whl", hash = "sha256:fa964bae817babece5aa2e8c1af841bebb6d0b9add8e637548809d040443fee0"}, - {file = "coverage-4.5.4-cp34-cp34m-win_amd64.whl", hash = "sha256:df6712284b2e44a065097846488f66840445eb987eb81b3cc6e4149e7b6982e1"}, - {file = "coverage-4.5.4-cp35-cp35m-macosx_10_12_x86_64.whl", hash = "sha256:efc89291bd5a08855829a3c522df16d856455297cf35ae827a37edac45f466a7"}, - {file = "coverage-4.5.4-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:e4ef9c164eb55123c62411f5936b5c2e521b12356037b6e1c2617cef45523d47"}, - {file = "coverage-4.5.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:ff37757e068ae606659c28c3bd0d923f9d29a85de79bf25b2b34b148473b5025"}, - {file = "coverage-4.5.4-cp35-cp35m-win32.whl", hash = "sha256:bf0a7aed7f5521c7ca67febd57db473af4762b9622254291fbcbb8cd0ba5e33e"}, - {file = "coverage-4.5.4-cp35-cp35m-win_amd64.whl", hash = "sha256:19e4df788a0581238e9390c85a7a09af39c7b539b29f25c89209e6c3e371270d"}, - {file = "coverage-4.5.4-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:60851187677b24c6085248f0a0b9b98d49cba7ecc7ec60ba6b9d2e5574ac1ee9"}, - {file = "coverage-4.5.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:245388cda02af78276b479f299bbf3783ef0a6a6273037d7c60dc73b8d8d7755"}, - {file = "coverage-4.5.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c0afd27bc0e307a1ffc04ca5ec010a290e49e3afbe841c5cafc5c5a80ecd81c9"}, - {file = "coverage-4.5.4-cp36-cp36m-win32.whl", hash = "sha256:6ba744056423ef8d450cf627289166da65903885272055fb4b5e113137cfa14f"}, - {file = "coverage-4.5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:af7ed8a8aa6957aac47b4268631fa1df984643f07ef00acd374e456364b373f5"}, - {file = "coverage-4.5.4-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:3a794ce50daee01c74a494919d5ebdc23d58873747fa0e288318728533a3e1ca"}, - {file = "coverage-4.5.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:0be0f1ed45fc0c185cfd4ecc19a1d6532d72f86a2bac9de7e24541febad72650"}, - {file = "coverage-4.5.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:eca2b7343524e7ba246cab8ff00cab47a2d6d54ada3b02772e908a45675722e2"}, - {file = "coverage-4.5.4-cp37-cp37m-win32.whl", hash = "sha256:93715dffbcd0678057f947f496484e906bf9509f5c1c38fc9ba3922893cda5f5"}, - {file = "coverage-4.5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:23cc09ed395b03424d1ae30dcc292615c1372bfba7141eb85e11e50efaa6b351"}, - {file = "coverage-4.5.4-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:141f08ed3c4b1847015e2cd62ec06d35e67a3ac185c26f7635f4406b90afa9c5"}, - {file = "coverage-4.5.4.tar.gz", hash = "sha256:e07d9f1a23e9e93ab5c62902833bf3e4b1f65502927379148b6622686223125c"}, - {file = "coverage-5.0.3-cp27-cp27m-macosx_10_12_x86_64.whl", hash = "sha256:cc1109f54a14d940b8512ee9f1c3975c181bbb200306c6d8b87d93376538782f"}, - {file = "coverage-5.0.3-cp27-cp27m-macosx_10_13_intel.whl", hash = "sha256:be18f4ae5a9e46edae3f329de2191747966a34a3d93046dbdf897319923923bc"}, - {file = "coverage-5.0.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:3230d1003eec018ad4a472d254991e34241e0bbd513e97a29727c7c2f637bd2a"}, - {file = "coverage-5.0.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:e69215621707119c6baf99bda014a45b999d37602cb7043d943c76a59b05bf52"}, - {file = "coverage-5.0.3-cp27-cp27m-win32.whl", hash = "sha256:1daa3eceed220f9fdb80d5ff950dd95112cd27f70d004c7918ca6dfc6c47054c"}, - {file = "coverage-5.0.3-cp27-cp27m-win_amd64.whl", hash = "sha256:51bc7710b13a2ae0c726f69756cf7ffd4362f4ac36546e243136187cfcc8aa73"}, - {file = "coverage-5.0.3-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:9bea19ac2f08672636350f203db89382121c9c2ade85d945953ef3c8cf9d2a68"}, - {file = "coverage-5.0.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:5012d3b8d5a500834783689a5d2292fe06ec75dc86ee1ccdad04b6f5bf231691"}, - {file = "coverage-5.0.3-cp35-cp35m-macosx_10_12_x86_64.whl", hash = "sha256:d513cc3db248e566e07a0da99c230aca3556d9b09ed02f420664e2da97eac301"}, - {file = "coverage-5.0.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:3dbb72eaeea5763676a1a1efd9b427a048c97c39ed92e13336e726117d0b72bf"}, - {file = "coverage-5.0.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:15cf13a6896048d6d947bf7d222f36e4809ab926894beb748fc9caa14605d9c3"}, - {file = "coverage-5.0.3-cp35-cp35m-win32.whl", hash = "sha256:fca1669d464f0c9831fd10be2eef6b86f5ebd76c724d1e0706ebdff86bb4adf0"}, - {file = "coverage-5.0.3-cp35-cp35m-win_amd64.whl", hash = "sha256:1e44a022500d944d42f94df76727ba3fc0a5c0b672c358b61067abb88caee7a0"}, - {file = "coverage-5.0.3-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:b26aaf69713e5674efbde4d728fb7124e429c9466aeaf5f4a7e9e699b12c9fe2"}, - {file = "coverage-5.0.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:722e4557c8039aad9592c6a4213db75da08c2cd9945320220634f637251c3894"}, - {file = "coverage-5.0.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:7afad9835e7a651d3551eab18cbc0fdb888f0a6136169fbef0662d9cdc9987cf"}, - {file = "coverage-5.0.3-cp36-cp36m-win32.whl", hash = "sha256:25dbf1110d70bab68a74b4b9d74f30e99b177cde3388e07cc7272f2168bd1477"}, - {file = "coverage-5.0.3-cp36-cp36m-win_amd64.whl", hash = "sha256:c312e57847db2526bc92b9bfa78266bfbaabac3fdcd751df4d062cd4c23e46dc"}, - {file = "coverage-5.0.3-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:a8b8ac7876bc3598e43e2603f772d2353d9931709345ad6c1149009fd1bc81b8"}, - {file = "coverage-5.0.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:527b4f316e6bf7755082a783726da20671a0cc388b786a64417780b90565b987"}, - {file = "coverage-5.0.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d649dc0bcace6fcdb446ae02b98798a856593b19b637c1b9af8edadf2b150bea"}, - {file = "coverage-5.0.3-cp37-cp37m-win32.whl", hash = "sha256:cd60f507c125ac0ad83f05803063bed27e50fa903b9c2cfee3f8a6867ca600fc"}, - {file = "coverage-5.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c60097190fe9dc2b329a0eb03393e2e0829156a589bd732e70794c0dd804258e"}, - {file = "coverage-5.0.3-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:d7008a6796095a79544f4da1ee49418901961c97ca9e9d44904205ff7d6aa8cb"}, - {file = "coverage-5.0.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:ea9525e0fef2de9208250d6c5aeeee0138921057cd67fcef90fbed49c4d62d37"}, - {file = "coverage-5.0.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:c62a2143e1313944bf4a5ab34fd3b4be15367a02e9478b0ce800cb510e3bbb9d"}, - {file = "coverage-5.0.3-cp38-cp38m-win32.whl", hash = "sha256:b0840b45187699affd4c6588286d429cd79a99d509fe3de0f209594669bb0954"}, - {file = "coverage-5.0.3-cp38-cp38m-win_amd64.whl", hash = "sha256:76e2057e8ffba5472fd28a3a010431fd9e928885ff480cb278877c6e9943cc2e"}, - {file = "coverage-5.0.3-cp39-cp39m-win32.whl", hash = "sha256:b63dd43f455ba878e5e9f80ba4f748c0a2156dde6e0e6e690310e24d6e8caf40"}, - {file = "coverage-5.0.3-cp39-cp39m-win_amd64.whl", hash = "sha256:da93027835164b8223e8e5af2cf902a4c80ed93cb0909417234f4a9df3bcd9af"}, - {file = "coverage-5.0.3.tar.gz", hash = "sha256:77afca04240c40450c331fa796b3eab6f1e15c5ecf8bf2b8bee9706cd5452fef"}, + {file = "coverage-5.1-cp27-cp27m-macosx_10_12_x86_64.whl", hash = "sha256:0cb4be7e784dcdc050fc58ef05b71aa8e89b7e6636b99967fadbdba694cf2b65"}, + {file = "coverage-5.1-cp27-cp27m-macosx_10_13_intel.whl", hash = "sha256:c317eaf5ff46a34305b202e73404f55f7389ef834b8dbf4da09b9b9b37f76dd2"}, + {file = "coverage-5.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:b83835506dfc185a319031cf853fa4bb1b3974b1f913f5bb1a0f3d98bdcded04"}, + {file = "coverage-5.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5f2294dbf7875b991c381e3d5af2bcc3494d836affa52b809c91697449d0eda6"}, + {file = "coverage-5.1-cp27-cp27m-win32.whl", hash = "sha256:de807ae933cfb7f0c7d9d981a053772452217df2bf38e7e6267c9cbf9545a796"}, + {file = "coverage-5.1-cp27-cp27m-win_amd64.whl", hash = "sha256:bf9cb9a9fd8891e7efd2d44deb24b86d647394b9705b744ff6f8261e6f29a730"}, + {file = "coverage-5.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:acf3763ed01af8410fc36afea23707d4ea58ba7e86a8ee915dfb9ceff9ef69d0"}, + {file = "coverage-5.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:dec5202bfe6f672d4511086e125db035a52b00f1648d6407cc8e526912c0353a"}, + {file = "coverage-5.1-cp35-cp35m-macosx_10_12_x86_64.whl", hash = "sha256:7a5bdad4edec57b5fb8dae7d3ee58622d626fd3a0be0dfceda162a7035885ecf"}, + {file = "coverage-5.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:1601e480b9b99697a570cea7ef749e88123c04b92d84cedaa01e117436b4a0a9"}, + {file = "coverage-5.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:dbe8c6ae7534b5b024296464f387d57c13caa942f6d8e6e0346f27e509f0f768"}, + {file = "coverage-5.1-cp35-cp35m-win32.whl", hash = "sha256:a027ef0492ede1e03a8054e3c37b8def89a1e3c471482e9f046906ba4f2aafd2"}, + {file = "coverage-5.1-cp35-cp35m-win_amd64.whl", hash = "sha256:0e61d9803d5851849c24f78227939c701ced6704f337cad0a91e0972c51c1ee7"}, + {file = "coverage-5.1-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:2d27a3f742c98e5c6b461ee6ef7287400a1956c11421eb574d843d9ec1f772f0"}, + {file = "coverage-5.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:66460ab1599d3cf894bb6baee8c684788819b71a5dc1e8fa2ecc152e5d752019"}, + {file = "coverage-5.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5c542d1e62eece33c306d66fe0a5c4f7f7b3c08fecc46ead86d7916684b36d6c"}, + {file = "coverage-5.1-cp36-cp36m-win32.whl", hash = "sha256:2742c7515b9eb368718cd091bad1a1b44135cc72468c731302b3d641895b83d1"}, + {file = "coverage-5.1-cp36-cp36m-win_amd64.whl", hash = "sha256:dead2ddede4c7ba6cb3a721870f5141c97dc7d85a079edb4bd8d88c3ad5b20c7"}, + {file = "coverage-5.1-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:01333e1bd22c59713ba8a79f088b3955946e293114479bbfc2e37d522be03355"}, + {file = "coverage-5.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:e1ea316102ea1e1770724db01998d1603ed921c54a86a2efcb03428d5417e489"}, + {file = "coverage-5.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:adeb4c5b608574a3d647011af36f7586811a2c1197c861aedb548dd2453b41cd"}, + {file = "coverage-5.1-cp37-cp37m-win32.whl", hash = "sha256:782caea581a6e9ff75eccda79287daefd1d2631cc09d642b6ee2d6da21fc0a4e"}, + {file = "coverage-5.1-cp37-cp37m-win_amd64.whl", hash = "sha256:00f1d23f4336efc3b311ed0d807feb45098fc86dee1ca13b3d6768cdab187c8a"}, + {file = "coverage-5.1-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:402e1744733df483b93abbf209283898e9f0d67470707e3c7516d84f48524f55"}, + {file = "coverage-5.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:a3f3654d5734a3ece152636aad89f58afc9213c6520062db3978239db122f03c"}, + {file = "coverage-5.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6402bd2fdedabbdb63a316308142597534ea8e1895f4e7d8bf7476c5e8751fef"}, + {file = "coverage-5.1-cp38-cp38-win32.whl", hash = "sha256:8fa0cbc7ecad630e5b0f4f35b0f6ad419246b02bc750de7ac66db92667996d24"}, + {file = "coverage-5.1-cp38-cp38-win_amd64.whl", hash = "sha256:79a3cfd6346ce6c13145731d39db47b7a7b859c0272f02cdb89a3bdcbae233a0"}, + {file = "coverage-5.1-cp39-cp39-win32.whl", hash = "sha256:a82b92b04a23d3c8a581fc049228bafde988abacba397d57ce95fe95e0338ab4"}, + {file = "coverage-5.1-cp39-cp39-win_amd64.whl", hash = "sha256:bb28a7245de68bf29f6fb199545d072d1036a1917dca17a1e75bbb919e14ee8e"}, + {file = "coverage-5.1.tar.gz", hash = "sha256:f90bfc4ad18450c80b024036eaf91e4a246ae287701aaa88eaebebf150868052"}, ] cryptography = [ - {file = "cryptography-2.8-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:fb81c17e0ebe3358486cd8cc3ad78adbae58af12fc2bf2bc0bb84e8090fa5ce8"}, - {file = "cryptography-2.8-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:44ff04138935882fef7c686878e1c8fd80a723161ad6a98da31e14b7553170c2"}, - {file = "cryptography-2.8-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:369d2346db5934345787451504853ad9d342d7f721ae82d098083e1f49a582ad"}, - {file = "cryptography-2.8-cp27-cp27m-win32.whl", hash = "sha256:df6b4dca2e11865e6cfbfb708e800efb18370f5a46fd601d3755bc7f85b3a8a2"}, - {file = "cryptography-2.8-cp27-cp27m-win_amd64.whl", hash = "sha256:7f09806ed4fbea8f51585231ba742b58cbcfbfe823ea197d8c89a5e433c7e912"}, - {file = "cryptography-2.8-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:58363dbd966afb4f89b3b11dfb8ff200058fbc3b947507675c19ceb46104b48d"}, - {file = "cryptography-2.8-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:6ec280fb24d27e3d97aa731e16207d58bd8ae94ef6eab97249a2afe4ba643d42"}, - {file = "cryptography-2.8-cp34-abi3-macosx_10_6_intel.whl", hash = "sha256:b43f53f29816ba1db8525f006fa6f49292e9b029554b3eb56a189a70f2a40879"}, - {file = "cryptography-2.8-cp34-abi3-manylinux1_x86_64.whl", hash = "sha256:7270a6c29199adc1297776937a05b59720e8a782531f1f122f2eb8467f9aab4d"}, - {file = "cryptography-2.8-cp34-abi3-manylinux2010_x86_64.whl", hash = "sha256:de96157ec73458a7f14e3d26f17f8128c959084931e8997b9e655a39c8fde9f9"}, - {file = "cryptography-2.8-cp34-cp34m-win32.whl", hash = "sha256:02079a6addc7b5140ba0825f542c0869ff4df9a69c360e339ecead5baefa843c"}, - {file = "cryptography-2.8-cp34-cp34m-win_amd64.whl", hash = "sha256:b0de590a8b0979649ebeef8bb9f54394d3a41f66c5584fff4220901739b6b2f0"}, - {file = "cryptography-2.8-cp35-cp35m-win32.whl", hash = "sha256:ecadccc7ba52193963c0475ac9f6fa28ac01e01349a2ca48509667ef41ffd2cf"}, - {file = "cryptography-2.8-cp35-cp35m-win_amd64.whl", hash = "sha256:90df0cc93e1f8d2fba8365fb59a858f51a11a394d64dbf3ef844f783844cc793"}, - {file = "cryptography-2.8-cp36-cp36m-win32.whl", hash = "sha256:1df22371fbf2004c6f64e927668734070a8953362cd8370ddd336774d6743595"}, - {file = "cryptography-2.8-cp36-cp36m-win_amd64.whl", hash = "sha256:a518c153a2b5ed6b8cc03f7ae79d5ffad7315ad4569b2d5333a13c38d64bd8d7"}, - {file = "cryptography-2.8-cp37-cp37m-win32.whl", hash = "sha256:4b1030728872c59687badcca1e225a9103440e467c17d6d1730ab3d2d64bfeff"}, - {file = "cryptography-2.8-cp37-cp37m-win_amd64.whl", hash = "sha256:d31402aad60ed889c7e57934a03477b572a03af7794fa8fb1780f21ea8f6551f"}, - {file = "cryptography-2.8-cp38-cp38-win32.whl", hash = "sha256:73fd30c57fa2d0a1d7a49c561c40c2f79c7d6c374cc7750e9ac7c99176f6428e"}, - {file = "cryptography-2.8-cp38-cp38-win_amd64.whl", hash = "sha256:971221ed40f058f5662a604bd1ae6e4521d84e6cad0b7b170564cc34169c8f13"}, - {file = "cryptography-2.8.tar.gz", hash = "sha256:3cda1f0ed8747339bbdf71b9f38ca74c7b592f24f65cdb3ab3765e4b02871651"}, + {file = "cryptography-2.9.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:daf54a4b07d67ad437ff239c8a4080cfd1cc7213df57d33c97de7b4738048d5e"}, + {file = "cryptography-2.9.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:3b3eba865ea2754738616f87292b7f29448aec342a7c720956f8083d252bf28b"}, + {file = "cryptography-2.9.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:c447cf087cf2dbddc1add6987bbe2f767ed5317adb2d08af940db517dd704365"}, + {file = "cryptography-2.9.2-cp27-cp27m-win32.whl", hash = "sha256:f118a95c7480f5be0df8afeb9a11bd199aa20afab7a96bcf20409b411a3a85f0"}, + {file = "cryptography-2.9.2-cp27-cp27m-win_amd64.whl", hash = "sha256:c4fd17d92e9d55b84707f4fd09992081ba872d1a0c610c109c18e062e06a2e55"}, + {file = "cryptography-2.9.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d0d5aeaedd29be304848f1c5059074a740fa9f6f26b84c5b63e8b29e73dfc270"}, + {file = "cryptography-2.9.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:1e4014639d3d73fbc5ceff206049c5a9a849cefd106a49fa7aaaa25cc0ce35cf"}, + {file = "cryptography-2.9.2-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:96c080ae7118c10fcbe6229ab43eb8b090fccd31a09ef55f83f690d1ef619a1d"}, + {file = "cryptography-2.9.2-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:e993468c859d084d5579e2ebee101de8f5a27ce8e2159959b6673b418fd8c785"}, + {file = "cryptography-2.9.2-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:88c881dd5a147e08d1bdcf2315c04972381d026cdb803325c03fe2b4a8ed858b"}, + {file = "cryptography-2.9.2-cp35-cp35m-win32.whl", hash = "sha256:651448cd2e3a6bc2bb76c3663785133c40d5e1a8c1a9c5429e4354201c6024ae"}, + {file = "cryptography-2.9.2-cp35-cp35m-win_amd64.whl", hash = "sha256:726086c17f94747cedbee6efa77e99ae170caebeb1116353c6cf0ab67ea6829b"}, + {file = "cryptography-2.9.2-cp36-cp36m-win32.whl", hash = "sha256:091d31c42f444c6f519485ed528d8b451d1a0c7bf30e8ca583a0cac44b8a0df6"}, + {file = "cryptography-2.9.2-cp36-cp36m-win_amd64.whl", hash = "sha256:bb1f0281887d89617b4c68e8db9a2c42b9efebf2702a3c5bf70599421a8623e3"}, + {file = "cryptography-2.9.2-cp37-cp37m-win32.whl", hash = "sha256:18452582a3c85b96014b45686af264563e3e5d99d226589f057ace56196ec78b"}, + {file = "cryptography-2.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:22e91636a51170df0ae4dcbd250d318fd28c9f491c4e50b625a49964b24fe46e"}, + {file = "cryptography-2.9.2-cp38-cp38-win32.whl", hash = "sha256:844a76bc04472e5135b909da6aed84360f522ff5dfa47f93e3dd2a0b84a89fa0"}, + {file = "cryptography-2.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:1dfa985f62b137909496e7fc182dac687206d8d089dd03eaeb28ae16eec8e7d5"}, + {file = "cryptography-2.9.2.tar.gz", hash = "sha256:a0c30272fb4ddda5f5ffc1089d7405b7a71b0b0f51993cb4e5dbb4590b2fc229"}, +] +distlib = [ + {file = "distlib-0.3.0.zip", hash = "sha256:2e166e231a26b36d6dfe35a48c4464346620f8645ed0ace01ee31822b288de21"}, ] entrypoints = [ {file = "entrypoints-0.3-py2.py3-none-any.whl", hash = "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19"}, {file = "entrypoints-0.3.tar.gz", hash = "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"}, ] enum34 = [ - {file = "enum34-1.1.6-py2-none-any.whl", hash = "sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79"}, - {file = "enum34-1.1.6-py3-none-any.whl", hash = "sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a"}, - {file = "enum34-1.1.6.tar.gz", hash = "sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1"}, - {file = "enum34-1.1.6.zip", hash = "sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850"}, + {file = "enum34-1.1.10-py2-none-any.whl", hash = "sha256:a98a201d6de3f2ab3db284e70a33b0f896fbf35f8086594e8c9e74b909058d53"}, + {file = "enum34-1.1.10-py3-none-any.whl", hash = "sha256:c3858660960c984d6ab0ebad691265180da2b43f07e061c0f8dca9ef3cffd328"}, + {file = "enum34-1.1.10.tar.gz", hash = "sha256:cce6a7477ed816bd2542d03d53db9f0db935dd013b70f336a95c73979289f248"}, ] filelock = [ {file = "filelock-3.0.12-py3-none-any.whl", hash = "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836"}, @@ -1574,8 +1462,9 @@ functools32 = [ {file = "functools32-3.2.3-2.zip", hash = "sha256:89d824aa6c358c421a234d7f9ee0bd75933a67c29588ce50aaa3acdf4d403fa0"}, ] futures = [ - {file = "futures-3.3.0-py2-none-any.whl", hash = "sha256:49b3f5b064b6e3afc3316421a3f25f66c137ae88f068abbf72830170033c5e16"}, - {file = "futures-3.3.0.tar.gz", hash = "sha256:7e033af76a5e35f58e56da7a91e687706faf4e7bdfb2cbc3f2cca6b9bcda9794"}, + {file = "futures-3.1.1-py2-none-any.whl", hash = "sha256:c4884a65654a7c45435063e14ae85280eb1f111d94e542396717ba9828c4337f"}, + {file = "futures-3.1.1-py3-none-any.whl", hash = "sha256:3a44f286998ae64f0cc083682fcfec16c406134a81a589a5de445d7bb7c2751b"}, + {file = "futures-3.1.1.tar.gz", hash = "sha256:51ecb45f0add83c806c68e4b06106f90db260585b25ef2abfcda0bd95c0132fd"}, ] glob2 = [ {file = "glob2-0.6.tar.gz", hash = "sha256:f5b0a686ff21f820c4d3f0c4edd216704cea59d79d00fa337e244a2f2ff83ed6"}, @@ -1588,44 +1477,40 @@ httpretty = [ {file = "httpretty-0.9.7.tar.gz", hash = "sha256:66216f26b9d2c52e81808f3e674a6fb65d4bf719721394a1a9be926177e55fbe"}, ] identify = [ - {file = "identify-1.4.11-py2.py3-none-any.whl", hash = "sha256:1222b648251bdcb8deb240b294f450fbf704c7984e08baa92507e4ea10b436d5"}, - {file = "identify-1.4.11.tar.gz", hash = "sha256:d824ebe21f38325c771c41b08a95a761db1982f1fc0eee37c6c97df3f1636b96"}, + {file = "identify-1.4.15-py2.py3-none-any.whl", hash = "sha256:88ed90632023e52a6495749c6732e61e08ec9f4f04e95484a5c37b9caf40283c"}, + {file = "identify-1.4.15.tar.gz", hash = "sha256:23c18d97bb50e05be1a54917ee45cc61d57cb96aedc06aabb2b02331edf0dbf0"}, ] idna = [ - {file = "idna-2.8-py2.py3-none-any.whl", hash = "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"}, - {file = "idna-2.8.tar.gz", hash = "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407"}, + {file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"}, + {file = "idna-2.9.tar.gz", hash = "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb"}, ] importlib-metadata = [ - {file = "importlib_metadata-1.1.3-py2.py3-none-any.whl", hash = "sha256:7c7f8ac40673f507f349bef2eed21a0e5f01ddf5b2a7356a6c65eb2099b53764"}, - {file = "importlib_metadata-1.1.3.tar.gz", hash = "sha256:7a99fb4084ffe6dae374961ba7a6521b79c1d07c658ab3a28aa264ee1d1b14e3"}, + {file = "importlib_metadata-1.6.0-py2.py3-none-any.whl", hash = "sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f"}, + {file = "importlib_metadata-1.6.0.tar.gz", hash = "sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e"}, ] importlib-resources = [ - {file = "importlib_resources-1.0.2-py2.py3-none-any.whl", hash = "sha256:6e2783b2538bd5a14678284a3962b0660c715e5a0f10243fd5e00a4b5974f50b"}, - {file = "importlib_resources-1.0.2.tar.gz", hash = "sha256:d3279fd0f6f847cced9f7acc19bd3e5df54d34f93a2e7bb5f238f81545787078"}, + {file = "importlib_resources-1.4.0-py2.py3-none-any.whl", hash = "sha256:dd98ceeef3f5ad2ef4cc287b8586da4ebad15877f351e9688987ad663a0a29b8"}, + {file = "importlib_resources-1.4.0.tar.gz", hash = "sha256:4019b6a9082d8ada9def02bece4a76b131518866790d58fdda0b5f8c603b36c2"}, ] ipaddress = [ {file = "ipaddress-1.0.23-py2.py3-none-any.whl", hash = "sha256:6e0f4a39e66cb5bb9a137b00276a2eff74f93b71dcbdad6f10ff7df9d3557fcc"}, {file = "ipaddress-1.0.23.tar.gz", hash = "sha256:b7f8e0369580bb4a24d5ba1d7cc29660a4a6987763faf1d8a8046830e020e7e2"}, ] jeepney = [ - {file = "jeepney-0.4.2-py3-none-any.whl", hash = "sha256:6f45dce1125cf6c58a1c88123d3831f36a789f9204fbad3172eac15f8ccd08d0"}, - {file = "jeepney-0.4.2.tar.gz", hash = "sha256:0ba6d8c597e9bef1ebd18aaec595f942a264e25c1a48f164d46120eacaa2e9bb"}, + {file = "jeepney-0.4.3-py3-none-any.whl", hash = "sha256:d6c6b49683446d2407d2fe3acb7a368a77ff063f9182fe427da15d622adc24cf"}, + {file = "jeepney-0.4.3.tar.gz", hash = "sha256:3479b861cc2b6407de5188695fa1a8d57e5072d7059322469b62628869b8e36e"}, ] jinja2 = [ - {file = "Jinja2-2.10.3-py2.py3-none-any.whl", hash = "sha256:74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f"}, - {file = "Jinja2-2.10.3.tar.gz", hash = "sha256:9fe95f19286cfefaa917656583d020be14e7859c6b0252588391e47db34527de"}, - {file = "Jinja2-2.11.1-py2.py3-none-any.whl", hash = "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49"}, - {file = "Jinja2-2.11.1.tar.gz", hash = "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250"}, -] -jsonschema = [ - {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"}, - {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"}, + {file = "Jinja2-2.11.2-py2.py3-none-any.whl", hash = "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"}, + {file = "Jinja2-2.11.2.tar.gz", hash = "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0"}, ] keyring = [ {file = "keyring-18.0.1-py2.py3-none-any.whl", hash = "sha256:7b29ebfcf8678c4da531b2478a912eea01e80007e5ddca9ee0c7038cb3489ec6"}, {file = "keyring-18.0.1.tar.gz", hash = "sha256:67d6cc0132bd77922725fae9f18366bb314fd8f95ff4d323a4df41890a96a838"}, {file = "keyring-20.0.1-py2.py3-none-any.whl", hash = "sha256:c674f032424b4bffc62abeac5523ec49cc84aed07a480c3233e0baf618efc15c"}, {file = "keyring-20.0.1.tar.gz", hash = "sha256:963bfa7f090269d30bdc5e25589e5fd9dad2cf2a7c6f176a7f2386910e5d0d8d"}, + {file = "keyring-21.2.0-py3-none-any.whl", hash = "sha256:8179b1cdcdcbc221456b5b74e6b7cfa06f8dd9f239eb81892166d9223d82c5ba"}, + {file = "keyring-21.2.0.tar.gz", hash = "sha256:197fd5903901030ef7b82fe247f43cfed2c157a28e7747d1cfcf4bc5e699dd03"}, ] livereload = [ {file = "livereload-2.6.1-py2.py3-none-any.whl", hash = "sha256:78d55f2c268a8823ba499305dcac64e28ddeb9a92571e12d543cd304faf5817b"}, @@ -1636,8 +1521,6 @@ lockfile = [ {file = "lockfile-0.12.2.tar.gz", hash = "sha256:6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799"}, ] markdown = [ - {file = "Markdown-3.0.1-py2.py3-none-any.whl", hash = "sha256:c00429bd503a47ec88d5e30a751e147dcb4c6889663cd3e2ba0afe858e009baa"}, - {file = "Markdown-3.0.1.tar.gz", hash = "sha256:d02e0f9b04c500cde6637c11ad7c72671f359b87b9fe924b2383649d8841db7c"}, {file = "Markdown-3.1.1-py2.py3-none-any.whl", hash = "sha256:56a46ac655704b91e5b7e6326ce43d5ef72411376588afa1dd90e881b83c7e8c"}, {file = "Markdown-3.1.1.tar.gz", hash = "sha256:2e50876bcdd74517e7b71f3e7a76102050edec255b3983403f1a63e7c8a41e7a"}, ] @@ -1672,6 +1555,11 @@ markupsafe = [ {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"}, {file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"}, {file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"}, {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"}, ] mkdocs = [ @@ -1686,52 +1574,45 @@ more-itertools = [ {file = "more-itertools-5.0.0.tar.gz", hash = "sha256:38a936c0a6d98a38bcc2d03fdaaedaba9f412879461dd2ceff8d37564d6522e4"}, {file = "more_itertools-5.0.0-py2-none-any.whl", hash = "sha256:c0a5785b1109a6bd7fac76d6837fd1feca158e54e521ccd2ae8bfe393cc9d4fc"}, {file = "more_itertools-5.0.0-py3-none-any.whl", hash = "sha256:fe7a7cae1ccb57d33952113ff4fa1bc5f879963600ed74918f1236e212ee50b9"}, - {file = "more-itertools-7.2.0.tar.gz", hash = "sha256:409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832"}, - {file = "more_itertools-7.2.0-py3-none-any.whl", hash = "sha256:92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4"}, - {file = "more-itertools-8.2.0.tar.gz", hash = "sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507"}, - {file = "more_itertools-8.2.0-py3-none-any.whl", hash = "sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c"}, ] msgpack = [ - {file = "msgpack-0.6.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:774f5edc3475917cd95fe593e625d23d8580f9b48b570d8853d06cac171cd170"}, - {file = "msgpack-0.6.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:a06efd0482a1942aad209a6c18321b5e22d64eb531ea20af138b28172d8f35ba"}, - {file = "msgpack-0.6.2-cp27-cp27m-win32.whl", hash = "sha256:8a3ada8401736df2bf497f65589293a86c56e197a80ae7634ec2c3150a2f5082"}, - {file = "msgpack-0.6.2-cp27-cp27m-win_amd64.whl", hash = "sha256:b8b4bd3dafc7b92608ae5462add1c8cc881851c2d4f5d8977fdea5b081d17f21"}, - {file = "msgpack-0.6.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:24149a75643aeaa81ece4259084d11b792308a6cf74e796cbb35def94c89a25a"}, - {file = "msgpack-0.6.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:757bd71a9b89e4f1db0622af4436d403e742506dbea978eba566815dc65ec895"}, - {file = "msgpack-0.6.2-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:32fea0ea3cd1ef820286863a6202dcfd62a539b8ec3edcbdff76068a8c2cc6ce"}, - {file = "msgpack-0.6.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:db7ff14abc73577b0bcbcf73ecff97d3580ecaa0fc8724babce21fdf3fe08ef6"}, - {file = "msgpack-0.6.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:187794cd1eb73acccd528247e3565f6760bd842d7dc299241f830024a7dd5610"}, - {file = "msgpack-0.6.2-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:b24afc52e18dccc8c175de07c1d680bdf315844566f4952b5bedb908894bec79"}, - {file = "msgpack-0.6.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:355f7fd0f90134229eaeefaee3cf42e0afc8518e8f3cd4b25f541a7104dcb8f9"}, - {file = "msgpack-0.6.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:76df51492bc6fa6cc8b65d09efdb67cbba3cbfe55004c3afc81352af92b4a43c"}, - {file = "msgpack-0.6.2-cp36-cp36m-win32.whl", hash = "sha256:f0f47bafe9c9b8ed03e19a100a743662dd8c6d0135e684feea720a0d0046d116"}, - {file = "msgpack-0.6.2-cp36-cp36m-win_amd64.whl", hash = "sha256:c6e5024fc0cdf7f83b6624850309ddd7e06c48a75fa0d1c5173de4d93300eb19"}, - {file = "msgpack-0.6.2-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:30b88c47e0cdb6062daed88ca283b0d84fa0d2ad6c273aa0788152a1c643e408"}, - {file = "msgpack-0.6.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:229a0ccdc39e9b6c6d1033cd8aecd9c296823b6c87f0de3943c59b8bc7c64bee"}, - {file = "msgpack-0.6.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4abdb88a9b67e64810fb54b0c24a1fd76b12297b4f7a1467d85a14dd8367191a"}, - {file = "msgpack-0.6.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:dedf54d72d9e7b6d043c244c8213fe2b8bbfe66874b9a65b39c4cc892dd99dd4"}, - {file = "msgpack-0.6.2-cp37-cp37m-win32.whl", hash = "sha256:0cc7ca04e575ba34fea7cfcd76039f55def570e6950e4155a4174368142c8e1b"}, - {file = "msgpack-0.6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:1904b7cb65342d0998b75908304a03cb004c63ef31e16c8c43fee6b989d7f0d7"}, - {file = "msgpack-0.6.2.tar.gz", hash = "sha256:ea3c2f859346fcd55fc46e96885301d9c2f7a36d453f5d8f2967840efa1e1830"}, + {file = "msgpack-1.0.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:cec8bf10981ed70998d98431cd814db0ecf3384e6b113366e7f36af71a0fca08"}, + {file = "msgpack-1.0.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aa5c057eab4f40ec47ea6f5a9825846be2ff6bf34102c560bad5cad5a677c5be"}, + {file = "msgpack-1.0.0-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:4233b7f86c1208190c78a525cd3828ca1623359ef48f78a6fea4b91bb995775a"}, + {file = "msgpack-1.0.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:b3758dfd3423e358bbb18a7cccd1c74228dffa7a697e5be6cb9535de625c0dbf"}, + {file = "msgpack-1.0.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:25b3bc3190f3d9d965b818123b7752c5dfb953f0d774b454fd206c18fe384fb8"}, + {file = "msgpack-1.0.0-cp36-cp36m-win32.whl", hash = "sha256:e7bbdd8e2b277b77782f3ce34734b0dfde6cbe94ddb74de8d733d603c7f9e2b1"}, + {file = "msgpack-1.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:5dba6d074fac9b24f29aaf1d2d032306c27f04187651511257e7831733293ec2"}, + {file = "msgpack-1.0.0-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:908944e3f038bca67fcfedb7845c4a257c7749bf9818632586b53bcf06ba4b97"}, + {file = "msgpack-1.0.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:db685187a415f51d6b937257474ca72199f393dad89534ebbdd7d7a3b000080e"}, + {file = "msgpack-1.0.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ea41c9219c597f1d2bf6b374d951d310d58684b5de9dc4bd2976db9e1e22c140"}, + {file = "msgpack-1.0.0-cp37-cp37m-win32.whl", hash = "sha256:e35b051077fc2f3ce12e7c6a34cf309680c63a842db3a0616ea6ed25ad20d272"}, + {file = "msgpack-1.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5bea44181fc8e18eed1d0cd76e355073f00ce232ff9653a0ae88cb7d9e643322"}, + {file = "msgpack-1.0.0-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c901e8058dd6653307906c5f157f26ed09eb94a850dddd989621098d347926ab"}, + {file = "msgpack-1.0.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:271b489499a43af001a2e42f42d876bb98ccaa7e20512ff37ca78c8e12e68f84"}, + {file = "msgpack-1.0.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7a22c965588baeb07242cb561b63f309db27a07382825fc98aecaf0827c1538e"}, + {file = "msgpack-1.0.0-cp38-cp38-win32.whl", hash = "sha256:002a0d813e1f7b60da599bdf969e632074f9eec1b96cbed8fb0973a63160a408"}, + {file = "msgpack-1.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:39c54fdebf5fa4dda733369012c59e7d085ebdfe35b6cf648f09d16708f1be5d"}, + {file = "msgpack-1.0.0.tar.gz", hash = "sha256:9534d5cc480d4aff720233411a1f765be90885750b07df772380b34c10ecb5c0"}, ] nodeenv = [ - {file = "nodeenv-1.3.4-py2.py3-none-any.whl", hash = "sha256:561057acd4ae3809e665a9aaaf214afff110bbb6a6d5c8a96121aea6878408b3"}, + {file = "nodeenv-1.3.5-py2.py3-none-any.whl", hash = "sha256:5b2438f2e42af54ca968dd1b374d14a1194848955187b0e5e4be1f73813a5212"}, ] packaging = [ - {file = "packaging-20.1-py2.py3-none-any.whl", hash = "sha256:170748228214b70b672c581a3dd610ee51f733018650740e98c7df862a583f73"}, - {file = "packaging-20.1.tar.gz", hash = "sha256:e665345f9eef0c621aa0bf2f8d78cf6d21904eef16a93f020240b704a57f1334"}, + {file = "packaging-20.3-py2.py3-none-any.whl", hash = "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752"}, + {file = "packaging-20.3.tar.gz", hash = "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3"}, ] pastel = [ - {file = "pastel-0.1.1-py2.py3-none-any.whl", hash = "sha256:a904e1659512cc9880a028f66de77cc813a4c32f7ceb68725cbc8afad57ef7ef"}, - {file = "pastel-0.1.1.tar.gz", hash = "sha256:bf3b1901b2442ea0d8ab9a390594e5b0c9584709d543a3113506fe8b28cbace3"}, + {file = "pastel-0.2.0-py2.py3-none-any.whl", hash = "sha256:18b559dc3ad4ba9b8bd5baebe6503f25f36d21460f021cf27a8d889cb5d17840"}, + {file = "pastel-0.2.0.tar.gz", hash = "sha256:46155fc523bdd4efcd450bbcb3f2b94a6e3b25edc0eb493e081104ad09e1ca36"}, ] pathlib2 = [ {file = "pathlib2-2.3.5-py2.py3-none-any.whl", hash = "sha256:0ec8205a157c80d7acc301c0b18fbd5d44fe655968f5d947b6ecef5290fc35db"}, {file = "pathlib2-2.3.5.tar.gz", hash = "sha256:6cd9a47b597b37cc57de1c05e56fb1a1c9cc9fab04fe78c29acd090418529868"}, ] pathspec = [ - {file = "pathspec-0.7.0-py2.py3-none-any.whl", hash = "sha256:163b0632d4e31cef212976cf57b43d9fd6b0bac6e67c26015d611a647d5e7424"}, - {file = "pathspec-0.7.0.tar.gz", hash = "sha256:562aa70af2e0d434367d9790ad37aed893de47f1693e4201fd1d3dca15d19b96"}, + {file = "pathspec-0.8.0-py2.py3-none-any.whl", hash = "sha256:7d91249d21749788d07a2d0f94147accd8f845507400749ea19c1ec9054a12b0"}, + {file = "pathspec-0.8.0.tar.gz", hash = "sha256:da45173eb3a6f2a5a487efba21f050af2b41948be6ab52b6a1e3ff22bb8b7061"}, ] pep562 = [ {file = "pep562-1.0-py2.py3-none-any.whl", hash = "sha256:d2a48b178ebf5f8dd31709cc26a19808ef794561fa2fe50ea01ea2bad4d667ef"}, @@ -1749,9 +1630,11 @@ pluggy = [ {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, ] +poetry-core = [ + {file = "poetry-core-1.0.0a6.tar.gz", hash = "sha256:965869ce488869e473f5afb96e6155724fce9ce8ed2ef71c7e47a900c6159ea8"}, + {file = "poetry_core-1.0.0a6-py2.py3-none-any.whl", hash = "sha256:440d3b43b64db47c2c348f784f770a1cbc83ae0aacb4f66d9f2f82b35366303f"}, +] pre-commit = [ - {file = "pre_commit-1.18.3-py2.py3-none-any.whl", hash = "sha256:fa78ff96e8e9ac94c748388597693f18b041a181c94a4f039ad20f45287ba44a"}, - {file = "pre_commit-1.18.3.tar.gz", hash = "sha256:1d3c0587bda7c4e537a46c27f2c84aa006acc18facf9970bf947df596ce91f3f"}, {file = "pre_commit-1.21.0-py2.py3-none-any.whl", hash = "sha256:f92a359477f3252452ae2e8d3029de77aec59415c16ae4189bcfba40b757e029"}, {file = "pre_commit-1.21.0.tar.gz", hash = "sha256:8f48d8637bdae6fa70cc97db9c1dd5aa7c5c8bf71968932a380628c25978b850"}, ] @@ -1764,11 +1647,10 @@ py = [ {file = "py-1.8.1.tar.gz", hash = "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa"}, ] pycparser = [ - {file = "pycparser-2.19.tar.gz", hash = "sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3"}, + {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, + {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, ] pygments = [ - {file = "Pygments-2.3.1-py2.py3-none-any.whl", hash = "sha256:e8218dd399a61674745138520d0d4cf2621d7e032439341bc3f647bff125818d"}, - {file = "Pygments-2.3.1.tar.gz", hash = "sha256:5ffada19f6203563680669ee7f53b64dabbeb100eb51b61996085e99c03b284a"}, {file = "Pygments-2.5.2-py2.py3-none-any.whl", hash = "sha256:2a3fe295e54a20164a9df49c75fa58526d3be48e14aceba6d6b1e8ac0bfd6f1b"}, {file = "Pygments-2.5.2.tar.gz", hash = "sha256:98c8aa5a9f778fcd1026a17361ddaf7330d1b7c62ae97c3bb0ae73e0b9b6b0fe"}, ] @@ -1781,17 +1663,12 @@ pylev = [ {file = "pylev-1.3.0.tar.gz", hash = "sha256:063910098161199b81e453025653ec53556c1be7165a9b7c50be2f4d57eae1c3"}, ] pymdown-extensions = [ - {file = "pymdown-extensions-6.0.tar.gz", hash = "sha256:6cf0cf36b5a03b291ace22dc2f320f4789ce56fbdb6635a3be5fadbf5d7694dd"}, - {file = "pymdown_extensions-6.0-py2.py3-none-any.whl", hash = "sha256:25b0a7967fa697b5035e23340a48594e3e93acb10b06d74574218ace3347d1df"}, {file = "pymdown-extensions-6.2.1.tar.gz", hash = "sha256:3bbe6048275f8a0d13a0fe44e0ea201e67268aa7bb40c2544eef16abbf168f7b"}, {file = "pymdown_extensions-6.2.1-py2.py3-none-any.whl", hash = "sha256:dce5e17b93be0572322b7d06c9a13c13a9d98694d6468277911d50ca87d26f29"}, ] pyparsing = [ - {file = "pyparsing-2.4.6-py2.py3-none-any.whl", hash = "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec"}, - {file = "pyparsing-2.4.6.tar.gz", hash = "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f"}, -] -pyrsistent = [ - {file = "pyrsistent-0.14.11.tar.gz", hash = "sha256:3ca82748918eb65e2d89f222b702277099aca77e34843c5eb9d52451173970e2"}, + {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, + {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, ] pytest = [ {file = "pytest-4.6.9-py2.py3-none-any.whl", hash = "sha256:c77a5f30a90e0ce24db9eaa14ddfd38d4afb5ea159309bdd2dae55b931bc9324"}, @@ -1814,57 +1691,44 @@ pywin32-ctypes = [ {file = "pywin32_ctypes-0.2.0-py2.py3-none-any.whl", hash = "sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98"}, ] pyyaml = [ - {file = "PyYAML-5.2-cp27-cp27m-win32.whl", hash = "sha256:35ace9b4147848cafac3db142795ee42deebe9d0dad885ce643928e88daebdcc"}, - {file = "PyYAML-5.2-cp27-cp27m-win_amd64.whl", hash = "sha256:ebc4ed52dcc93eeebeae5cf5deb2ae4347b3a81c3fa12b0b8c976544829396a4"}, - {file = "PyYAML-5.2-cp35-cp35m-win32.whl", hash = "sha256:38a4f0d114101c58c0f3a88aeaa44d63efd588845c5a2df5290b73db8f246d15"}, - {file = "PyYAML-5.2-cp35-cp35m-win_amd64.whl", hash = "sha256:483eb6a33b671408c8529106df3707270bfacb2447bf8ad856a4b4f57f6e3075"}, - {file = "PyYAML-5.2-cp36-cp36m-win32.whl", hash = "sha256:7f38e35c00e160db592091751d385cd7b3046d6d51f578b29943225178257b31"}, - {file = "PyYAML-5.2-cp36-cp36m-win_amd64.whl", hash = "sha256:0e7f69397d53155e55d10ff68fdfb2cf630a35e6daf65cf0bdeaf04f127c09dc"}, - {file = "PyYAML-5.2-cp37-cp37m-win32.whl", hash = "sha256:e4c015484ff0ff197564917b4b4246ca03f411b9bd7f16e02a2f586eb48b6d04"}, - {file = "PyYAML-5.2-cp37-cp37m-win_amd64.whl", hash = "sha256:4b6be5edb9f6bb73680f5bf4ee08ff25416d1400fbd4535fe0069b2994da07cd"}, - {file = "PyYAML-5.2-cp38-cp38-win32.whl", hash = "sha256:8100c896ecb361794d8bfdb9c11fce618c7cf83d624d73d5ab38aef3bc82d43f"}, - {file = "PyYAML-5.2-cp38-cp38-win_amd64.whl", hash = "sha256:2e9f0b7c5914367b0916c3c104a024bb68f269a486b9d04a2e8ac6f6597b7803"}, - {file = "PyYAML-5.2.tar.gz", hash = "sha256:c0ee8eca2c582d29c3c2ec6e2c4f703d1b7f1fb10bc72317355a746057e7346c"}, - {file = "PyYAML-5.3-cp27-cp27m-win32.whl", hash = "sha256:940532b111b1952befd7db542c370887a8611660d2b9becff75d39355303d82d"}, - {file = "PyYAML-5.3-cp27-cp27m-win_amd64.whl", hash = "sha256:059b2ee3194d718896c0ad077dd8c043e5e909d9180f387ce42012662a4946d6"}, - {file = "PyYAML-5.3-cp35-cp35m-win32.whl", hash = "sha256:4fee71aa5bc6ed9d5f116327c04273e25ae31a3020386916905767ec4fc5317e"}, - {file = "PyYAML-5.3-cp35-cp35m-win_amd64.whl", hash = "sha256:dbbb2379c19ed6042e8f11f2a2c66d39cceb8aeace421bfc29d085d93eda3689"}, - {file = "PyYAML-5.3-cp36-cp36m-win32.whl", hash = "sha256:e3a057b7a64f1222b56e47bcff5e4b94c4f61faac04c7c4ecb1985e18caa3994"}, - {file = "PyYAML-5.3-cp36-cp36m-win_amd64.whl", hash = "sha256:74782fbd4d4f87ff04159e986886931456a1894c61229be9eaf4de6f6e44b99e"}, - {file = "PyYAML-5.3-cp37-cp37m-win32.whl", hash = "sha256:24521fa2890642614558b492b473bee0ac1f8057a7263156b02e8b14c88ce6f5"}, - {file = "PyYAML-5.3-cp37-cp37m-win_amd64.whl", hash = "sha256:1cf708e2ac57f3aabc87405f04b86354f66799c8e62c28c5fc5f88b5521b2dbf"}, - {file = "PyYAML-5.3-cp38-cp38-win32.whl", hash = "sha256:70024e02197337533eef7b85b068212420f950319cc8c580261963aefc75f811"}, - {file = "PyYAML-5.3-cp38-cp38-win_amd64.whl", hash = "sha256:cb1f2f5e426dc9f07a7681419fe39cee823bb74f723f36f70399123f439e9b20"}, - {file = "PyYAML-5.3.tar.gz", hash = "sha256:e9f45bd5b92c7974e59bcd2dcc8631a6b6cc380a904725fce7bc08872e691615"}, + {file = "PyYAML-5.3.1-cp27-cp27m-win32.whl", hash = "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f"}, + {file = "PyYAML-5.3.1-cp27-cp27m-win_amd64.whl", hash = "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76"}, + {file = "PyYAML-5.3.1-cp35-cp35m-win32.whl", hash = "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2"}, + {file = "PyYAML-5.3.1-cp35-cp35m-win_amd64.whl", hash = "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c"}, + {file = "PyYAML-5.3.1-cp36-cp36m-win32.whl", hash = "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2"}, + {file = "PyYAML-5.3.1-cp36-cp36m-win_amd64.whl", hash = "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648"}, + {file = "PyYAML-5.3.1-cp37-cp37m-win32.whl", hash = "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a"}, + {file = "PyYAML-5.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf"}, + {file = "PyYAML-5.3.1-cp38-cp38-win32.whl", hash = "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97"}, + {file = "PyYAML-5.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee"}, + {file = "PyYAML-5.3.1.tar.gz", hash = "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d"}, ] regex = [ - {file = "regex-2020.1.8-cp27-cp27m-win32.whl", hash = "sha256:4e8f02d3d72ca94efc8396f8036c0d3bcc812aefc28ec70f35bb888c74a25161"}, - {file = "regex-2020.1.8-cp27-cp27m-win_amd64.whl", hash = "sha256:e6c02171d62ed6972ca8631f6f34fa3281d51db8b326ee397b9c83093a6b7242"}, - {file = "regex-2020.1.8-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:4eae742636aec40cf7ab98171ab9400393360b97e8f9da67b1867a9ee0889b26"}, - {file = "regex-2020.1.8-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:bd25bb7980917e4e70ccccd7e3b5740614f1c408a642c245019cff9d7d1b6149"}, - {file = "regex-2020.1.8-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:3e77409b678b21a056415da3a56abfd7c3ad03da71f3051bbcdb68cf44d3c34d"}, - {file = "regex-2020.1.8-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:07b39bf943d3d2fe63d46281d8504f8df0ff3fe4c57e13d1656737950e53e525"}, - {file = "regex-2020.1.8-cp36-cp36m-win32.whl", hash = "sha256:23e2c2c0ff50f44877f64780b815b8fd2e003cda9ce817a7fd00dea5600c84a0"}, - {file = "regex-2020.1.8-cp36-cp36m-win_amd64.whl", hash = "sha256:27429b8d74ba683484a06b260b7bb00f312e7c757792628ea251afdbf1434003"}, - {file = "regex-2020.1.8-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:0e182d2f097ea8549a249040922fa2b92ae28be4be4895933e369a525ba36576"}, - {file = "regex-2020.1.8-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e3cd21cc2840ca67de0bbe4071f79f031c81418deb544ceda93ad75ca1ee9f7b"}, - {file = "regex-2020.1.8-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:ecc6de77df3ef68fee966bb8cb4e067e84d4d1f397d0ef6fce46913663540d77"}, - {file = "regex-2020.1.8-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:26ff99c980f53b3191d8931b199b29d6787c059f2e029b2b0c694343b1708c35"}, - {file = "regex-2020.1.8-cp37-cp37m-win32.whl", hash = "sha256:7bcd322935377abcc79bfe5b63c44abd0b29387f267791d566bbb566edfdd146"}, - {file = "regex-2020.1.8-cp37-cp37m-win_amd64.whl", hash = "sha256:10671601ee06cf4dc1bc0b4805309040bb34c9af423c12c379c83d7895622bb5"}, - {file = "regex-2020.1.8-cp38-cp38-manylinux1_i686.whl", hash = "sha256:98b8ed7bb2155e2cbb8b76f627b2fd12cf4b22ab6e14873e8641f266e0fb6d8f"}, - {file = "regex-2020.1.8-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6a6ba91b94427cd49cd27764679024b14a96874e0dc638ae6bdd4b1a3ce97be1"}, - {file = "regex-2020.1.8-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:6a6ae17bf8f2d82d1e8858a47757ce389b880083c4ff2498dba17c56e6c103b9"}, - {file = "regex-2020.1.8-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:0932941cdfb3afcbc26cc3bcf7c3f3d73d5a9b9c56955d432dbf8bbc147d4c5b"}, - {file = "regex-2020.1.8-cp38-cp38-win32.whl", hash = "sha256:d58e4606da2a41659c84baeb3cfa2e4c87a74cec89a1e7c56bee4b956f9d7461"}, - {file = "regex-2020.1.8-cp38-cp38-win_amd64.whl", hash = "sha256:e7c7661f7276507bce416eaae22040fd91ca471b5b33c13f8ff21137ed6f248c"}, - {file = "regex-2020.1.8.tar.gz", hash = "sha256:d0f424328f9822b0323b3b6f2e4b9c90960b24743d220763c7f07071e0778351"}, + {file = "regex-2020.4.4-cp27-cp27m-win32.whl", hash = "sha256:90742c6ff121a9c5b261b9b215cb476eea97df98ea82037ec8ac95d1be7a034f"}, + {file = "regex-2020.4.4-cp27-cp27m-win_amd64.whl", hash = "sha256:24f4f4062eb16c5bbfff6a22312e8eab92c2c99c51a02e39b4eae54ce8255cd1"}, + {file = "regex-2020.4.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:08119f707f0ebf2da60d2f24c2f39ca616277bb67ef6c92b72cbf90cbe3a556b"}, + {file = "regex-2020.4.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c9423a150d3a4fc0f3f2aae897a59919acd293f4cb397429b120a5fcd96ea3db"}, + {file = "regex-2020.4.4-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:c087bff162158536387c53647411db09b6ee3f9603c334c90943e97b1052a156"}, + {file = "regex-2020.4.4-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:1cbe0fa0b7f673400eb29e9ef41d4f53638f65f9a2143854de6b1ce2899185c3"}, + {file = "regex-2020.4.4-cp36-cp36m-win32.whl", hash = "sha256:0ce9537396d8f556bcfc317c65b6a0705320701e5ce511f05fc04421ba05b8a8"}, + {file = "regex-2020.4.4-cp36-cp36m-win_amd64.whl", hash = "sha256:7e1037073b1b7053ee74c3c6c0ada80f3501ec29d5f46e42669378eae6d4405a"}, + {file = "regex-2020.4.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4385f12aa289d79419fede43f979e372f527892ac44a541b5446617e4406c468"}, + {file = "regex-2020.4.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a58dd45cb865be0ce1d5ecc4cfc85cd8c6867bea66733623e54bd95131f473b6"}, + {file = "regex-2020.4.4-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:ccccdd84912875e34c5ad2d06e1989d890d43af6c2242c6fcfa51556997af6cd"}, + {file = "regex-2020.4.4-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:ea4adf02d23b437684cd388d557bf76e3afa72f7fed5bbc013482cc00c816948"}, + {file = "regex-2020.4.4-cp37-cp37m-win32.whl", hash = "sha256:2294f8b70e058a2553cd009df003a20802ef75b3c629506be20687df0908177e"}, + {file = "regex-2020.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:e91ba11da11cf770f389e47c3f5c30473e6d85e06d7fd9dcba0017d2867aab4a"}, + {file = "regex-2020.4.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5635cd1ed0a12b4c42cce18a8d2fb53ff13ff537f09de5fd791e97de27b6400e"}, + {file = "regex-2020.4.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:23069d9c07e115537f37270d1d5faea3e0bdded8279081c4d4d607a2ad393683"}, + {file = "regex-2020.4.4-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:c162a21e0da33eb3d31a3ac17a51db5e634fc347f650d271f0305d96601dc15b"}, + {file = "regex-2020.4.4-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:fb95debbd1a824b2c4376932f2216cc186912e389bdb0e27147778cf6acb3f89"}, + {file = "regex-2020.4.4-cp38-cp38-win32.whl", hash = "sha256:2a3bf8b48f8e37c3a40bb3f854bf0121c194e69a650b209628d951190b862de3"}, + {file = "regex-2020.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:5bfed051dbff32fd8945eccca70f5e22b55e4148d2a8a45141a3b053d6455ae3"}, + {file = "regex-2020.4.4.tar.gz", hash = "sha256:295badf61a51add2d428a46b8580309c520d8b26e769868b922750cf3ce67142"}, ] requests = [ - {file = "requests-2.21.0-py2.py3-none-any.whl", hash = "sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b"}, - {file = "requests-2.21.0.tar.gz", hash = "sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e"}, - {file = "requests-2.22.0-py2.py3-none-any.whl", hash = "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"}, - {file = "requests-2.22.0.tar.gz", hash = "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4"}, + {file = "requests-2.23.0-py2.py3-none-any.whl", hash = "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee"}, + {file = "requests-2.23.0.tar.gz", hash = "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"}, ] requests-toolbelt = [ {file = "requests-toolbelt-0.8.0.tar.gz", hash = "sha256:f6a531936c6fa4c6cfce1b9c10d5c4f498d16528d2a54a22ca00011205a187b5"}, @@ -1889,8 +1753,12 @@ secretstorage = [ {file = "SecretStorage-3.1.2.tar.gz", hash = "sha256:15da8a989b65498e29be338b3b279965f1b8f09b9668bd8010da183024c8bff6"}, ] shellingham = [ - {file = "shellingham-1.3.1-py2.py3-none-any.whl", hash = "sha256:77d37a4fd287c1e663006f7ecf1b9deca9ad492d0082587bd813c44eb49e4e62"}, - {file = "shellingham-1.3.1.tar.gz", hash = "sha256:985b23bbd1feae47ca6a6365eacd314d93d95a8a16f8f346945074c28fe6f3e0"}, + {file = "shellingham-1.3.2-py2.py3-none-any.whl", hash = "sha256:7f6206ae169dc1a03af8a138681b3f962ae61cc93ade84d0585cca3aaf770044"}, + {file = "shellingham-1.3.2.tar.gz", hash = "sha256:576c1982bea0ba82fb46c36feb951319d7f42214a82634233f58b40d858a751e"}, +] +singledispatch = [ + {file = "singledispatch-3.4.0.3-py2.py3-none-any.whl", hash = "sha256:833b46966687b3de7f438c761ac475213e53b306740f1abfaa86e1d1aae56aa8"}, + {file = "singledispatch-3.4.0.3.tar.gz", hash = "sha256:5b06af87df13818d14f08a028e42f566640aef80805c3b50c5056b086e3c2b9c"}, ] six = [ {file = "six-1.14.0-py2.py3-none-any.whl", hash = "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"}, @@ -1909,8 +1777,8 @@ toml = [ {file = "toml-0.10.0.tar.gz", hash = "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c"}, ] tomlkit = [ - {file = "tomlkit-0.5.8-py2.py3-none-any.whl", hash = "sha256:96e6369288571799a3052c1ef93b9de440e1ab751aa045f435b55e9d3bcd0690"}, - {file = "tomlkit-0.5.8.tar.gz", hash = "sha256:32c10cc16ded7e4101c79f269910658cc2a0be5913f1252121c3cd603051c269"}, + {file = "tomlkit-0.5.11-py2.py3-none-any.whl", hash = "sha256:4e1bd6c9197d984528f9ff0cc9db667c317d8881288db50db20eeeb0f6b0380b"}, + {file = "tomlkit-0.5.11.tar.gz", hash = "sha256:f044eda25647882e5ef22b43a1688fb6ab12af2fc50e8456cdfc751c873101cf"}, ] tornado = [ {file = "tornado-5.1.1-cp35-cp35m-win32.whl", hash = "sha256:732e836008c708de2e89a31cb2fa6c0e5a70cb60492bee6f1ea1047500feaf7f"}, @@ -1920,19 +1788,10 @@ tornado = [ {file = "tornado-5.1.1-cp37-cp37m-win32.whl", hash = "sha256:e5f2585afccbff22390cddac29849df463b252b711aa2ce7c5f3f342a5b3b444"}, {file = "tornado-5.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:8e9d728c4579682e837c92fdd98036bd5cdefa1da2aaf6acf26947e6dd0c01c5"}, {file = "tornado-5.1.1.tar.gz", hash = "sha256:4e5158d97583502a7e2739951553cbd88a72076f152b4b11b64b9a10c4c49409"}, - {file = "tornado-6.0.3-cp35-cp35m-win32.whl", hash = "sha256:c9399267c926a4e7c418baa5cbe91c7d1cf362d505a1ef898fde44a07c9dd8a5"}, - {file = "tornado-6.0.3-cp35-cp35m-win_amd64.whl", hash = "sha256:398e0d35e086ba38a0427c3b37f4337327231942e731edaa6e9fd1865bbd6f60"}, - {file = "tornado-6.0.3-cp36-cp36m-win32.whl", hash = "sha256:4e73ef678b1a859f0cb29e1d895526a20ea64b5ffd510a2307b5998c7df24281"}, - {file = "tornado-6.0.3-cp36-cp36m-win_amd64.whl", hash = "sha256:349884248c36801afa19e342a77cc4458caca694b0eda633f5878e458a44cb2c"}, - {file = "tornado-6.0.3-cp37-cp37m-win32.whl", hash = "sha256:559bce3d31484b665259f50cd94c5c28b961b09315ccd838f284687245f416e5"}, - {file = "tornado-6.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:abbe53a39734ef4aba061fca54e30c6b4639d3e1f59653f0da37a0003de148c7"}, - {file = "tornado-6.0.3.tar.gz", hash = "sha256:c845db36ba616912074c5b1ee897f8e0124df269468f25e4fe21fe72f6edd7a9"}, ] tox = [ - {file = "tox-3.12.1-py2.py3-none-any.whl", hash = "sha256:f5c8e446b51edd2ea97df31d4ded8c8b72e7d6c619519da6bb6084b9dd5770f9"}, - {file = "tox-3.12.1.tar.gz", hash = "sha256:f87fd33892a2df0950e5e034def9468988b8d008c7e9416be665fcc0dd45b14f"}, - {file = "tox-3.14.3-py2.py3-none-any.whl", hash = "sha256:806d0a9217584558cc93747a945a9d9bff10b141a5287f0c8429a08828a22192"}, - {file = "tox-3.14.3.tar.gz", hash = "sha256:06ba73b149bf838d5cd25dc30c2dd2671ae5b2757cf98e5c41a35fe449f131b3"}, + {file = "tox-3.14.6-py2.py3-none-any.whl", hash = "sha256:b2c4b91c975ea5c11463d9ca00bebf82654439c5df0f614807b9bdec62cc9471"}, + {file = "tox-3.14.6.tar.gz", hash = "sha256:a4a6689045d93c208d77230853b28058b7513f5123647b67bf012f82fa168303"}, ] typed-ast = [ {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3"}, @@ -1962,25 +1821,32 @@ typing = [ {file = "typing-3.7.4.1-py3-none-any.whl", hash = "sha256:f38d83c5a7a7086543a0f649564d661859c5146a85775ab90c0d2f93ffaa9714"}, {file = "typing-3.7.4.1.tar.gz", hash = "sha256:91dfe6f3f706ee8cc32d38edbbf304e9b7583fb37108fef38229617f8b3eba23"}, ] +typing-extensions = [ + {file = "typing_extensions-3.7.4.2-py2-none-any.whl", hash = "sha256:f8d2bd89d25bc39dabe7d23df520442fa1d8969b82544370e03d88b5a591c392"}, + {file = "typing_extensions-3.7.4.2-py3-none-any.whl", hash = "sha256:6e95524d8a547a91e08f404ae485bbb71962de46967e1b71a0cb89af24e761c5"}, + {file = "typing_extensions-3.7.4.2.tar.gz", hash = "sha256:79ee589a3caca649a9bfd2a8de4709837400dfa00b6cc81962a1e6a1815969ae"}, +] urllib3 = [ - {file = "urllib3-1.24.3-py2.py3-none-any.whl", hash = "sha256:a637e5fae88995b256e3409dc4d52c2e2e0ba32c42a6365fee8bbd2238de3cfb"}, - {file = "urllib3-1.24.3.tar.gz", hash = "sha256:2393a695cd12afedd0dcb26fe5d50d0cf248e5a66f75dbd89a3d4eb333a61af4"}, - {file = "urllib3-1.25.8-py2.py3-none-any.whl", hash = "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc"}, - {file = "urllib3-1.25.8.tar.gz", hash = "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"}, + {file = "urllib3-1.25.9-py2.py3-none-any.whl", hash = "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115"}, + {file = "urllib3-1.25.9.tar.gz", hash = "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527"}, ] virtualenv = [ - {file = "virtualenv-16.7.9-py2.py3-none-any.whl", hash = "sha256:55059a7a676e4e19498f1aad09b8313a38fcc0cdbe4fdddc0e9b06946d21b4bb"}, - {file = "virtualenv-16.7.9.tar.gz", hash = "sha256:0d62c70883c0342d59c11d0ddac0d954d0431321a41ab20851facf2b222598f3"}, + {file = "virtualenv-20.0.18-py2.py3-none-any.whl", hash = "sha256:5021396e8f03d0d002a770da90e31e61159684db2859d0ba4850fbea752aa675"}, + {file = "virtualenv-20.0.18.tar.gz", hash = "sha256:ac53ade75ca189bc97b6c1d9ec0f1a50efe33cbf178ae09452dcd9fd309013c1"}, ] wcwidth = [ - {file = "wcwidth-0.1.8-py2.py3-none-any.whl", hash = "sha256:8fd29383f539be45b20bd4df0dc29c20ba48654a41e661925e612311e9f3c603"}, - {file = "wcwidth-0.1.8.tar.gz", hash = "sha256:f28b3e8a6483e5d49e7f8949ac1a78314e740333ae305b4ba5defd3e74fb37a8"}, + {file = "wcwidth-0.1.9-py2.py3-none-any.whl", hash = "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1"}, + {file = "wcwidth-0.1.9.tar.gz", hash = "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1"}, ] webencodings = [ {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, ] +woops = [ + {file = "woops-0.2.1-py3-none-any.whl", hash = "sha256:77f7179941d0a3d354d923f71428ee2c2519e0b86f465ed5882b98a6d00ec7f0"}, + {file = "woops-0.2.1.tar.gz", hash = "sha256:f95dee22e055b61980209fdf481f33e743e02d5ef135853c9089d0061370f94a"}, +] zipp = [ - {file = "zipp-1.1.0-py2.py3-none-any.whl", hash = "sha256:15428d652e993b6ce86694c3cccf0d71aa7afdc6ef1807fa25a920e9444e0281"}, - {file = "zipp-1.1.0.tar.gz", hash = "sha256:d9d2efe11d3a3fb9184da550d35bd1319dc8e30a63255927c82bb42fca1f4f7c"}, + {file = "zipp-1.2.0-py2.py3-none-any.whl", hash = "sha256:e0d9e63797e483a30d27e09fffd308c59a700d365ec34e93cc100844168bf921"}, + {file = "zipp-1.2.0.tar.gz", hash = "sha256:c70410551488251b0fee67b460fb9a536af8d6f9f008ad10ac51f615b6a521b1"}, ] diff --git a/poetry/__init__.py b/poetry/__init__.py index 6d7492fe6c1..26cfe4052b1 100644 --- a/poetry/__init__.py +++ b/poetry/__init__.py @@ -1,14 +1,4 @@ -import os -import sys +from pkgutil import extend_path -from .__version__ import __version__ # noqa - -_ROOT = os.path.dirname(os.path.realpath(__file__)) -_VENDOR = os.path.join(_ROOT, "_vendor") -_CURRENT_VENDOR = os.path.join( - _VENDOR, "py{}".format(".".join(str(v) for v in sys.version_info[:2])) -) - -# Add vendored dependencies to path. -sys.path.insert(0, _CURRENT_VENDOR) +__path__ = extend_path(__path__, __name__) diff --git a/poetry/__version__.py b/poetry/__version__.py index 976498ab9ca..b8d9ea00cbe 100644 --- a/poetry/__version__.py +++ b/poetry/__version__.py @@ -1 +1 @@ -__version__ = "1.0.3" +__version__ = "1.1.0a1" diff --git a/poetry/console/application.py b/poetry/console/application.py index 1e6df4fa361..72f293124f8 100644 --- a/poetry/console/application.py +++ b/poetry/console/application.py @@ -1,6 +1,6 @@ from cleo import Application as BaseApplication -from poetry import __version__ +from poetry.__version__ import __version__ from .commands.about import AboutCommand from .commands.add import AddCommand diff --git a/poetry/console/commands/add.py b/poetry/console/commands/add.py index bb210265703..5747fe386df 100644 --- a/poetry/console/commands/add.py +++ b/poetry/console/commands/add.py @@ -45,6 +45,7 @@ class AddCommand(EnvCommand, InitCommand): None, "Output the operations but do not execute anything (implicitly enables --verbose).", ), + option("lock", None, "Do not perform operations (only update the lockfile)."), ] help = """The add command adds required packages to your pyproject.toml and installs them. @@ -56,7 +57,7 @@ class AddCommand(EnvCommand, InitCommand): def handle(self): from poetry.installation.installer import Installer - from poetry.semver import parse_constraint + from poetry.core.semver import parse_constraint from tomlkit import inline_table packages = self.argument("name") @@ -154,6 +155,8 @@ def handle(self): installer.dry_run(self.option("dry-run")) installer.update(True) + if self.option("lock"): + installer.lock() installer.whitelist([r["name"] for r in requirements]) try: diff --git a/poetry/console/commands/build.py b/poetry/console/commands/build.py index 5af68714233..d2473ab0bfd 100644 --- a/poetry/console/commands/build.py +++ b/poetry/console/commands/build.py @@ -12,8 +12,13 @@ class BuildCommand(EnvCommand): option("format", "f", "Limit the format to either sdist or wheel.", flag=False) ] + loggers = [ + "poetry.core.masonry.builders.sdist", + "poetry.core.masonry.builders.wheel", + ] + def handle(self): - from poetry.masonry import Builder + from poetry.core.masonry import Builder fmt = "all" if self.option("format"): @@ -21,10 +26,10 @@ def handle(self): package = self.poetry.package self.line( - "Building {} ({})".format( + "Building {} ({})".format( package.pretty_name, package.version ) ) - builder = Builder(self.poetry, self.env, self.io) + builder = Builder(self.poetry) builder.build(fmt) diff --git a/poetry/console/commands/debug/resolve.py b/poetry/console/commands/debug/resolve.py index c6ff0d19feb..f58b09cbbb1 100644 --- a/poetry/console/commands/debug/resolve.py +++ b/poetry/console/commands/debug/resolve.py @@ -29,7 +29,8 @@ class DebugResolveCommand(InitCommand): def handle(self): from poetry.io.null_io import NullIO - from poetry.packages import ProjectPackage + from poetry.core.packages import ProjectPackage + from poetry.installation.installer import Installer from poetry.puzzle import Solver from poetry.repositories.pool import Pool from poetry.repositories.repository import Repository @@ -114,10 +115,15 @@ def handle(self): pool.add_repository(locked_repository) with package.with_python_versions(current_python_version): + installer = Installer(NullIO(), env, package, self.poetry.locker, pool) solver = Solver(package, pool, Repository(), Repository(), NullIO()) ops = solver.solve() + installer._filter_operations(ops, Repository()) for op in ops: + if self.option("install") and op.skipped: + continue + pkg = op.package row = [ "{}".format(pkg.name), diff --git a/poetry/console/commands/export.py b/poetry/console/commands/export.py index 37cfc1394e8..2a966792aad 100644 --- a/poetry/console/commands/export.py +++ b/poetry/console/commands/export.py @@ -11,7 +11,13 @@ class ExportCommand(Command): description = "Exports the lock file to alternative formats." options = [ - option("format", "f", "Format to export to.", flag=False), + option( + "format", + "f", + "Format to export to.", + flag=False, + default=Exporter.FORMAT_REQUIREMENTS_TXT, + ), option("output", "o", "The name of the output file.", flag=False), option("without-hashes", None, "Exclude hashes from the exported file."), option("dev", None, "Include development dependencies."), diff --git a/poetry/console/commands/init.py b/poetry/console/commands/init.py index 40ed33a17f1..3af482b8818 100644 --- a/poetry/console/commands/init.py +++ b/poetry/console/commands/init.py @@ -64,7 +64,7 @@ def handle(self): from poetry.layouts import layout from poetry.utils._compat import Path from poetry.utils.env import SystemEnv - from poetry.vcs.git import GitConfig + from poetry.core.vcs.git import GitConfig if (Path.cwd() / "pyproject.toml").exists(): self.line("A pyproject.toml file already exists.") @@ -367,8 +367,8 @@ def _parse_requirements( if url_parsed.scheme and url_parsed.netloc: # Url if url_parsed.scheme in ["git+https", "git+ssh"]: - from poetry.vcs.git import Git - from poetry.vcs.git import ParsedUrl + from poetry.core.vcs.git import Git + from poetry.core.vcs.git import ParsedUrl parsed = ParsedUrl.parse(requirement) url = Git.normalize_url(requirement) @@ -481,7 +481,7 @@ def _format_requirements( return requires def _validate_author(self, author, default): - from poetry.packages.package import AUTHOR_REGEX + from poetry.core.packages.package import AUTHOR_REGEX author = author or default @@ -498,7 +498,7 @@ def _validate_author(self, author, default): return author def _validate_license(self, license): - from poetry.spdx import license_by_id + from poetry.core.spdx import license_by_id if license: license_by_id(license) diff --git a/poetry/console/commands/install.py b/poetry/console/commands/install.py index 0daec01fe12..12bd3e64e0a 100644 --- a/poetry/console/commands/install.py +++ b/poetry/console/commands/install.py @@ -47,7 +47,7 @@ def handle(self): from clikit.io import NullIO from poetry.installation.installer import Installer from poetry.masonry.builders import EditableBuilder - from poetry.masonry.utils.module import ModuleOrPackageNotFound + from poetry.core.masonry.utils.module import ModuleOrPackageNotFound installer = Installer( self.io, self.env, self.poetry.package, self.poetry.locker, self.poetry.pool @@ -83,7 +83,7 @@ def handle(self): return 0 self.line( - " - Installing {} ({})".format( + " - Installing {} ({})".format( self.poetry.package.pretty_name, self.poetry.package.pretty_version ) ) diff --git a/poetry/console/commands/new.py b/poetry/console/commands/new.py index 5159f88bd30..53e61702f90 100644 --- a/poetry/console/commands/new.py +++ b/poetry/console/commands/new.py @@ -21,10 +21,10 @@ class NewCommand(Command): def handle(self): from poetry.layouts import layout - from poetry.semver import parse_constraint + from poetry.core.semver import parse_constraint from poetry.utils._compat import Path from poetry.utils.env import SystemEnv - from poetry.vcs.git import GitConfig + from poetry.core.vcs.git import GitConfig if self.option("src"): layout_ = layout("src") diff --git a/poetry/console/commands/publish.py b/poetry/console/commands/publish.py index edbdadb140d..557cd1d7ab7 100644 --- a/poetry/console/commands/publish.py +++ b/poetry/console/commands/publish.py @@ -26,6 +26,7 @@ class PublishCommand(Command): flag=False, ), option("build", None, "Build the package before publishing."), + option("dry-run", None, "Perform all actions except upload the package."), ] help = """The publish command builds and uploads the package to a remote repository. @@ -40,7 +41,7 @@ class PublishCommand(Command): loggers = ["poetry.masonry.publishing.publisher"] def handle(self): - from poetry.masonry.publishing.publisher import Publisher + from poetry.publishing.publisher import Publisher publisher = Publisher(self.poetry, self.io) @@ -79,4 +80,5 @@ def handle(self): self.option("password"), cert, client_cert, + self.option("dry-run"), ) diff --git a/poetry/console/commands/run.py b/poetry/console/commands/run.py index d9e9b7639d9..fda01114426 100644 --- a/poetry/console/commands/run.py +++ b/poetry/console/commands/run.py @@ -50,7 +50,7 @@ def run_script(self, script, args): @property def _module(self): - from ...masonry.utils.module import Module + from poetry.core.masonry.utils.module import Module poetry = self.poetry package = poetry.package diff --git a/poetry/console/commands/self/update.py b/poetry/console/commands/self/update.py index 032213ae0ce..dcfb2967a71 100644 --- a/poetry/console/commands/self/update.py +++ b/poetry/console/commands/self/update.py @@ -37,11 +37,8 @@ class SelfUpdateCommand(Command): @property def home(self): from poetry.utils._compat import Path - from poetry.utils.appdirs import expanduser - home = Path(expanduser("~")) - - return home / ".poetry" + return Path(os.environ.get("POETRY_HOME", "~/.poetry")).expanduser() @property def lib(self): @@ -54,7 +51,7 @@ def lib_backup(self): def handle(self): from poetry.__version__ import __version__ from poetry.repositories.pypi_repository import PyPiRepository - from poetry.semver import Version + from poetry.core.semver import Version from poetry.utils._compat import Path current = Path(__file__) diff --git a/poetry/console/commands/show.py b/poetry/console/commands/show.py index c689853a92c..24caae800bf 100644 --- a/poetry/console/commands/show.py +++ b/poetry/console/commands/show.py @@ -35,7 +35,7 @@ class ShowCommand(EnvCommand): def handle(self): from clikit.utils.terminal import Terminal from poetry.repositories.installed_repository import InstalledRepository - from poetry.semver import Version + from poetry.core.semver import Version package = self.argument("package") @@ -347,7 +347,7 @@ def find_latest_package(self, package, include_dev): return selector.find_best_candidate(name, ">={}".format(package.pretty_version)) def get_update_status(self, latest, package): - from poetry.semver import parse_constraint + from poetry.core.semver import parse_constraint if latest.full_pretty_version == package.full_pretty_version: return "up-to-date" diff --git a/poetry/console/commands/version.py b/poetry/console/commands/version.py index ab1ad276e1c..21ed676f54f 100644 --- a/poetry/console/commands/version.py +++ b/poetry/console/commands/version.py @@ -1,4 +1,5 @@ from cleo import argument +from cleo import option from .command import Command @@ -18,6 +19,7 @@ class VersionCommand(Command): optional=True, ) ] + options = [option("short", "s", "Output the version number only")] help = """\ The version command shows the current version of the project or bumps the version of @@ -58,14 +60,17 @@ def handle(self): self.poetry.file.write(content) else: - self.line( - "{} {}".format( - self.poetry.package.name, self.poetry.package.pretty_version + if self.option("short"): + self.line("{}".format(self.poetry.package.pretty_version)) + else: + self.line( + "{} {}".format( + self.poetry.package.name, self.poetry.package.pretty_version + ) ) - ) def increment_version(self, version, rule): - from poetry.semver import Version + from poetry.core.semver import Version try: version = Version.parse(version) diff --git a/poetry/console/config/application_config.py b/poetry/console/config/application_config.py index 97570956b09..e8f752752fd 100644 --- a/poetry/console/config/application_config.py +++ b/poetry/console/config/application_config.py @@ -36,11 +36,12 @@ def configure(self): super(ApplicationConfig, self).configure() self.add_style(Style("c1").fg("cyan")) + self.add_style(Style("c2").fg("green")) self.add_style(Style("info").fg("blue")) self.add_style(Style("comment").fg("green")) self.add_style(Style("error").fg("red").bold()) - self.add_style(Style("warning").fg("yellow")) - self.add_style(Style("debug").fg("black").bold()) + self.add_style(Style("warning").fg("yellow").bold()) + self.add_style(Style("debug").fg("default").dark()) self.add_event_listener(PRE_HANDLE, self.register_command_loggers) self.add_event_listener(PRE_HANDLE, self.set_env) diff --git a/poetry/console/logging/formatters/__init__.py b/poetry/console/logging/formatters/__init__.py new file mode 100644 index 00000000000..247f51bec8e --- /dev/null +++ b/poetry/console/logging/formatters/__init__.py @@ -0,0 +1,7 @@ +from .builder_formatter import BuilderLogFormatter + + +FORMATTERS = { + "poetry.core.masonry.builders.sdist": BuilderLogFormatter(), + "poetry.core.masonry.builders.wheel": BuilderLogFormatter(), +} diff --git a/poetry/console/logging/formatters/builder_formatter.py b/poetry/console/logging/formatters/builder_formatter.py new file mode 100644 index 00000000000..df2f7e301fa --- /dev/null +++ b/poetry/console/logging/formatters/builder_formatter.py @@ -0,0 +1,13 @@ +import re + +from .formatter import Formatter + + +class BuilderLogFormatter(Formatter): + def format(self, msg): # type: (str) -> str + if msg.startswith(" - Building ") or msg.startswith(" - Built "): + msg = re.sub(r" - (Buil(?:t|ing)) (.+)", " - \\1 \\2", msg) + elif msg.startswith(" - Adding: "): + msg = re.sub(r" - Adding: (.+)", " - Adding: \\1", msg) + + return msg diff --git a/poetry/console/logging/formatters/formatter.py b/poetry/console/logging/formatters/formatter.py new file mode 100644 index 00000000000..35b59374be4 --- /dev/null +++ b/poetry/console/logging/formatters/formatter.py @@ -0,0 +1,6 @@ +import logging + + +class Formatter(object): + def format(self, record): # type: (logging.LogRecord) -> str + raise NotImplementedError() diff --git a/poetry/console/logging/io_formatter.py b/poetry/console/logging/io_formatter.py index c9e389a3e4b..9ff57fec761 100644 --- a/poetry/console/logging/io_formatter.py +++ b/poetry/console/logging/io_formatter.py @@ -1,5 +1,7 @@ import logging +from .formatters import FORMATTERS + class IOFormatter(logging.Formatter): @@ -15,7 +17,9 @@ def format(self, record): level = record.levelname.lower() msg = record.msg - if level in self._colors: + if record.name in FORMATTERS: + msg = FORMATTERS[record.name].format(msg) + elif level in self._colors: msg = "<{}>{}".format(self._colors[level], msg) return msg diff --git a/poetry/factory.py b/poetry/factory.py index 90c9cec3295..48cac9809da 100644 --- a/poetry/factory.py +++ b/poetry/factory.py @@ -1,30 +1,25 @@ from __future__ import absolute_import from __future__ import unicode_literals -import shutil - from typing import Dict -from typing import List from typing import Optional from clikit.api.io.io import IO +from poetry.core.factory import Factory as BaseFactory +from poetry.core.utils.toml_file import TomlFile + from .config.config import Config from .config.file_config_source import FileConfigSource from .io.null_io import NullIO -from .json import validate_object from .locations import CONFIG_DIR -from .packages.dependency import Dependency from .packages.locker import Locker -from .packages.project_package import ProjectPackage from .poetry import Poetry from .repositories.pypi_repository import PyPiRepository -from .spdx import license_by_id from .utils._compat import Path -from .utils.toml_file import TomlFile -class Factory: +class Factory(BaseFactory): """ Factory class to create various elements needed by Poetry. """ @@ -35,125 +30,17 @@ def create_poetry( if io is None: io = NullIO() - poetry_file = self.locate(cwd) - - local_config = TomlFile(poetry_file.as_posix()).read() - if "tool" not in local_config or "poetry" not in local_config["tool"]: - raise RuntimeError( - "[tool.poetry] section not found in {}".format(poetry_file.name) - ) - local_config = local_config["tool"]["poetry"] - - # Checking validity - check_result = self.validate(local_config) - if check_result["errors"]: - message = "" - for error in check_result["errors"]: - message += " - {}\n".format(error) - - raise RuntimeError("The Poetry configuration is invalid:\n" + message) - - # Load package - name = local_config["name"] - version = local_config["version"] - package = ProjectPackage(name, version, version) - package.root_dir = poetry_file.parent - - for author in local_config["authors"]: - package.authors.append(author) - - for maintainer in local_config.get("maintainers", []): - package.maintainers.append(maintainer) - - package.description = local_config.get("description", "") - package.homepage = local_config.get("homepage") - package.repository_url = local_config.get("repository") - package.documentation_url = local_config.get("documentation") - try: - license_ = license_by_id(local_config.get("license", "")) - except ValueError: - license_ = None - - package.license = license_ - package.keywords = local_config.get("keywords", []) - package.classifiers = local_config.get("classifiers", []) - - if "readme" in local_config: - package.readme = Path(poetry_file.parent) / local_config["readme"] - - if "platform" in local_config: - package.platform = local_config["platform"] - - if "dependencies" in local_config: - for name, constraint in local_config["dependencies"].items(): - if name.lower() == "python": - package.python_versions = constraint - continue - - if isinstance(constraint, list): - for _constraint in constraint: - package.add_dependency(name, _constraint) - - continue - - package.add_dependency(name, constraint) - - if "dev-dependencies" in local_config: - for name, constraint in local_config["dev-dependencies"].items(): - if isinstance(constraint, list): - for _constraint in constraint: - package.add_dependency(name, _constraint, category="dev") - - continue - - package.add_dependency(name, constraint, category="dev") - - extras = local_config.get("extras", {}) - for extra_name, requirements in extras.items(): - package.extras[extra_name] = [] - - # Checking for dependency - for req in requirements: - req = Dependency(req, "*") - - for dep in package.requires: - if dep.name == req.name: - dep.in_extras.append(extra_name) - package.extras[extra_name].append(dep) - - break - - if "build" in local_config: - package.build = local_config["build"] - - if "include" in local_config: - package.include = local_config["include"] + base_poetry = super(Factory, self).create_poetry(cwd) - if "exclude" in local_config: - package.exclude = local_config["exclude"] - - if "packages" in local_config: - package.packages = local_config["packages"] - - # Custom urls - if "urls" in local_config: - package.custom_urls = local_config["urls"] - - # Moving lock if necessary (pyproject.lock -> poetry.lock) - lock = poetry_file.parent / "poetry.lock" - if not lock.exists(): - # Checking for pyproject.lock - old_lock = poetry_file.with_suffix(".lock") - if old_lock.exists(): - shutil.move(str(old_lock), str(lock)) - - locker = Locker(poetry_file.parent / "poetry.lock", local_config) + locker = Locker( + base_poetry.file.parent / "poetry.lock", base_poetry.local_config + ) # Loading global configuration config = self.create_config(io) # Loading local configuration - local_config_file = TomlFile(poetry_file.parent / "poetry.toml") + local_config_file = TomlFile(base_poetry.file.parent / "poetry.toml") if local_config_file.exists(): if io.is_debug(): io.write_line( @@ -162,10 +49,16 @@ def create_poetry( config.merge(local_config_file.read()) - poetry = Poetry(poetry_file, local_config, package, locker, config) + poetry = Poetry( + base_poetry.file.path, + base_poetry.local_config, + base_poetry.package, + locker, + config, + ) # Configuring sources - for source in local_config.get("source", []): + for source in poetry.local_config.get("source", []): repository = self.create_legacy_repository(source, config) is_default = source.get("default", False) is_secondary = source.get("secondary", False) @@ -259,82 +152,3 @@ def create_legacy_repository( cert=get_cert(auth_config, name), client_cert=get_client_cert(auth_config, name), ) - - @classmethod - def validate( - cls, config, strict=False - ): # type: (dict, bool) -> Dict[str, List[str]] - """ - Checks the validity of a configuration - """ - result = {"errors": [], "warnings": []} - # Schema validation errors - validation_errors = validate_object(config, "poetry-schema") - - result["errors"] += validation_errors - - if strict: - # If strict, check the file more thoroughly - - # Checking license - license = config.get("license") - if license: - try: - license_by_id(license) - except ValueError: - result["errors"].append("{} is not a valid license".format(license)) - - if "dependencies" in config: - python_versions = config["dependencies"]["python"] - if python_versions == "*": - result["warnings"].append( - "A wildcard Python dependency is ambiguous. " - "Consider specifying a more explicit one." - ) - - for name, constraint in config["dependencies"].items(): - if not isinstance(constraint, dict): - continue - - if "allows-prereleases" in constraint: - result["warnings"].append( - 'The "{}" dependency specifies ' - 'the "allows-prereleases" property, which is deprecated. ' - 'Use "allow-prereleases" instead.'.format(name) - ) - - # Checking for scripts with extras - if "scripts" in config: - scripts = config["scripts"] - for name, script in scripts.items(): - if not isinstance(script, dict): - continue - - extras = script["extras"] - for extra in extras: - if extra not in config["extras"]: - result["errors"].append( - 'Script "{}" requires extra "{}" which is not defined.'.format( - name, extra - ) - ) - - return result - - @classmethod - def locate(cls, cwd): # type: (Path) -> Path - candidates = [Path(cwd)] - candidates.extend(Path(cwd).parents) - - for path in candidates: - poetry_file = path / "pyproject.toml" - - if poetry_file.exists(): - return poetry_file - - else: - raise RuntimeError( - "Poetry could not find a pyproject.toml file in {} or its parents".format( - cwd - ) - ) diff --git a/poetry/masonry/utils/__init__.py b/poetry/inspection/__init__.py similarity index 100% rename from poetry/masonry/utils/__init__.py rename to poetry/inspection/__init__.py diff --git a/poetry/inspection/info.py b/poetry/inspection/info.py new file mode 100644 index 00000000000..50ef2793e5b --- /dev/null +++ b/poetry/inspection/info.py @@ -0,0 +1,499 @@ +import glob +import logging +import os +import tarfile +import zipfile + +from typing import Dict +from typing import Iterator +from typing import List +from typing import Optional +from typing import Union + +import pkginfo + +from poetry.core.factory import Factory +from poetry.core.packages import Package +from poetry.core.packages import ProjectPackage +from poetry.core.packages import dependency_from_pep_508 +from poetry.core.utils._compat import PY35 +from poetry.core.utils._compat import Path +from poetry.core.utils.helpers import parse_requires +from poetry.core.utils.helpers import temporary_directory +from poetry.core.version.markers import InvalidMarker +from poetry.utils.env import EnvCommandError +from poetry.utils.env import EnvManager +from poetry.utils.env import VirtualEnv +from poetry.utils.setup_reader import SetupReader +from poetry.utils.toml_file import TomlFile + + +logger = logging.getLogger(__name__) + + +class PackageInfoError(ValueError): + def __init__(self, path): # type: (Union[Path, str]) -> None + super(PackageInfoError, self).__init__( + "Unable to determine package info for path: {}".format(str(path)) + ) + + +class PackageInfo: + def __init__( + self, + name=None, # type: Optional[str] + version=None, # type: Optional[str] + summary=None, # type: Optional[str] + platform=None, # type: Optional[str] + requires_dist=None, # type: Optional[List[str]] + requires_python=None, # type: Optional[str] + files=None, # type: Optional[List[str]] + cache_version=None, # type: Optional[str] + ): + self.name = name + self.version = version + self.summary = summary + self.platform = platform + self.requires_dist = requires_dist + self.requires_python = requires_python + self.files = files or [] + self._cache_version = cache_version + + @property + def cache_version(self): # type: () -> Optional[str] + return self._cache_version + + def update(self, other): # type: (PackageInfo) -> PackageInfo + self.name = other.name or self.name + self.version = other.version or self.version + self.summary = other.summary or self.summary + self.platform = other.platform or self.platform + self.requires_dist = other.requires_dist or self.requires_dist + self.requires_python = other.requires_python or self.requires_python + self.files = other.files or self.files + self._cache_version = other.cache_version or self._cache_version + return self + + def asdict(self): # type: () -> Dict[str, Optional[Union[str, List[str]]]] + """ + Helper method to convert package info into a dictionary used for caching. + """ + return { + "name": self.name, + "version": self.version, + "summary": self.summary, + "platform": self.platform, + "requires_dist": self.requires_dist, + "requires_python": self.requires_python, + "files": self.files, + "_cache_version": self._cache_version, + } + + @classmethod + def load( + cls, data + ): # type: (Dict[str, Optional[Union[str, List[str]]]]) -> PackageInfo + """ + Helper method to load data from a dictionary produced by `PackageInfo.asdict()`. + + :param data: Data to load. This is expected to be a `dict` object output by `asdict()`. + """ + cache_version = data.pop("_cache_version", None) + return cls(cache_version=cache_version, **data) + + @classmethod + def _log(cls, msg, level="info"): + """Internal helper method to log information.""" + getattr(logger, level)("{}: {}".format(cls.__name__, msg)) + + def to_package( + self, name=None, extras=None, root_dir=None + ): # type: (Optional[str], Optional[List[str]], Optional[Path]) -> Package + """ + Create a new `poetry.core.packages.package.Package` instance using metadata from this instance. + + :param name: Name to use for the package, if not specified name from this instance is used. + :param extras: Extras to activate for this package. + :param root_dir: Optional root directory to use for the package. If set, dependency strings + will be parsed relative to this directory. + """ + name = name or self.name + + if not self.version: + # The version could not be determined, so we raise an error since it is mandatory. + raise RuntimeError( + "Unable to retrieve the package version for {}".format(name) + ) + + package = Package(name=name, version=self.version) + package.description = self.summary + package.root_dir = root_dir + package.python_versions = self.requires_python or "*" + package.files = self.files + + for req in self.requires_dist or []: + try: + # Attempt to parse the PEP-508 requirement string + dependency = dependency_from_pep_508(req, relative_to=root_dir) + except InvalidMarker: + # Invalid marker, We strip the markers hoping for the best + req = req.split(";")[0] + dependency = dependency_from_pep_508(req, relative_to=root_dir) + except ValueError: + # Likely unable to parse constraint so we skip it + self._log( + "Invalid constraint ({}) found in {}-{} dependencies, " + "skipping".format(req, package.name, package.version), + level="debug", + ) + continue + + if dependency.in_extras: + # this dependency is required by an extra package + for extra in dependency.in_extras: + if extra not in package.extras: + # this is the first time we encounter this extra for this package + package.extras[extra] = [] + + # Activate extra dependencies if specified + if extras and extra in extras: + dependency.activate() + + package.extras[extra].append(dependency) + + if not dependency.is_optional() or dependency.is_activated(): + # we skip add only if the dependency is option and was not activated as part of an extra + package.requires.append(dependency) + + return package + + @classmethod + def _from_distribution( + cls, dist + ): # type: (Union[pkginfo.BDist, pkginfo.SDist, pkginfo.Wheel]) -> PackageInfo + """ + Helper method to parse package information from a `pkginfo.Distribution` instance. + + :param dist: The distribution instance to parse information from. + """ + if dist.requires_dist: + requirements = list(dist.requires_dist) + else: + requirements = [] + requires = Path(dist.filename) / "requires.txt" + if requires.exists(): + with requires.open(encoding="utf-8") as f: + requirements = parse_requires(f.read()) + + return cls( + name=dist.name, + version=dist.version, + summary=dist.summary, + platform=dist.supported_platforms, + requires_dist=requirements or None, + requires_python=dist.requires_python, + ) + + @classmethod + def _from_sdist_file(cls, path): # type: (Path) -> PackageInfo + """ + Helper method to parse package information from an sdist file. We attempt to first inspect the + file using `pkginfo.SDist`. If this does not provide us with package requirements, we extract the + source and handle it as a directory. + + :param path: The sdist file to parse information from. + """ + info = None + + try: + info = cls._from_distribution(pkginfo.SDist(str(path))) + except ValueError: + # Unable to determine dependencies + # We pass and go deeper + pass + else: + if info.requires_dist is not None: + # we successfully retrieved dependencies from sdist metadata + return info + + # Still not dependencies found + # So, we unpack and introspect + suffix = path.suffix + + if suffix == ".zip": + context = zipfile.ZipFile + else: + if suffix == ".bz2": + suffixes = path.suffixes + if len(suffixes) > 1 and suffixes[-2] == ".tar": + suffix = ".tar.bz2" + else: + suffix = ".tar.gz" + + context = tarfile.open + + with temporary_directory() as tmp: + tmp = Path(tmp) + with context(str(path)) as archive: + archive.extractall(str(tmp)) + + # a little bit of guess work to determine the directory we care about + elements = list(tmp.glob("*")) + + if len(elements) == 1 and elements[0].is_dir(): + sdist_dir = elements[0] + else: + sdist_dir = tmp / path.name.rstrip(suffix) + + # now this is an unpacked directory we know how to deal with + new_info = cls.from_directory(path=sdist_dir) + + if not info: + return new_info + + return info.update(new_info) + + @classmethod + def from_setup_py(cls, path): # type: (Union[str, Path]) -> PackageInfo + """ + Mechanism to parse package information from a `setup.py` file. This uses the implentation + at `poetry.utils.setup_reader.SetupReader` in order to parse the file. This is not reliable for + complex setup files and should only attempted as a fallback. + + :param path: Path to `setup.py` file + :return: + """ + result = SetupReader.read_from_directory(Path(path)) + python_requires = result["python_requires"] + if python_requires is None: + python_requires = "*" + + requires = "" + for dep in result["install_requires"]: + requires += dep + "\n" + + if result["extras_require"]: + requires += "\n" + + for extra_name, deps in result["extras_require"].items(): + requires += "[{}]\n".format(extra_name) + + for dep in deps: + requires += dep + "\n" + + requires += "\n" + + requirements = parse_requires(requires) + + return cls( + name=result.get("name"), + version=result.get("version"), + summary=result.get("description", ""), + requires_dist=requirements or None, + requires_python=python_requires, + ) + + @staticmethod + def _find_dist_info(path): # type: (Path) -> Iterator[Path] + """ + Discover all `*.*-info` directories in a given path. + + :param path: Path to search. + """ + pattern = "**/*.*-info" + if PY35: + # Sometimes pathlib will fail on recursive symbolic links, so we need to workaround it + # and use the glob module instead. Note that this does not happen with pathlib2 + # so it's safe to use it for Python < 3.4. + directories = glob.iglob(Path(path, pattern).as_posix(), recursive=True) + else: + directories = path.glob(pattern) + + for d in directories: + yield Path(d) + + @classmethod + def from_metadata(cls, path): # type: (Union[str, Path]) -> PackageInfo + """ + Helper method to parse package information from an unpacked metadata directory. + + :param path: The metadata directory to parse information from. + """ + path = Path(path) + + if path.suffix in {".dist-info", ".egg-info"}: + directories = [path.suffix] + else: + directories = cls._find_dist_info(path=path) + + for directory in directories: + try: + if directory.suffix == ".egg-info": + dist = pkginfo.UnpackedSDist(str(directory)) + elif directory.suffix == ".dist-info": + dist = pkginfo.Wheel(str(directory)) + else: + continue + info = cls._from_distribution(dist=dist) + if info: + return info + except ValueError: + pass + + @classmethod + def from_package(cls, package): # type: (Package) -> PackageInfo + """ + Helper method to inspect a `Package` object, in order to generate package info. + + :param package: This must be a poetry package instance. + """ + requires = {dependency.to_pep_508() for dependency in package.requires} + + for extra_requires in package.extras.values(): + for dependency in extra_requires: + requires.add(dependency.to_pep_508()) + + return cls( + name=package.name, + version=package.version, + summary=package.description, + platform=package.platform, + requires_dist=list(requires), + requires_python=package.python_versions, + files=package.files, + ) + + @staticmethod + def _get_poetry_package(path): # type: (Path) -> Optional[ProjectPackage] + pyproject = path.joinpath("pyproject.toml") + try: + # Note: we ignore any setup.py file at this step + if pyproject.exists(): + # TODO: add support for handling non-poetry PEP-517 builds + pyproject = TomlFile(pyproject) + pyproject_content = pyproject.read() + supports_poetry = ( + "tool" in pyproject_content + and "poetry" in pyproject_content["tool"] + ) + if supports_poetry: + return Factory().create_poetry(path).package + except RuntimeError: + pass + + @classmethod + def from_directory( + cls, path, allow_build=False + ): # type: (Union[str, Path], bool) -> PackageInfo + """ + Generate package information from a package source directory. When `allow_build` is enabled and + introspection of all available metadata fails, the package is attempted to be build in an isolated + environment so as to generate required metadata. + + :param path: Path to generate package information from. + :param allow_build: If enabled, as a fallback, build the project to gather metadata. + """ + path = Path(path) + + setup_py = path.joinpath("setup.py") + + project_package = cls._get_poetry_package(path) + if project_package: + return cls.from_package(project_package) + + if not setup_py.exists(): + # this means we cannot do anything else here + raise PackageInfoError(path) + + current_dir = os.getcwd() + + info = cls.from_metadata(path) + + if info and info.requires_dist is not None: + # return only if requirements are discovered + return info + + if not allow_build: + return cls.from_setup_py(path=path) + + try: + # TODO: replace with PEP517 + # we need to switch to the correct path in order for egg_info command to work + os.chdir(str(path)) + + # Execute egg_info + with temporary_directory() as tmp_dir: + EnvManager.build_venv(tmp_dir) + venv = VirtualEnv(Path(tmp_dir), Path(tmp_dir)) + venv.run("python", "setup.py", "egg_info") + except EnvCommandError: + cls._log( + "Falling back to parsing setup.py file for {}".format(path), "debug" + ) + # egg_info could not be generated, we fallback to ast parser + return cls.from_setup_py(path=path) + else: + info = cls.from_metadata(path) + if info: + return info + finally: + os.chdir(current_dir) + + # if we reach here, everything has failed and all hope is lost + raise PackageInfoError(path) + + @classmethod + def from_sdist(cls, path): # type: (Union[Path, pkginfo.SDist]) -> PackageInfo + """ + Gather package information from an sdist file, packed or unpacked. + + :param path: Path to an sdist file or unpacked directory. + """ + if path.is_file(): + return cls._from_sdist_file(path=path) + + # if we get here then it is neither an sdist instance nor a file + # so, we assume this is an directory + return cls.from_directory(path=path) + + @classmethod + def from_wheel(cls, path): # type: (Path) -> PackageInfo + """ + Gather package information from a wheel. + + :param path: Path to wheel. + """ + try: + return cls._from_distribution(pkginfo.Wheel(str(path))) + except ValueError: + return PackageInfo() + + @classmethod + def from_bdist(cls, path): # type: (Path) -> PackageInfo + """ + Gather package information from a bdist (wheel etc.). + + :param path: Path to bdist. + """ + if isinstance(path, (pkginfo.BDist, pkginfo.Wheel)): + cls._from_distribution(dist=path) + + if path.suffix == ".whl": + return cls.from_wheel(path=path) + + try: + return cls._from_distribution(pkginfo.BDist(str(path))) + except ValueError: + raise PackageInfoError(path) + + @classmethod + def from_path(cls, path): # type: (Path) -> PackageInfo + """ + Gather package information from a given path (bdist, sdist, directory). + + :param path: Path to inspect. + """ + try: + return cls.from_bdist(path=path) + except PackageInfoError: + return cls.from_sdist(path=path) diff --git a/poetry/installation/installer.py b/poetry/installation/installer.py index 78efa9a01cd..1bcd3da228d 100644 --- a/poetry/installation/installer.py +++ b/poetry/installation/installer.py @@ -2,10 +2,10 @@ from typing import Union from clikit.api.io import IO -from clikit.io import NullIO +from poetry.core.packages.package import Package +from poetry.core.semver import parse_constraint from poetry.packages import Locker -from poetry.packages import Package from poetry.puzzle import Solver from poetry.puzzle.operations import Install from poetry.puzzle.operations import Uninstall @@ -14,7 +14,6 @@ from poetry.repositories import Pool from poetry.repositories import Repository from poetry.repositories.installed_repository import InstalledRepository -from poetry.semver import parse_constraint from poetry.utils.extras import get_extra_package_names from poetry.utils.helpers import canonicalize_name @@ -206,33 +205,6 @@ def _do_install(self, local_repo): root = root.clone() del root.dev_requires[:] - with root.with_python_versions( - ".".join([str(i) for i in self._env.version_info[:3]]) - ): - # We resolve again by only using the lock file - pool = Pool(ignore_repository_names=True) - - # Making a new repo containing the packages - # newly resolved and the ones from the current lock file - repo = Repository() - for package in local_repo.packages + locked_repository.packages: - if not repo.has_package(package): - repo.add_package(package) - - pool.add_repository(repo) - - # We whitelist all packages to be sure - # that the latest ones are picked up - whitelist = [] - for pkg in locked_repository.packages: - whitelist.append(pkg.name) - - solver = Solver( - root, pool, self._installed_repository, locked_repository, NullIO() - ) - - ops = solver.solve(use_latest=whitelist) - # We need to filter operations so that packages # not compatible with the current system, # or optional and not requested, are dropped @@ -314,7 +286,7 @@ def _execute_install(self, operation): # type: (Install) -> None if operation.skipped: if self.is_verbose() and (self._execute_operations or self.is_dry_run()): self._io.write_line( - " - Skipping {} ({}) {}".format( + " - Skipping {} ({}) {}".format( operation.package.pretty_name, operation.package.full_pretty_version, operation.skip_reason, @@ -325,7 +297,7 @@ def _execute_install(self, operation): # type: (Install) -> None if self._execute_operations or self.is_dry_run(): self._io.write_line( - " - Installing {} ({})".format( + " - Installing {} ({})".format( operation.package.pretty_name, operation.package.full_pretty_version ) ) @@ -342,7 +314,7 @@ def _execute_update(self, operation): # type: (Update) -> None if operation.skipped: if self.is_verbose() and (self._execute_operations or self.is_dry_run()): self._io.write_line( - " - Skipping {} ({}) {}".format( + " - Skipping {} ({}) {}".format( target.pretty_name, target.full_pretty_version, operation.skip_reason, @@ -353,7 +325,7 @@ def _execute_update(self, operation): # type: (Update) -> None if self._execute_operations or self.is_dry_run(): self._io.write_line( - " - Updating {} ({} -> {})".format( + " - Updating {} ({} -> {})".format( target.pretty_name, source.full_pretty_version, target.full_pretty_version, @@ -369,7 +341,7 @@ def _execute_uninstall(self, operation): # type: (Uninstall) -> None if operation.skipped: if self.is_verbose() and (self._execute_operations or self.is_dry_run()): self._io.write_line( - " - Not removing {} ({}) {}".format( + " - Not removing {} ({}) {}".format( operation.package.pretty_name, operation.package.full_pretty_version, operation.skip_reason, @@ -380,7 +352,7 @@ def _execute_uninstall(self, operation): # type: (Uninstall) -> None if self._execute_operations or self.is_dry_run(): self._io.write_line( - " - Removing {} ({})".format( + " - Removing {} ({})".format( operation.package.pretty_name, operation.package.full_pretty_version ) ) diff --git a/poetry/installation/pip_installer.py b/poetry/installation/pip_installer.py index aada0cd0190..44c7ecc37ad 100644 --- a/poetry/installation/pip_installer.py +++ b/poetry/installation/pip_installer.py @@ -5,7 +5,6 @@ from subprocess import CalledProcessError from clikit.api.io import IO -from clikit.io import NullIO from poetry.repositories.pool import Pool from poetry.utils._compat import encode @@ -176,10 +175,9 @@ def create_temporary_requirement(self, package): return name def install_directory(self, package): - from poetry.masonry.builder import SdistBuilder + from poetry.core.masonry.builder import SdistBuilder from poetry.factory import Factory from poetry.utils._compat import decode - from poetry.utils.env import NullEnv from poetry.utils.toml_file import TomlFile if package.root_dir: @@ -210,9 +208,7 @@ def install_directory(self, package): # file since pip, as of this comment, does not support # build-system for editable packages # We also need it for non-PEP-517 packages - builder = SdistBuilder( - Factory().create_poetry(pyproject.parent), NullEnv(), NullIO() - ) + builder = SdistBuilder(Factory().create_poetry(pyproject.parent),) with open(setup, "w", encoding="utf-8") as f: f.write(decode(builder.build_setup())) @@ -229,8 +225,8 @@ def install_directory(self, package): os.remove(setup) def install_git(self, package): - from poetry.packages import Package - from poetry.vcs import Git + from poetry.core.packages import Package + from poetry.core.vcs import Git src_dir = self._env.path / "src" / package.name if src_dir.exists(): diff --git a/poetry/json/schemas/poetry-schema.json b/poetry/json/schemas/poetry-schema.json index 10aff39e502..e94b90d28cc 100644 --- a/poetry/json/schemas/poetry-schema.json +++ b/poetry/json/schemas/poetry-schema.json @@ -460,6 +460,9 @@ }, { "$ref": "#/definitions/path-dependency" + }, + { + "$ref": "#/definitions/url-dependency" } ] } diff --git a/poetry/layouts/layout.py b/poetry/layouts/layout.py index f47157d7d25..a7378c67c4c 100644 --- a/poetry/layouts/layout.py +++ b/poetry/layouts/layout.py @@ -38,7 +38,7 @@ def test_version(): [tool.poetry.dev-dependencies] """ -BUILD_SYSTEM_MIN_VERSION = "0.12" +BUILD_SYSTEM_MIN_VERSION = "1.0.0a5" BUILD_SYSTEM_MAX_VERSION = None @@ -109,8 +109,8 @@ def generate_poetry_content(self): if BUILD_SYSTEM_MAX_VERSION is not None: build_system_version += ",<" + BUILD_SYSTEM_MAX_VERSION - build_system.add("requires", ["poetry" + build_system_version]) - build_system.add("build-backend", "poetry.masonry.api") + build_system.add("requires", ["poetry-core" + build_system_version]) + build_system.add("build-backend", "poetry.core.masonry.api") content.add("build-system", build_system) diff --git a/poetry/masonry/__init__.py b/poetry/masonry/__init__.py index ddd3a14f153..e69de29bb2d 100644 --- a/poetry/masonry/__init__.py +++ b/poetry/masonry/__init__.py @@ -1,10 +0,0 @@ -""" -This module handles the packaging and publishing -of python projects. - -A lot of the code used here has been taken from -`flit `__ and adapted -to work with the poetry codebase, so kudos to them for showing the way. -""" - -from .builder import Builder diff --git a/poetry/masonry/api.py b/poetry/masonry/api.py index b6df04b0168..417def2c834 100644 --- a/poetry/masonry/api.py +++ b/poetry/masonry/api.py @@ -1,76 +1,14 @@ -""" -PEP-517 compliant buildsystem API -""" -import logging -import sys - -from clikit.io import NullIO - -from poetry.factory import Factory -from poetry.utils._compat import Path -from poetry.utils._compat import unicode -from poetry.utils.env import SystemEnv - -from .builders.sdist import SdistBuilder -from .builders.wheel import WheelBuilder - - -log = logging.getLogger(__name__) - - -def get_requires_for_build_wheel(config_settings=None): - """ - Returns an additional list of requirements for building, as PEP508 strings, - above and beyond those specified in the pyproject.toml file. - - This implementation is optional. At the moment it only returns an empty list, which would be the same as if - not define. So this is just for completeness for future implementation. - """ - - return [] - - -# For now, we require all dependencies to build either a wheel or an sdist. -get_requires_for_build_sdist = get_requires_for_build_wheel - - -def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None): - poetry = Factory().create_poetry(Path(".")) - builder = WheelBuilder(poetry, SystemEnv(Path(sys.prefix)), NullIO()) - - dist_info = Path(metadata_directory, builder.dist_info) - dist_info.mkdir(parents=True, exist_ok=True) - - if "scripts" in poetry.local_config or "plugins" in poetry.local_config: - with (dist_info / "entry_points.txt").open("w", encoding="utf-8") as f: - builder._write_entry_points(f) - - with (dist_info / "WHEEL").open("w", encoding="utf-8") as f: - builder._write_wheel_file(f) - - with (dist_info / "METADATA").open("w", encoding="utf-8") as f: - builder._write_metadata_file(f) - - return dist_info.name - - -def build_wheel(wheel_directory, config_settings=None, metadata_directory=None): - """Builds a wheel, places it in wheel_directory""" - poetry = Factory().create_poetry(Path(".")) - - return unicode( - WheelBuilder.make_in( - poetry, SystemEnv(Path(sys.prefix)), NullIO(), Path(wheel_directory) - ) - ) - - -def build_sdist(sdist_directory, config_settings=None): - """Builds an sdist, places it in sdist_directory""" - poetry = Factory().create_poetry(Path(".")) - - path = SdistBuilder(poetry, SystemEnv(Path(sys.prefix)), NullIO()).build( - Path(sdist_directory) - ) - - return unicode(path.name) +from poetry.core.masonry.api import build_sdist +from poetry.core.masonry.api import build_wheel +from poetry.core.masonry.api import get_requires_for_build_sdist +from poetry.core.masonry.api import get_requires_for_build_wheel +from poetry.core.masonry.api import prepare_metadata_for_build_wheel + + +__all__ = [ + "build_sdist", + "build_wheel", + "get_requires_for_build_sdist", + "get_requires_for_build_wheel", + "prepare_metadata_for_build_wheel", +] diff --git a/poetry/masonry/builder.py b/poetry/masonry/builder.py deleted file mode 100644 index 3437bb0b88c..00000000000 --- a/poetry/masonry/builder.py +++ /dev/null @@ -1,21 +0,0 @@ -from .builders.complete import CompleteBuilder -from .builders.sdist import SdistBuilder -from .builders.wheel import WheelBuilder - - -class Builder: - - _FORMATS = {"sdist": SdistBuilder, "wheel": WheelBuilder, "all": CompleteBuilder} - - def __init__(self, poetry, env, io): - self._poetry = poetry - self._env = env - self._io = io - - def build(self, fmt): - if fmt not in self._FORMATS: - raise ValueError("Invalid format: {}".format(fmt)) - - builder = self._FORMATS[fmt](self._poetry, self._env, self._io) - - return builder.build() diff --git a/poetry/masonry/builders/__init__.py b/poetry/masonry/builders/__init__.py index 4fd8d4880ef..f1f02b72d67 100644 --- a/poetry/masonry/builders/__init__.py +++ b/poetry/masonry/builders/__init__.py @@ -1,4 +1 @@ -from .complete import CompleteBuilder from .editable import EditableBuilder -from .sdist import SdistBuilder -from .wheel import WheelBuilder diff --git a/poetry/masonry/builders/builder.py b/poetry/masonry/builders/builder.py deleted file mode 100644 index 40e8c771e81..00000000000 --- a/poetry/masonry/builders/builder.py +++ /dev/null @@ -1,286 +0,0 @@ -# -*- coding: utf-8 -*- -import re -import shutil -import tempfile - -from collections import defaultdict -from contextlib import contextmanager -from typing import Set -from typing import Union - -from clikit.api.io.flags import VERY_VERBOSE - -from poetry.utils._compat import Path -from poetry.utils._compat import glob -from poetry.utils._compat import lru_cache -from poetry.utils._compat import to_str -from poetry.vcs import get_vcs - -from ..metadata import Metadata -from ..utils.module import Module -from ..utils.package_include import PackageInclude - - -AUTHOR_REGEX = re.compile(r"(?u)^(?P[- .,\w\d'’\"()]+) <(?P.+?)>$") - -METADATA_BASE = """\ -Metadata-Version: 2.1 -Name: {name} -Version: {version} -Summary: {summary} -""" - - -class Builder(object): - AVAILABLE_PYTHONS = {"2", "2.7", "3", "3.4", "3.5", "3.6", "3.7"} - - format = None - - def __init__( - self, poetry, env, io, ignore_packages_formats=False - ): # type: ("Poetry", "Env", "IO", bool) -> None - self._poetry = poetry - self._env = env - self._io = io - self._package = poetry.package - self._path = poetry.file.parent - - packages = [] - for p in self._package.packages: - formats = p.get("format", []) - if not isinstance(formats, list): - formats = [formats] - - if ( - formats - and self.format - and self.format not in formats - and not ignore_packages_formats - ): - continue - - packages.append(p) - - self._module = Module( - self._package.name, - self._path.as_posix(), - packages=packages, - includes=self._package.include, - ) - self._meta = Metadata.from_package(self._package) - - def build(self): - raise NotImplementedError() - - @lru_cache(maxsize=None) - def find_excluded_files(self): # type: () -> Set[str] - # Checking VCS - vcs = get_vcs(self._path) - if not vcs: - vcs_ignored_files = set() - else: - vcs_ignored_files = set(vcs.get_ignored_files()) - - explicitely_excluded = set() - for excluded_glob in self._package.exclude: - - for excluded in glob( - Path(self._path, excluded_glob).as_posix(), recursive=True - ): - explicitely_excluded.add( - Path(excluded).relative_to(self._path).as_posix() - ) - - ignored = vcs_ignored_files | explicitely_excluded - result = set() - for file in ignored: - result.add(file) - - # The list of excluded files might be big and we will do a lot - # containment check (x in excluded). - # Returning a set make those tests much much faster. - return result - - def is_excluded(self, filepath): # type: (Union[str, Path]) -> bool - exclude_path = Path(filepath) - - while True: - if exclude_path.as_posix() in self.find_excluded_files(): - return True - - if len(exclude_path.parts) > 1: - exclude_path = exclude_path.parent - else: - break - - return False - - def find_files_to_add(self, exclude_build=True): # type: (bool) -> list - """ - Finds all files to add to the tarball - """ - to_add = [] - - for include in self._module.includes: - for file in include.elements: - if "__pycache__" in str(file): - continue - - if file.is_dir(): - continue - - file = file.relative_to(self._path) - - if self.is_excluded(file) and isinstance(include, PackageInclude): - continue - - if file.suffix == ".pyc": - continue - - if file in to_add: - # Skip duplicates - continue - - self._io.write_line( - " - Adding: {}".format(str(file)), VERY_VERBOSE - ) - to_add.append(file) - - # Include project files - self._io.write_line( - " - Adding: pyproject.toml", VERY_VERBOSE - ) - to_add.append(Path("pyproject.toml")) - - # If a license file exists, add it - for license_file in self._path.glob("LICENSE*"): - self._io.write_line( - " - Adding: {}".format( - license_file.relative_to(self._path) - ), - VERY_VERBOSE, - ) - to_add.append(license_file.relative_to(self._path)) - - # If a README is specified we need to include it - # to avoid errors - if "readme" in self._poetry.local_config: - readme = self._path / self._poetry.local_config["readme"] - if readme.exists(): - self._io.write_line( - " - Adding: {}".format( - readme.relative_to(self._path) - ), - VERY_VERBOSE, - ) - to_add.append(readme.relative_to(self._path)) - - # If a build script is specified and explicitely required - # we add it to the list of files - if self._package.build and not exclude_build: - to_add.append(Path(self._package.build)) - - 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.maintainer: - content += "Maintainer: {}\n".format(to_str(self._meta.maintainer)) - - if self._meta.maintainer_email: - content += "Maintainer-email: {}\n".format( - to_str(self._meta.maintainer_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 - result = defaultdict(list) - - # Scripts -> Entry points - for name, ep in self._poetry.local_config.get("scripts", {}).items(): - extras = "" - if isinstance(ep, dict): - extras = "[{}]".format(", ".join(ep["extras"])) - ep = ep["callable"] - - result["console_scripts"].append("{} = {}{}".format(name, ep, extras)) - - # Plugins -> entry points - plugins = self._poetry.local_config.get("plugins", {}) - for groupname, group in plugins.items(): - for name, ep in sorted(group.items()): - result[groupname].append("{} = {}".format(name, ep)) - - for groupname in result: - result[groupname] = sorted(result[groupname]) - - return dict(result) - - @classmethod - def convert_author(cls, author): # type: (...) -> dict - m = AUTHOR_REGEX.match(author) - - name = m.group("name") - email = m.group("email") - - return {"name": name, "email": email} - - @classmethod - @contextmanager - def temporary_directory(cls, *args, **kwargs): - try: - from tempfile import TemporaryDirectory - - with TemporaryDirectory(*args, **kwargs) as name: - yield name - except ImportError: - name = tempfile.mkdtemp(*args, **kwargs) - - yield name - - shutil.rmtree(name) diff --git a/poetry/masonry/builders/complete.py b/poetry/masonry/builders/complete.py deleted file mode 100644 index 6339f9351b5..00000000000 --- a/poetry/masonry/builders/complete.py +++ /dev/null @@ -1,73 +0,0 @@ -import os -import tarfile - -from contextlib import contextmanager - -from poetry.factory import Factory -from poetry.io.null_io import NullIO -from poetry.utils._compat import Path -from poetry.utils.helpers import temporary_directory - -from .builder import Builder -from .sdist import SdistBuilder -from .wheel import WheelBuilder - - -class CompleteBuilder(Builder): - def build(self): - # We start by building the tarball - # We will use it to build the wheel - sdist_builder = SdistBuilder(self._poetry, self._env, self._io) - build_for_all_formats = False - for p in self._package.packages: - formats = p.get("format", []) - if not isinstance(formats, list): - formats = [formats] - - if formats and sdist_builder.format not in formats: - build_for_all_formats = True - break - - sdist_file = sdist_builder.build() - - self._io.write_line("") - - dist_dir = self._path / "dist" - - if build_for_all_formats: - sdist_builder = SdistBuilder( - self._poetry, self._env, NullIO(), ignore_packages_formats=True - ) - with temporary_directory() as tmp_dir: - sdist_file = sdist_builder.build(Path(tmp_dir)) - - with self.unpacked_tarball(sdist_file) as tmpdir: - WheelBuilder.make_in( - Factory().create_poetry(tmpdir), - self._env, - self._io, - dist_dir, - original=self._poetry, - ) - else: - with self.unpacked_tarball(sdist_file) as tmpdir: - WheelBuilder.make_in( - Factory().create_poetry(tmpdir), - self._env, - self._io, - dist_dir, - original=self._poetry, - ) - - @classmethod - @contextmanager - def unpacked_tarball(cls, path): - tf = tarfile.open(str(path)) - - with cls.temporary_directory() as tmpdir: - tf.extractall(tmpdir) - files = os.listdir(tmpdir) - - assert len(files) == 1, files - - yield Path(tmpdir) / files[0] diff --git a/poetry/masonry/builders/editable.py b/poetry/masonry/builders/editable.py index 1757bd4ff3d..e6924c574ff 100644 --- a/poetry/masonry/builders/editable.py +++ b/poetry/masonry/builders/editable.py @@ -5,19 +5,24 @@ from collections import defaultdict -from poetry.semver.version import Version +from poetry.core.masonry.builders.builder import Builder +from poetry.core.masonry.builders.sdist import SdistBuilder +from poetry.core.semver.version import Version from poetry.utils._compat import decode -from .builder import Builder -from .sdist import SdistBuilder - class EditableBuilder(Builder): + def __init__(self, poetry, env, io): + super(EditableBuilder, self).__init__(poetry) + + self._env = env + self._io = io + def build(self): return self._setup_build() def _setup_build(self): - builder = SdistBuilder(self._poetry, self._env, self._io) + builder = SdistBuilder(self._poetry) setup = self._path / "setup.py" has_setup = setup.exists() diff --git a/poetry/masonry/builders/sdist.py b/poetry/masonry/builders/sdist.py deleted file mode 100644 index c906f4c473d..00000000000 --- a/poetry/masonry/builders/sdist.py +++ /dev/null @@ -1,346 +0,0 @@ -# -*- coding: utf-8 -*- -import os -import re -import tarfile -import time - -from collections import defaultdict -from copy import copy -from gzip import GzipFile -from io import BytesIO -from posixpath import join as pjoin -from pprint import pformat - -from poetry.utils._compat import Path -from poetry.utils._compat import encode -from poetry.utils._compat import to_str - -from ..utils.helpers import normalize_file_permissions -from ..utils.package_include import PackageInclude -from .builder import Builder - - -SETUP = """\ -# -*- coding: utf-8 -*- -from setuptools import setup - -{before} -setup_kwargs = {{ - 'name': {name!r}, - 'version': {version!r}, - 'description': {description!r}, - 'long_description': {long_description!r}, - 'author': {author!r}, - 'author_email': {author_email!r}, - 'maintainer': {maintainer!r}, - 'maintainer_email': {maintainer_email!r}, - 'url': {url!r}, - {extra} -}} -{after} - -setup(**setup_kwargs) -""" - - -class SdistBuilder(Builder): - - format = "sdist" - - def build(self, target_dir=None): # type: (Path) -> Path - self._io.write_line(" - Building sdist") - if target_dir is None: - target_dir = self._path / "dist" - - if not target_dir.exists(): - target_dir.mkdir(parents=True) - - target = target_dir / "{}-{}.tar.gz".format( - self._package.pretty_name, self._meta.version - ) - gz = GzipFile(target.as_posix(), mode="wb") - tar = tarfile.TarFile( - target.as_posix(), mode="w", fileobj=gz, format=tarfile.PAX_FORMAT - ) - - try: - tar_dir = "{}-{}".format(self._package.pretty_name, self._meta.version) - - files_to_add = self.find_files_to_add(exclude_build=False) - - for relpath in files_to_add: - path = self._path / relpath - tar_info = tar.gettarinfo( - str(path), arcname=pjoin(tar_dir, str(relpath)) - ) - tar_info = self.clean_tarinfo(tar_info) - - if tar_info.isreg(): - with path.open("rb") as f: - tar.addfile(tar_info, f) - else: - tar.addfile(tar_info) # Symlinks & ? - - setup = self.build_setup() - tar_info = tarfile.TarInfo(pjoin(tar_dir, "setup.py")) - tar_info.size = len(setup) - tar_info.mtime = time.time() - tar.addfile(tar_info, BytesIO(setup)) - - pkg_info = self.build_pkg_info() - - tar_info = tarfile.TarInfo(pjoin(tar_dir, "PKG-INFO")) - tar_info.size = len(pkg_info) - tar_info.mtime = time.time() - tar.addfile(tar_info, BytesIO(pkg_info)) - finally: - tar.close() - gz.close() - - self._io.write_line(" - Built {}".format(target.name)) - - return target - - def build_setup(self): # type: () -> bytes - before, extra, after = [], [], [] - package_dir = {} - - # If we have a build script, use it - if self._package.build: - after += [ - "from {} import *".format(self._package.build.split(".")[0]), - "build(setup_kwargs)", - ] - - modules = [] - packages = [] - package_data = {} - for include in self._module.includes: - if include.formats and "sdist" not in include.formats: - continue - - if isinstance(include, PackageInclude): - if include.is_package(): - pkg_dir, _packages, _package_data = self.find_packages(include) - - if pkg_dir is not None: - package_dir[""] = os.path.relpath(pkg_dir, str(self._path)) - - packages += [p for p in _packages if p not in packages] - package_data.update(_package_data) - else: - module = include.elements[0].relative_to(include.base).stem - - if include.source is not None: - package_dir[""] = str(include.base.relative_to(self._path)) - - if module not in modules: - modules.append(module) - else: - pass - - if package_dir: - before.append("package_dir = \\\n{}\n".format(pformat(package_dir))) - extra.append("'package_dir': package_dir,") - - if packages: - before.append("packages = \\\n{}\n".format(pformat(sorted(packages)))) - extra.append("'packages': packages,") - - if package_data: - before.append("package_data = \\\n{}\n".format(pformat(package_data))) - extra.append("'package_data': package_data,") - - if modules: - before.append("modules = \\\n{}".format(pformat(modules))) - extra.append("'py_modules': modules,".format()) - - dependencies, extras = self.convert_dependencies( - self._package, self._package.requires - ) - if dependencies: - before.append( - "install_requires = \\\n{}\n".format(pformat(sorted(dependencies))) - ) - extra.append("'install_requires': install_requires,") - - if extras: - before.append("extras_require = \\\n{}\n".format(pformat(extras))) - extra.append("'extras_require': extras_require,") - - entry_points = self.convert_entry_points() - if entry_points: - before.append("entry_points = \\\n{}\n".format(pformat(entry_points))) - extra.append("'entry_points': entry_points,") - - if self._package.python_versions != "*": - python_requires = self._meta.requires_python - - extra.append("'python_requires': {!r},".format(python_requires)) - - return encode( - SETUP.format( - before="\n".join(before), - name=to_str(self._meta.name), - version=to_str(self._meta.version), - description=to_str(self._meta.summary), - long_description=to_str(self._meta.description), - author=to_str(self._meta.author), - author_email=to_str(self._meta.author_email), - maintainer=to_str(self._meta.maintainer), - maintainer_email=to_str(self._meta.maintainer_email), - url=to_str(self._meta.home_page), - extra="\n ".join(extra), - after="\n".join(after), - ) - ) - - def build_pkg_info(self): - return encode(self.get_metadata_content()) - - def find_packages(self, include): - """ - Discover subpackages and data. - - It also retrieves necessary files. - """ - pkgdir = None - if include.source is not None: - pkgdir = str(include.base) - - base = str(include.elements[0].parent) - - pkg_name = include.package - pkg_data = defaultdict(list) - # Undocumented distutils feature: - # the empty string matches all package names - pkg_data[""].append("*") - packages = [pkg_name] - subpkg_paths = set() - - def find_nearest_pkg(rel_path): - parts = rel_path.split(os.sep) - for i in reversed(range(1, len(parts))): - ancestor = "/".join(parts[:i]) - if ancestor in subpkg_paths: - pkg = ".".join([pkg_name] + parts[:i]) - return pkg, "/".join(parts[i:]) - - # Relative to the top-level package - return pkg_name, Path(rel_path).as_posix() - - for path, dirnames, filenames in os.walk(str(base), topdown=True): - if os.path.basename(path) == "__pycache__": - continue - - from_top_level = os.path.relpath(path, base) - if from_top_level == ".": - continue - - is_subpkg = any([filename.endswith(".py") for filename in filenames]) - if is_subpkg: - subpkg_paths.add(from_top_level) - parts = from_top_level.split(os.sep) - packages.append(".".join([pkg_name] + parts)) - else: - pkg, from_nearest_pkg = find_nearest_pkg(from_top_level) - - data_elements = [ - f.relative_to(self._path) - for f in Path(path).glob("*") - if not f.is_dir() - ] - - data = [e for e in data_elements if not self.is_excluded(e)] - if not data: - continue - - if len(data) == len(data_elements): - pkg_data[pkg].append(pjoin(from_nearest_pkg, "*")) - else: - for d in data: - if d.is_dir(): - continue - - pkg_data[pkg] += [pjoin(from_nearest_pkg, d.name) for d in data] - - # Sort values in pkg_data - pkg_data = {k: sorted(v) for (k, v) in pkg_data.items() if v} - - return pkgdir, sorted(packages), pkg_data - - @classmethod - def convert_dependencies(cls, package, dependencies): - main = [] - extras = defaultdict(list) - req_regex = re.compile(r"^(.+) \((.+)\)$") - - for dependency in dependencies: - if dependency.is_optional(): - for extra_name, reqs in package.extras.items(): - for req in reqs: - if req.name == dependency.name: - requirement = to_str( - dependency.to_pep_508(with_extras=False) - ) - if ";" in requirement: - requirement, conditions = requirement.split(";") - - requirement = requirement.strip() - if req_regex.match(requirement): - requirement = req_regex.sub( - "\\1\\2", requirement.strip() - ) - - extras[extra_name + ":" + conditions.strip()].append( - requirement - ) - - continue - - requirement = requirement.strip() - if req_regex.match(requirement): - requirement = req_regex.sub( - "\\1\\2", requirement.strip() - ) - extras[extra_name].append(requirement) - continue - - requirement = to_str(dependency.to_pep_508()) - if ";" in requirement: - requirement, conditions = requirement.split(";") - - requirement = requirement.strip() - if req_regex.match(requirement): - requirement = req_regex.sub("\\1\\2", requirement.strip()) - - extras[":" + conditions.strip()].append(requirement) - - continue - - requirement = requirement.strip() - if req_regex.match(requirement): - requirement = req_regex.sub("\\1\\2", requirement.strip()) - - main.append(requirement) - - return main, dict(extras) - - @classmethod - def clean_tarinfo(cls, tar_info): - """ - Clean metadata from a TarInfo object to make it more reproducible. - - - Set uid & gid to 0 - - Set uname and gname to "" - - Normalise permissions to 644 or 755 - - Set mtime if not None - """ - ti = copy(tar_info) - ti.uid = 0 - ti.gid = 0 - ti.uname = "" - ti.gname = "" - ti.mode = normalize_file_permissions(ti.mode) - - return ti diff --git a/poetry/masonry/builders/wheel.py b/poetry/masonry/builders/wheel.py deleted file mode 100644 index cdba38c51e3..00000000000 --- a/poetry/masonry/builders/wheel.py +++ /dev/null @@ -1,324 +0,0 @@ -from __future__ import unicode_literals - -import contextlib -import hashlib -import os -import shutil -import stat -import tempfile -import zipfile - -from base64 import urlsafe_b64encode -from io import StringIO - -from clikit.api.io.flags import VERY_VERBOSE - -from poetry.__version__ import __version__ -from poetry.semver import parse_constraint -from poetry.utils._compat import decode - -from ..utils.helpers import escape_name -from ..utils.helpers import escape_version -from ..utils.helpers import normalize_file_permissions -from ..utils.package_include import PackageInclude -from ..utils.tags import get_abbr_impl -from ..utils.tags import get_abi_tag -from ..utils.tags import get_impl_ver -from ..utils.tags import get_platform -from .builder import Builder - - -wheel_file_template = """\ -Wheel-Version: 1.0 -Generator: poetry {version} -Root-Is-Purelib: {pure_lib} -Tag: {tag} -""" - - -class WheelBuilder(Builder): - - format = "wheel" - - def __init__(self, poetry, env, io, target_dir=None, original=None): - super(WheelBuilder, self).__init__(poetry, env, io) - - self._records = [] - self._original_path = self._path - self._target_dir = target_dir or (self._poetry.file.parent / "dist") - if original: - self._original_path = original.file.parent - - @classmethod - def make_in(cls, poetry, env, io, directory=None, original=None): - wb = WheelBuilder(poetry, env, io, target_dir=directory, original=original) - wb.build() - - return wb.wheel_filename - - @classmethod - def make(cls, poetry, env, io): - """Build a wheel in the dist/ directory, and optionally upload it.""" - cls.make_in(poetry, env, io) - - def build(self): - self._io.write_line(" - Building wheel") - - dist_dir = self._target_dir - if not dist_dir.exists(): - dist_dir.mkdir() - - (fd, temp_path) = tempfile.mkstemp(suffix=".whl") - - st_mode = os.stat(temp_path).st_mode - new_mode = normalize_file_permissions(st_mode) - os.chmod(temp_path, new_mode) - - with zipfile.ZipFile( - os.fdopen(fd, "w+b"), mode="w", compression=zipfile.ZIP_DEFLATED - ) as zip_file: - self._copy_module(zip_file) - self._build(zip_file) - self._write_metadata(zip_file) - self._write_record(zip_file) - - wheel_path = dist_dir / self.wheel_filename - if wheel_path.exists(): - wheel_path.unlink() - shutil.move(temp_path, str(wheel_path)) - - self._io.write_line( - " - Built {}".format(self.wheel_filename) - ) - - def _build(self, wheel): - if self._package.build: - setup = self._path / "setup.py" - - # We need to place ourselves in the temporary - # directory in order to build the package - current_path = os.getcwd() - try: - os.chdir(str(self._path)) - self._env.run( - "python", str(setup), "build", "-b", str(self._path / "build") - ) - finally: - os.chdir(current_path) - - build_dir = self._path / "build" - lib = list(build_dir.glob("lib.*")) - if not lib: - # The result of building the extensions - # does not exist, this may due to conditional - # builds, so we assume that it's okay - return - - lib = lib[0] - - for pkg in lib.glob("**/*"): - if pkg.is_dir() or self.is_excluded(pkg): - continue - - rel_path = str(pkg.relative_to(lib)) - - if rel_path in wheel.namelist(): - continue - - self._io.write_line( - " - Adding: {}".format(rel_path), VERY_VERBOSE - ) - - self._add_file(wheel, pkg, rel_path) - - def _copy_module(self, wheel): - - to_add = [] - - for include in self._module.includes: - if include.formats and "wheel" not in include.formats: - continue - - include.refresh() - - for file in include.elements: - if "__pycache__" in str(file): - continue - - if file.is_dir(): - continue - - if isinstance(include, PackageInclude) and include.source: - rel_file = file.relative_to(include.base) - else: - rel_file = file.relative_to(self._path) - - if self.is_excluded(rel_file.as_posix()) and isinstance( - include, PackageInclude - ): - continue - - if file.suffix == ".pyc": - continue - - if (file, rel_file) in to_add: - # Skip duplicates - continue - - self._io.write_line( - " - Adding: {}".format(str(file)), VERY_VERBOSE - ) - to_add.append((file, rel_file)) - - # Walk the files and compress them, - # sorting everything so the order is stable. - for full_path, rel_path in sorted(to_add, key=lambda x: x[1]): - self._add_file(wheel, full_path, rel_path) - - def _write_metadata(self, wheel): - if ( - "scripts" in self._poetry.local_config - or "plugins" in self._poetry.local_config - ): - with self._write_to_zip(wheel, self.dist_info + "/entry_points.txt") as f: - self._write_entry_points(f) - - for base in ("COPYING", "LICENSE"): - for path in sorted(self._path.glob(base + "*")): - self._add_file(wheel, path, "%s/%s" % (self.dist_info, path.name)) - - with self._write_to_zip(wheel, self.dist_info + "/WHEEL") as f: - self._write_wheel_file(f) - - with self._write_to_zip(wheel, self.dist_info + "/METADATA") as f: - self._write_metadata_file(f) - - def _write_record(self, wheel): - # Write a record of the files in the wheel - with self._write_to_zip(wheel, self.dist_info + "/RECORD") as f: - for path, hash, size in self._records: - f.write("{},sha256={},{}\n".format(path, hash, size)) - # RECORD itself is recorded with no hash or size - f.write(self.dist_info + "/RECORD,,\n") - - @property - def dist_info(self): # type: () -> str - return self.dist_info_name(self._package.name, self._meta.version) - - @property - def wheel_filename(self): # type: () -> str - return "{}-{}-{}.whl".format( - escape_name(self._package.pretty_name), - escape_version(self._meta.version), - self.tag, - ) - - def supports_python2(self): - return self._package.python_constraint.allows_any( - parse_constraint(">=2.0.0 <3.0.0") - ) - - def dist_info_name(self, distribution, version): # type: (...) -> str - escaped_name = escape_name(distribution) - escaped_version = escape_version(version) - - return "{}-{}.dist-info".format(escaped_name, escaped_version) - - @property - def tag(self): - if self._package.build: - platform = get_platform().replace(".", "_").replace("-", "_") - impl_name = get_abbr_impl(self._env) - impl_ver = get_impl_ver(self._env) - impl = impl_name + impl_ver - abi_tag = str(get_abi_tag(self._env)).lower() - tag = (impl, abi_tag, platform) - else: - platform = "any" - if self.supports_python2(): - impl = "py2.py3" - else: - impl = "py3" - - tag = (impl, "none", platform) - - return "-".join(tag) - - def _add_file(self, wheel, full_path, rel_path): - full_path, rel_path = str(full_path), str(rel_path) - if os.sep != "/": - # We always want to have /-separated paths in the zip file and in - # RECORD - rel_path = rel_path.replace(os.sep, "/") - - zinfo = zipfile.ZipInfo(rel_path) - - # Normalize permission bits to either 755 (executable) or 644 - st_mode = os.stat(full_path).st_mode - new_mode = normalize_file_permissions(st_mode) - zinfo.external_attr = (new_mode & 0xFFFF) << 16 # Unix attributes - - if stat.S_ISDIR(st_mode): - zinfo.external_attr |= 0x10 # MS-DOS directory flag - - hashsum = hashlib.sha256() - with open(full_path, "rb") as src: - while True: - buf = src.read(1024 * 8) - if not buf: - break - hashsum.update(buf) - - src.seek(0) - wheel.writestr(zinfo, src.read(), compress_type=zipfile.ZIP_DEFLATED) - - size = os.stat(full_path).st_size - hash_digest = urlsafe_b64encode(hashsum.digest()).decode("ascii").rstrip("=") - - self._records.append((rel_path, hash_digest, size)) - - @contextlib.contextmanager - def _write_to_zip(self, wheel, rel_path): - sio = StringIO() - yield sio - - # The default is a fixed timestamp rather than the current time, so - # that building a wheel twice on the same computer can automatically - # give you the exact same result. - date_time = (2016, 1, 1, 0, 0, 0) - zi = zipfile.ZipInfo(rel_path, date_time) - zi.external_attr = (0o644 & 0xFFFF) << 16 # Unix attributes - b = sio.getvalue().encode("utf-8") - hashsum = hashlib.sha256(b) - hash_digest = urlsafe_b64encode(hashsum.digest()).decode("ascii").rstrip("=") - - wheel.writestr(zi, b, compress_type=zipfile.ZIP_DEFLATED) - self._records.append((rel_path, hash_digest, len(b))) - - def _write_entry_points(self, fp): - """ - Write entry_points.txt. - """ - entry_points = self.convert_entry_points() - - for group_name in sorted(entry_points): - fp.write("[{}]\n".format(group_name)) - for ep in sorted(entry_points[group_name]): - fp.write(ep.replace(" ", "") + "\n") - - fp.write("\n") - - def _write_wheel_file(self, fp): - fp.write( - wheel_file_template.format( - version=__version__, - pure_lib="true" if self._package.build is None else "false", - tag=self.tag, - ) - ) - - def _write_metadata_file(self, fp): - """ - Write out metadata in the 2.x format (email like) - """ - fp.write(decode(self.get_metadata_content())) diff --git a/poetry/masonry/metadata.py b/poetry/masonry/metadata.py deleted file mode 100644 index 64e91bc397b..00000000000 --- a/poetry/masonry/metadata.py +++ /dev/null @@ -1,90 +0,0 @@ -from poetry.utils.helpers import canonicalize_name -from poetry.utils.helpers import normalize_version -from poetry.version.helpers import format_python_constraint - - -class Metadata: - - metadata_version = "2.1" - # version 1.0 - name = None - version = None - platforms = () - supported_platforms = () - summary = None - description = None - keywords = None - home_page = None - download_url = None - author = None - author_email = None - license = None - # version 1.1 - classifiers = () - requires = () - provides = () - obsoletes = () - # version 1.2 - maintainer = None - maintainer_email = None - requires_python = None - requires_external = () - requires_dist = [] - provides_dist = () - obsoletes_dist = () - project_urls = () - - # Version 2.1 - description_content_type = None - provides_extra = [] - - @classmethod - def from_package(cls, package): # type: (...) -> Metadata - meta = cls() - - meta.name = canonicalize_name(package.name) - meta.version = normalize_version(package.version.text) - meta.summary = package.description - if package.readme: - with package.readme.open(encoding="utf-8") as f: - meta.description = f.read() - - meta.keywords = ",".join(package.keywords) - meta.home_page = package.homepage or package.repository_url - meta.author = package.author_name - meta.author_email = package.author_email - - if package.license: - meta.license = package.license.id - - meta.classifiers = package.all_classifiers - - # Version 1.2 - meta.maintainer = package.maintainer_name - meta.maintainer_email = package.maintainer_email - - # Requires python - if package.python_versions != "*": - meta.requires_python = format_python_constraint(package.python_constraint) - - meta.requires_dist = [d.to_pep_508() for d in package.requires] - - # Version 2.1 - if package.readme: - if package.readme.suffix == ".rst": - meta.description_content_type = "text/x-rst" - elif package.readme.suffix in [".md", ".markdown"]: - meta.description_content_type = "text/markdown" - else: - meta.description_content_type = "text/plain" - - meta.provides_extra = [e for e in package.extras] - - if package.urls: - for name, url in package.urls.items(): - if name == "Homepage" and meta.home_page == url: - continue - - meta.project_urls += ("{}, {}".format(name, url),) - - return meta diff --git a/poetry/masonry/utils/helpers.py b/poetry/masonry/utils/helpers.py deleted file mode 100644 index e69ebc2488a..00000000000 --- a/poetry/masonry/utils/helpers.py +++ /dev/null @@ -1,31 +0,0 @@ -import re - - -def normalize_file_permissions(st_mode): - """ - Normalizes the permission bits in the st_mode field from stat to 644/755 - - Popular VCSs only track whether a file is executable or not. The exact - permissions can vary on systems with different umasks. Normalising - to 644 (non executable) or 755 (executable) makes builds more reproducible. - """ - # Set 644 permissions, leaving higher bits of st_mode unchanged - new_mode = (st_mode | 0o644) & ~0o133 - if st_mode & 0o100: - new_mode |= 0o111 # Executable: 644 -> 755 - - return new_mode - - -def escape_version(version): - """ - Escaped version in wheel filename. Doesn't exactly follow - the escaping specification in :pep:`427#escaping-and-unicode` - because this conflicts with :pep:`440#local-version-identifiers`. - """ - return re.sub(r"[^\w\d.+]+", "_", version, flags=re.UNICODE) - - -def escape_name(name): - """Escaped wheel name as specified in :pep:`427#escaping-and-unicode`.""" - return re.sub(r"[^\w\d.]+", "_", name, flags=re.UNICODE) diff --git a/poetry/masonry/utils/include.py b/poetry/masonry/utils/include.py deleted file mode 100644 index 5b6938a0bd1..00000000000 --- a/poetry/masonry/utils/include.py +++ /dev/null @@ -1,48 +0,0 @@ -from typing import List -from typing import Optional - -from poetry.utils._compat import Path - - -class Include(object): - """ - Represents an "include" entry. - - It can be a glob string, a single file or a directory. - - This class will then detect the type of this include: - - - a package - - a module - - a file - - a directory - """ - - def __init__( - self, base, include, formats=None - ): # type: (Path, str, Optional[List[str]]) -> None - self._base = base - self._include = str(include) - self._formats = formats - - self._elements = sorted(list(self._base.glob(str(self._include)))) - - @property - def base(self): # type: () -> Path - return self._base - - @property - def elements(self): # type: () -> List[Path] - return self._elements - - @property - def formats(self): # type: () -> Optional[List[str]] - return self._formats - - def is_empty(self): # type: () -> bool - return len(self._elements) == 0 - - def refresh(self): # type: () -> Include - self._elements = sorted(list(self._base.glob(self._include))) - - return self diff --git a/poetry/masonry/utils/module.py b/poetry/masonry/utils/module.py deleted file mode 100644 index bf4d7ab0ecd..00000000000 --- a/poetry/masonry/utils/module.py +++ /dev/null @@ -1,102 +0,0 @@ -from typing import List - -from poetry.utils._compat import Path -from poetry.utils.helpers import module_name - -from .include import Include -from .package_include import PackageInclude - - -class ModuleOrPackageNotFound(ValueError): - - pass - - -class Module: - def __init__(self, name, directory=".", packages=None, includes=None): - self._name = module_name(name) - self._in_src = False - self._is_package = False - self._path = Path(directory) - self._includes = [] - packages = packages or [] - includes = includes or [] - - if not packages: - # It must exist either as a .py file or a directory, but not both - pkg_dir = Path(directory, self._name) - py_file = Path(directory, self._name + ".py") - if pkg_dir.is_dir() and py_file.is_file(): - raise ValueError("Both {} and {} exist".format(pkg_dir, py_file)) - elif pkg_dir.is_dir(): - packages = [{"include": str(pkg_dir.relative_to(self._path))}] - elif py_file.is_file(): - packages = [{"include": str(py_file.relative_to(self._path))}] - else: - # Searching for a src module - src = Path(directory, "src") - src_pkg_dir = src / self._name - src_py_file = src / (self._name + ".py") - - if src_pkg_dir.is_dir() and src_py_file.is_file(): - raise ValueError("Both {} and {} exist".format(pkg_dir, py_file)) - elif src_pkg_dir.is_dir(): - packages = [ - { - "include": str(src_pkg_dir.relative_to(src)), - "from": str(src.relative_to(self._path)), - } - ] - elif src_py_file.is_file(): - packages = [ - { - "include": str(src_py_file.relative_to(src)), - "from": str(src.relative_to(self._path)), - } - ] - else: - raise ModuleOrPackageNotFound( - "No file/folder found for package {}".format(name) - ) - - for package in packages: - formats = package.get("format") - if formats and not isinstance(formats, list): - formats = [formats] - - self._includes.append( - PackageInclude( - self._path, - package["include"], - formats=formats, - source=package.get("from"), - ) - ) - - for include in includes: - self._includes.append(Include(self._path, include)) - - @property - def name(self): # type: () -> str - return self._name - - @property - def path(self): # type: () -> Path - return self._path - - @property - def file(self): # type: () -> Path - if self._is_package: - return self._path / "__init__.py" - else: - return self._path - - @property - def includes(self): # type: () -> List - return self._includes - - def is_package(self): # type: () -> bool - return self._is_package - - def is_in_src(self): # type: () -> bool - return self._in_src diff --git a/poetry/masonry/utils/package_include.py b/poetry/masonry/utils/package_include.py deleted file mode 100644 index 42ecbbc1fd0..00000000000 --- a/poetry/masonry/utils/package_include.py +++ /dev/null @@ -1,68 +0,0 @@ -from .include import Include - - -class PackageInclude(Include): - def __init__(self, base, include, formats=None, source=None): - self._package = None - self._is_package = False - self._is_module = False - self._source = source - - if source is not None: - base = base / source - - super(PackageInclude, self).__init__(base, include, formats=formats) - self.check_elements() - - @property - def package(self): # type: () -> str - return self._package - - @property - def source(self): # type: () -> str - return self._source - - def is_package(self): # type: () -> bool - return self._is_package - - def is_module(self): # type: () -> bool - return self._is_module - - def refresh(self): # type: () -> PackageInclude - super(PackageInclude, self).refresh() - - return self.check_elements() - - def check_elements(self): # type: () -> PackageInclude - root = self._elements[0] - - if not self._elements: - raise ValueError( - "{} does not contain any element".format(self._base / self._include) - ) - - if len(self._elements) > 1: - # Probably glob - self._is_package = True - - # Packages no longer need an __init__.py in python3, but there must - # at least be one .py file for it to be considered a package - if not any([element.suffix == ".py" for element in self._elements]): - raise ValueError("{} is not a package.".format(root.name)) - - self._package = root.parent.name - else: - if root.is_dir(): - # If it's a directory, we include everything inside it - self._package = root.name - self._elements = sorted(list(root.glob("**/*"))) - - if not any([element.suffix == ".py" for element in self._elements]): - raise ValueError("{} is not a package.".format(root.name)) - - self._is_package = True - else: - self._package = root.stem - self._is_module = True - - return self diff --git a/poetry/masonry/utils/tags.py b/poetry/masonry/utils/tags.py deleted file mode 100644 index 175cdd8b73b..00000000000 --- a/poetry/masonry/utils/tags.py +++ /dev/null @@ -1,184 +0,0 @@ -""" -Generate and work with PEP 425 Compatibility Tags. - -Base implementation taken from -https://github.com/pypa/wheel/blob/master/wheel/pep425tags.py -and adapted to work with poetry's env util. -""" -from __future__ import unicode_literals - -import distutils.util -import sys -import warnings - - -def get_abbr_impl(env): - """Return abbreviated implementation name.""" - impl = env.python_implementation - - if impl == "PyPy": - return "pp" - elif impl == "Jython": - return "jy" - elif impl == "IronPython": - return "ip" - elif impl == "CPython": - return "cp" - - raise LookupError("Unknown Python implementation: " + impl) - - -def get_impl_ver(env): - """Return implementation version.""" - impl_ver = env.config_var("py_version_nodot") - if not impl_ver or get_abbr_impl(env) == "pp": - impl_ver = "".join(map(str, get_impl_version_info(env))) - - return impl_ver - - -def get_impl_version_info(env): - """Return sys.version_info-like tuple for use in decrementing the minor - version.""" - if get_abbr_impl(env) == "pp": - # as per https://github.com/pypa/pip/issues/2882 - return env.version_info[:3] - else: - return env.version_info[:2] - - -def get_flag(env, var, fallback, expected=True, warn=True): - """Use a fallback method for determining SOABI flags if the needed config - var is unset or unavailable.""" - val = env.config_var(var) - if val is None: - if warn: - warnings.warn( - "Config variable '{0}' is unset, Python ABI tag may " - "be incorrect".format(var), - RuntimeWarning, - 2, - ) - return fallback() - return val == expected - - -def get_abi_tag(env): - """Return the ABI tag based on SOABI (if available) or emulate SOABI - (CPython 2, PyPy).""" - soabi = env.config_var("SOABI") - impl = get_abbr_impl(env) - if not soabi and impl in ("cp", "pp") and hasattr(sys, "maxunicode"): - d = "" - m = "" - u = "" - if get_flag( - env, - "Py_DEBUG", - lambda: hasattr(sys, "gettotalrefcount"), - warn=(impl == "cp"), - ): - d = "d" - if get_flag(env, "WITH_PYMALLOC", lambda: impl == "cp", warn=(impl == "cp")): - m = "m" - if get_flag( - env, - "Py_UNICODE_SIZE", - lambda: sys.maxunicode == 0x10FFFF, - expected=4, - warn=(impl == "cp" and env.version_info < (3, 3)), - ) and env.version_info < (3, 3): - u = "u" - abi = "%s%s%s%s%s" % (impl, get_impl_ver(env), d, m, u) - elif soabi and soabi.startswith("cpython-"): - abi = "cp" + soabi.split("-")[1] - elif soabi: - abi = soabi.replace(".", "_").replace("-", "_") - else: - abi = None - return abi - - -def get_platform(): - """Return our platform name 'win32', 'linux_x86_64'""" - # XXX remove distutils dependency - result = distutils.util.get_platform().replace(".", "_").replace("-", "_") - if result == "linux_x86_64" and sys.maxsize == 2147483647: - # pip pull request #3497 - result = "linux_i686" - return result - - -def get_supported(env, versions=None, supplied_platform=None): - """Return a list of supported tags for each version specified in - `versions`. - :param versions: a list of string versions, of the form ["33", "32"], - or None. The first version will be assumed to support our ABI. - """ - supported = [] - - # Versions must be given with respect to the preference - if versions is None: - versions = [] - version_info = get_impl_version_info(env) - major = version_info[:-1] - # Support all previous minor Python versions. - for minor in range(version_info[-1], -1, -1): - versions.append("".join(map(str, major + (minor,)))) - - impl = get_abbr_impl(env) - - abis = [] - - abi = get_abi_tag(env) - if abi: - abis[0:0] = [abi] - - abi3s = set() - import imp - - for suffix in imp.get_suffixes(): - if suffix[0].startswith(".abi"): - abi3s.add(suffix[0].split(".", 2)[1]) - - abis.extend(sorted(list(abi3s))) - - abis.append("none") - - platforms = [] - if supplied_platform: - platforms.append(supplied_platform) - platforms.append(get_platform()) - - # Current version, current API (built specifically for our Python): - for abi in abis: - for arch in platforms: - supported.append(("%s%s" % (impl, versions[0]), abi, arch)) - - # abi3 modules compatible with older version of Python - for version in versions[1:]: - # abi3 was introduced in Python 3.2 - if version in ("31", "30"): - break - for abi in abi3s: # empty set if not Python 3 - for arch in platforms: - supported.append(("%s%s" % (impl, version), abi, arch)) - - # No abi / arch, but requires our implementation: - for i, version in enumerate(versions): - supported.append(("%s%s" % (impl, version), "none", "any")) - if i == 0: - # Tagged specifically as being cross-version compatible - # (with just the major version specified) - supported.append(("%s%s" % (impl, versions[0][0]), "none", "any")) - - # Major Python version + platform; e.g. binaries not using the Python API - supported.append(("py%s" % (versions[0][0]), "none", arch)) - - # No abi / arch, generic Python - for i, version in enumerate(versions): - supported.append(("py%s" % (version,), "none", "any")) - if i == 0: - supported.append(("py%s" % (version[0]), "none", "any")) - - return supported diff --git a/poetry/mixology/partial_solution.py b/poetry/mixology/partial_solution.py index b8130a2af10..34c3231e2bc 100644 --- a/poetry/mixology/partial_solution.py +++ b/poetry/mixology/partial_solution.py @@ -2,8 +2,8 @@ from typing import Dict from typing import List -from poetry.packages import Dependency -from poetry.packages import Package +from poetry.core.packages import Dependency +from poetry.core.packages import Package from .assignment import Assignment from .incompatibility import Incompatibility diff --git a/poetry/mixology/term.py b/poetry/mixology/term.py index 1204d1a3356..346c9431abb 100644 --- a/poetry/mixology/term.py +++ b/poetry/mixology/term.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from typing import Union -from poetry.packages import Dependency +from poetry.core.packages import Dependency from .set_relation import SetRelation diff --git a/poetry/mixology/version_solver.py b/poetry/mixology/version_solver.py index d1c78ba7661..bd6d5c73f01 100644 --- a/poetry/mixology/version_solver.py +++ b/poetry/mixology/version_solver.py @@ -6,12 +6,12 @@ from typing import List from typing import Union -from poetry.packages import Dependency -from poetry.packages import Package -from poetry.packages import ProjectPackage +from poetry.core.packages import Dependency +from poetry.core.packages import Package +from poetry.core.packages import ProjectPackage +from poetry.core.semver import Version +from poetry.core.semver import VersionRange from poetry.puzzle.provider import Provider -from poetry.semver import Version -from poetry.semver import VersionRange from .failure import SolveFailure from .incompatibility import Incompatibility diff --git a/poetry/packages/__init__.py b/poetry/packages/__init__.py index e0a2203c9d3..555a8317e04 100644 --- a/poetry/packages/__init__.py +++ b/poetry/packages/__init__.py @@ -1,167 +1,3 @@ -import os -import re - -from poetry.semver import Version -from poetry.utils.patterns import wheel_file_re -from poetry.version.requirements import Requirement - -from .dependency import Dependency from .dependency_package import DependencyPackage -from .directory_dependency import DirectoryDependency -from .file_dependency import FileDependency from .locker import Locker -from .package import Package from .package_collection import PackageCollection -from .project_package import ProjectPackage -from .url_dependency import URLDependency -from .utils.link import Link -from .utils.utils import convert_markers -from .utils.utils import group_markers -from .utils.utils import is_archive_file -from .utils.utils import is_installable_dir -from .utils.utils import is_url -from .utils.utils import path_to_url -from .utils.utils import strip_extras -from .vcs_dependency import VCSDependency - - -def dependency_from_pep_508(name): - from poetry.vcs.git import ParsedUrl - - # Removing comments - parts = name.split("#", 1) - name = parts[0].strip() - if len(parts) > 1: - rest = parts[1] - if ";" in rest: - name += ";" + rest.split(";", 1)[1] - - req = Requirement(name) - - if req.marker: - markers = convert_markers(req.marker) - else: - markers = {} - - name = req.name - path = os.path.normpath(os.path.abspath(name)) - link = None - - if is_url(name): - link = Link(name) - elif req.url: - link = Link(req.url) - else: - p, extras = strip_extras(path) - if os.path.isdir(p) and (os.path.sep in name or name.startswith(".")): - - if not is_installable_dir(p): - raise ValueError( - "Directory {!r} is not installable. File 'setup.py' " - "not found.".format(name) - ) - link = Link(path_to_url(p)) - elif is_archive_file(p): - link = Link(path_to_url(p)) - - # it's a local file, dir, or url - if link: - # Handle relative file URLs - if link.scheme == "file" and re.search(r"\.\./", link.url): - link = Link(path_to_url(os.path.normpath(os.path.abspath(link.path)))) - # wheel file - if link.is_wheel: - m = wheel_file_re.match(link.filename) - if not m: - raise ValueError("Invalid wheel name: {}".format(link.filename)) - - name = m.group("name") - version = m.group("ver") - dep = Dependency(name, version) - else: - name = req.name or link.egg_fragment - - if link.scheme.startswith("git+"): - url = ParsedUrl.parse(link.url) - dep = VCSDependency(name, "git", url.url, rev=url.rev) - elif link.scheme == "git": - dep = VCSDependency(name, "git", link.url_without_fragment) - elif link.scheme in ["http", "https"]: - dep = URLDependency(name, link.url_without_fragment) - else: - dep = Dependency(name, "*") - else: - if req.pretty_constraint: - constraint = req.constraint - else: - constraint = "*" - - dep = Dependency(name, constraint) - - if "extra" in markers: - # If we have extras, the dependency is optional - dep.deactivate() - - for or_ in markers["extra"]: - for _, extra in or_: - dep.in_extras.append(extra) - - if "python_version" in markers: - ors = [] - for or_ in markers["python_version"]: - ands = [] - for op, version in or_: - # Expand python version - if op == "==": - version = "~" + version - op = "" - elif op == "!=": - 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"): - versions = [] - for v in re.split("[ ,]+", version): - split = v.split(".") - if len(split) in [1, 2]: - split.append("*") - op_ = "" if op == "in" else "!=" - else: - op_ = "==" if op == "in" else "!=" - - versions.append(op_ + ".".join(split)) - - glue = " || " if op == "in" else ", " - if versions: - ands.append(glue.join(versions)) - - continue - - ands.append("{}{}".format(op, version)) - - ors.append(" ".join(ands)) - - dep.python_versions = " || ".join(ors) - - if req.marker: - dep.marker = req.marker - - # Extras - for extra in req.extras: - dep.extras.append(extra) - - return dep diff --git a/poetry/packages/constraints/__init__.py b/poetry/packages/constraints/__init__.py deleted file mode 100644 index bd5c2fbc958..00000000000 --- a/poetry/packages/constraints/__init__.py +++ /dev/null @@ -1,57 +0,0 @@ -import re - -from .any_constraint import AnyConstraint -from .base_constraint import BaseConstraint -from .constraint import Constraint -from .union_constraint import UnionConstraint - - -BASIC_CONSTRAINT = re.compile(r"^(!?==?)?\s*([^\s]+?)\s*$") - - -def parse_constraint(constraints): - if constraints == "*": - return AnyConstraint() - - or_constraints = re.split(r"\s*\|\|?\s*", constraints.strip()) - or_groups = [] - for constraints in or_constraints: - and_constraints = re.split( - r"(?< ,]) *(? 1: - for constraint in and_constraints: - constraint_objects.append(parse_single_constraint(constraint)) - else: - constraint_objects.append(parse_single_constraint(and_constraints[0])) - - if len(constraint_objects) == 1: - constraint = constraint_objects[0] - else: - constraint = constraint_objects[0] - for next_constraint in constraint_objects[1:]: - constraint = constraint.intersect(next_constraint) - - or_groups.append(constraint) - - if len(or_groups) == 1: - return or_groups[0] - else: - return UnionConstraint(*or_groups) - - -def parse_single_constraint(constraint): # type: (str) -> BaseConstraint - # Basic comparator - m = BASIC_CONSTRAINT.match(constraint) - if m: - op = m.group(1) - if op is None: - op = "==" - - version = m.group(2).strip() - - return Constraint(version, op) - - raise ValueError("Could not parse version constraint: {}".format(constraint)) diff --git a/poetry/packages/constraints/any_constraint.py b/poetry/packages/constraints/any_constraint.py deleted file mode 100644 index c0003725e83..00000000000 --- a/poetry/packages/constraints/any_constraint.py +++ /dev/null @@ -1,37 +0,0 @@ -from .base_constraint import BaseConstraint -from .empty_constraint import EmptyConstraint - - -class AnyConstraint(BaseConstraint): - def allows(self, other): - return True - - def allows_all(self, other): - return True - - def allows_any(self, other): - return True - - def difference(self, other): - if other.is_any(): - return EmptyConstraint() - - return other - - def intersect(self, other): - return other - - def union(self, other): - return AnyConstraint() - - def is_any(self): - return True - - def is_empty(self): - return False - - def __str__(self): - return "*" - - def __eq__(self, other): - return other.is_any() diff --git a/poetry/packages/constraints/base_constraint.py b/poetry/packages/constraints/base_constraint.py deleted file mode 100644 index c8076fe7b41..00000000000 --- a/poetry/packages/constraints/base_constraint.py +++ /dev/null @@ -1,27 +0,0 @@ -class BaseConstraint(object): - def allows_all(self, other): - raise NotImplementedError() - - def allows_any(self, other): - raise NotImplementedError() - - def difference(self, other): - raise NotImplementedError() - - def intersect(self, other): - raise NotImplementedError() - - def union(self, other): - raise NotImplementedError() - - def is_any(self): - return False - - def is_empty(self): - return False - - def __repr__(self): - return "<{} {}>".format(self.__class__.__name__, str(self)) - - def __eq__(self, other): - raise NotImplementedError() diff --git a/poetry/packages/constraints/constraint.py b/poetry/packages/constraints/constraint.py deleted file mode 100644 index f05bf54d5a1..00000000000 --- a/poetry/packages/constraints/constraint.py +++ /dev/null @@ -1,121 +0,0 @@ -import operator - -from .base_constraint import BaseConstraint -from .empty_constraint import EmptyConstraint - - -class Constraint(BaseConstraint): - - OP_EQ = operator.eq - OP_NE = operator.ne - - _trans_op_str = {"=": OP_EQ, "==": OP_EQ, "!=": OP_NE} - - _trans_op_int = {OP_EQ: "==", OP_NE: "!="} - - def __init__(self, version, operator="=="): - if operator == "=": - operator = "==" - - self._version = version - self._operator = operator - self._op = self._trans_op_str[operator] - - @property - def version(self): - return self._version - - @property - def operator(self): - return self._operator - - def allows(self, other): - is_equal_op = self._operator == "==" - is_non_equal_op = self._operator == "!=" - is_other_equal_op = other.operator == "==" - is_other_non_equal_op = other.operator == "!=" - - if is_equal_op and is_other_equal_op: - return self._version == other.version - - if ( - is_equal_op - and is_other_non_equal_op - or is_non_equal_op - and is_other_equal_op - or is_non_equal_op - and is_other_non_equal_op - ): - return self._version != other.version - - return False - - def allows_all(self, other): - if not isinstance(other, Constraint): - return other.is_empty() - - return other == self - - def allows_any(self, other): - if isinstance(other, Constraint): - is_non_equal_op = self._operator == "!=" - is_other_non_equal_op = other.operator == "!=" - - if is_non_equal_op and is_other_non_equal_op: - return self._version != other.version - - return other.allows(self) - - def difference(self, other): - if other.allows(self): - return EmptyConstraint() - - return self - - def intersect(self, other): - from .multi_constraint import MultiConstraint - - if isinstance(other, Constraint): - if other == self: - return self - - if self.operator == "!=" and other.operator == "==" and self.allows(other): - return other - - if other.operator == "!=" and self.operator == "==" and other.allows(self): - return self - - if other.operator == "!=" and self.operator == "!=": - return MultiConstraint(self, other) - - return EmptyConstraint() - - return other.intersect(self) - - def union(self, other): - if isinstance(other, Constraint): - from .union_constraint import UnionConstraint - - return UnionConstraint(self, other) - - return other.union(self) - - def is_any(self): - return False - - def is_empty(self): - return False - - def __eq__(self, other): - if not isinstance(other, Constraint): - return NotImplemented - - return (self.version, self.operator) == (other.version, other.operator) - - def __hash__(self): - return hash((self._operator, self._version)) - - def __str__(self): - return "{}{}".format( - self._operator if self._operator != "==" else "", self._version - ) diff --git a/poetry/packages/constraints/empty_constraint.py b/poetry/packages/constraints/empty_constraint.py deleted file mode 100644 index 0a1c45ecc27..00000000000 --- a/poetry/packages/constraints/empty_constraint.py +++ /dev/null @@ -1,30 +0,0 @@ -from .base_constraint import BaseConstraint - - -class EmptyConstraint(BaseConstraint): - - pretty_string = None - - def matches(self, _): - return True - - def is_empty(self): - return True - - def allows_all(self, other): - return True - - def allows_any(self, other): - return True - - def intersect(self, other): - return other - - def difference(self, other): - return - - def __eq__(self, other): - return other.is_empty() - - def __str__(self): - return "" diff --git a/poetry/packages/constraints/multi_constraint.py b/poetry/packages/constraints/multi_constraint.py deleted file mode 100644 index 0bb63dd27a1..00000000000 --- a/poetry/packages/constraints/multi_constraint.py +++ /dev/null @@ -1,92 +0,0 @@ -from .base_constraint import BaseConstraint -from .constraint import Constraint - - -class MultiConstraint(BaseConstraint): - def __init__(self, *constraints): - if any(c.operator == "==" for c in constraints): - raise ValueError( - "A multi-constraint can only be comprised of negative constraints" - ) - - self._constraints = constraints - - @property - def constraints(self): - return self._constraints - - def allows(self, other): - for constraint in self._constraints: - if not constraint.allows(other): - return False - - return True - - def allows_all(self, other): - if other.is_any(): - return False - - if other.is_empty(): - return True - - if isinstance(other, Constraint): - return self.allows(other) - - our_constraints = iter(self._constraints) - their_constraints = iter(other.constraints) - our_constraint = next(our_constraints, None) - their_constraint = next(their_constraints, None) - - while our_constraint and their_constraint: - if our_constraint.allows_all(their_constraint): - their_constraint = next(their_constraints, None) - else: - our_constraint = next(our_constraints, None) - - return their_constraint is None - - def allows_any(self, other): - if other.is_any(): - return True - - if other.is_empty(): - return True - - if isinstance(other, Constraint): - return self.allows(other) - - if isinstance(other, MultiConstraint): - for c1 in self.constraints: - for c2 in other.constraints: - if c1.allows(c2): - return True - - return False - - def intersect(self, other): - if isinstance(other, Constraint): - constraints = self._constraints - if other not in constraints: - constraints += (other,) - else: - constraints = (other,) - - if len(constraints) == 1: - return constraints[0] - - return MultiConstraint(*constraints) - - def __eq__(self, other): - if not isinstance(other, MultiConstraint): - return False - - return sorted( - self._constraints, key=lambda c: (c.operator, c.version) - ) == sorted(other.constraints, key=lambda c: (c.operator, c.version)) - - def __str__(self): - constraints = [] - for constraint in self._constraints: - constraints.append(str(constraint)) - - return "{}".format(", ").join(constraints) diff --git a/poetry/packages/constraints/union_constraint.py b/poetry/packages/constraints/union_constraint.py deleted file mode 100644 index 8053154999b..00000000000 --- a/poetry/packages/constraints/union_constraint.py +++ /dev/null @@ -1,112 +0,0 @@ -from .base_constraint import BaseConstraint -from .constraint import Constraint -from .empty_constraint import EmptyConstraint - - -class UnionConstraint(BaseConstraint): - def __init__(self, *constraints): - self._constraints = constraints - - @property - def constraints(self): - return self._constraints - - def allows(self, other): - for constraint in self._constraints: - if constraint.allows(other): - return True - - return False - - def allows_any(self, other): - if other.is_empty(): - return False - - if other.is_any(): - return True - - if isinstance(other, Constraint): - constraints = [other] - else: - constraints = other.constraints - - for our_constraint in self._constraints: - for their_constraint in constraints: - if our_constraint.allows_any(their_constraint): - return True - - return False - - def allows_all(self, other): - if other.is_any(): - return False - - if other.is_empty(): - return True - - if isinstance(other, Constraint): - constraints = [other] - else: - constraints = other.constraints - - our_constraints = iter(self._constraints) - their_constraints = iter(constraints) - our_constraint = next(our_constraints, None) - their_constraint = next(their_constraints, None) - - while our_constraint and their_constraint: - if our_constraint.allows_all(their_constraint): - their_constraint = next(their_constraints, None) - else: - our_constraint = next(our_constraints, None) - - return their_constraint is None - - def intersect(self, other): - if other.is_any(): - return self - - if other.is_empty(): - return other - - if isinstance(other, Constraint): - if self.allows(other): - return other - - return EmptyConstraint() - - new_constraints = [] - for our_constraint in self._constraints: - for their_constraint in other.constraints: - intersection = our_constraint.intersect(their_constraint) - - if not intersection.is_empty() and intersection not in new_constraints: - new_constraints.append(intersection) - - if not new_constraints: - return EmptyConstraint() - - return UnionConstraint(*new_constraints) - - def union(self, other): - if isinstance(other, Constraint): - constraints = self._constraints - if other not in self._constraints: - constraints += (other,) - - return UnionConstraint(*constraints) - - def __eq__(self, other): - if not isinstance(other, UnionConstraint): - return False - - return sorted( - self._constraints, key=lambda c: (c.operator, c.version) - ) == sorted(other.constraints, key=lambda c: (c.operator, c.version)) - - def __str__(self): - constraints = [] - for constraint in self._constraints: - constraints.append(str(constraint)) - - return "{}".format(" || ").join(constraints) diff --git a/poetry/packages/constraints/wildcard_constraint.py b/poetry/packages/constraints/wildcard_constraint.py deleted file mode 100644 index ede8ffb647a..00000000000 --- a/poetry/packages/constraints/wildcard_constraint.py +++ /dev/null @@ -1,71 +0,0 @@ -import re - -from .constraint import Constraint - - -class WilcardConstraint(Constraint): - def __init__(self, constraint): # type: (str) -> None - m = re.match( - r"^(!= ?|==)?v?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:\.[xX*])+$", constraint - ) - if not m: - raise ValueError("Invalid value for wildcard constraint") - - if not m.group(1): - operator = "==" - else: - operator = m.group(1).strip() - - super(WilcardConstraint, self).__init__( - operator, ".".join([g if g else "*" for g in m.groups()[1:]]) - ) - - if m.group(4): - position = 2 - elif m.group(3): - position = 1 - else: - position = 0 - - from ..version_parser import VersionParser - - parser = VersionParser() - groups = m.groups()[1:] - low_version = parser._manipulate_version_string(groups, position) - high_version = parser._manipulate_version_string(groups, position, 1) - - if operator == "!=": - if low_version == "0.0.0.0": - self._constraint = Constraint(">=", high_version) - else: - self._constraint = parser.parse_constraints( - "<{} || >={}".format(low_version, high_version) - ) - else: - if low_version == "0.0.0.0": - self._constraint = Constraint("<", high_version) - else: - self._constraint = parser.parse_constraints( - ">={},<{}".format(low_version, high_version) - ) - - @property - def supported_operators(self): - return ["!=", "=="] - - @property - def constraint(self): - return self._constraint - - def matches(self, provider): # type: (Constraint) -> bool - if isinstance(provider, self.__class__): - return self._constraint.matches(provider.constraint) - - return provider.matches(self._constraint) - - def __str__(self): - op = "" - if self.string_operator == "!=": - op = "!= " - - return "{}{}".format(op, self._version) diff --git a/poetry/packages/dependency.py b/poetry/packages/dependency.py deleted file mode 100644 index 83ad36a129c..00000000000 --- a/poetry/packages/dependency.py +++ /dev/null @@ -1,361 +0,0 @@ -from typing import Optional - -import poetry.packages - -from poetry.semver import Version -from poetry.semver import VersionConstraint -from poetry.semver import VersionRange -from poetry.semver import VersionUnion -from poetry.semver import parse_constraint -from poetry.utils.helpers import canonicalize_name -from poetry.version.markers import AnyMarker -from poetry.version.markers import parse_marker - -from .constraints import parse_constraint as parse_generic_constraint -from .constraints.constraint import Constraint -from .constraints.multi_constraint import MultiConstraint -from .constraints.union_constraint import UnionConstraint -from .utils.utils import convert_markers - - -class Dependency(object): - def __init__( - self, - name, # type: str - constraint, # type: str - optional=False, # type: bool - category="main", # type: str - allows_prereleases=False, # type: bool - source_name=None, # type: Optional[str] - ): - self._name = canonicalize_name(name) - self._pretty_name = name - - try: - if not isinstance(constraint, VersionConstraint): - self._constraint = parse_constraint(constraint) - else: - self._constraint = constraint - except ValueError: - self._constraint = parse_constraint("*") - - self._pretty_constraint = str(constraint) - self._optional = optional - self._category = category - - if isinstance(self._constraint, VersionRange) and self._constraint.min: - allows_prereleases = ( - allows_prereleases or self._constraint.min.is_prerelease() - ) - - self._allows_prereleases = allows_prereleases - self._source_name = source_name - - self._python_versions = "*" - self._python_constraint = parse_constraint("*") - self._transitive_python_versions = None - self._transitive_python_constraint = None - self._transitive_marker = None - - self._extras = [] - self._in_extras = [] - - self._activated = not self._optional - - self.is_root = False - self.marker = AnyMarker() - - @property - def name(self): - return self._name - - @property - def constraint(self): - return self._constraint - - @property - def pretty_constraint(self): - return self._pretty_constraint - - @property - def pretty_name(self): - return self._pretty_name - - @property - def category(self): - return self._category - - @property - def source_name(self): - return self._source_name - - @property - def python_versions(self): - return self._python_versions - - @python_versions.setter - def python_versions(self, value): - self._python_versions = value - self._python_constraint = parse_constraint(value) - if not self._python_constraint.is_any(): - self.marker = self.marker.intersect( - parse_marker( - self._create_nested_marker( - "python_version", self._python_constraint - ) - ) - ) - - @property - def transitive_python_versions(self): - if self._transitive_python_versions is None: - return self._python_versions - - return self._transitive_python_versions - - @transitive_python_versions.setter - def transitive_python_versions(self, value): - self._transitive_python_versions = value - self._transitive_python_constraint = parse_constraint(value) - - @property - def transitive_marker(self): - if self._transitive_marker is None: - return self.marker - - return self._transitive_marker - - @transitive_marker.setter - def transitive_marker(self, value): - self._transitive_marker = value - - @property - def python_constraint(self): - return self._python_constraint - - @property - def transitive_python_constraint(self): - if self._transitive_python_constraint is None: - return self._python_constraint - - return self._transitive_python_constraint - - @property - def extras(self): # type: () -> list - return self._extras - - @property - def in_extras(self): # type: () -> list - 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): - if self.constraint.excludes_single_version(): - requirement += " ({})".format(str(self.constraint)) - else: - requirement += " ({})".format(self.pretty_constraint) - 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): - return self._allows_prereleases - - def is_optional(self): - return self._optional - - def is_activated(self): - return self._activated - - def is_vcs(self): - return False - - def is_file(self): - return False - - def is_directory(self): - return False - - def is_url(self): - return False - - def accepts(self, package): # type: (poetry.packages.Package) -> bool - """ - Determines if the given package matches this dependency. - """ - return ( - self._name == package.name - and self._constraint.allows(package.version) - and (not package.is_prerelease() or self.allows_prereleases()) - ) - - def to_pep_508(self, with_extras=True): # type: (bool) -> str - requirement = self.base_pep_508_name - - markers = [] - has_extras = False - if not self.marker.is_any(): - marker = self.marker - if not with_extras: - marker = marker.without_extras() - - if not marker.is_empty(): - markers.append(str(marker)) - - has_extras = "extra" in convert_markers(marker) - else: - # Python marker - if self.python_versions != "*": - python_constraint = self.python_constraint - - markers.append( - self._create_nested_marker("python_version", python_constraint) - ) - - in_extras = " || ".join(self._in_extras) - if in_extras and with_extras and not has_extras: - markers.append( - self._create_nested_marker("extra", parse_generic_constraint(in_extras)) - ) - - if markers: - if self.is_vcs(): - requirement += " " - - if len(markers) > 1: - markers = ["({})".format(m) for m in markers] - requirement += "; {}".format(" and ".join(markers)) - else: - requirement += "; {}".format(markers[0]) - - return requirement - - def _create_nested_marker(self, name, constraint): - if isinstance(constraint, (MultiConstraint, UnionConstraint)): - parts = [] - for c in constraint.constraints: - multi = False - if isinstance(c, (MultiConstraint, UnionConstraint)): - multi = True - - parts.append((multi, self._create_nested_marker(name, c))) - - glue = " and " - if isinstance(constraint, UnionConstraint): - parts = [ - "({})".format(part[1]) if part[0] else part[1] for part in parts - ] - glue = " or " - else: - parts = [part[1] for part in parts] - - marker = glue.join(parts) - elif isinstance(constraint, Constraint): - marker = '{} {} "{}"'.format(name, constraint.operator, constraint.version) - elif isinstance(constraint, VersionUnion): - parts = [] - for c in constraint.ranges: - parts.append(self._create_nested_marker(name, c)) - - glue = " or " - parts = ["({})".format(part) for part in parts] - - marker = glue.join(parts) - elif isinstance(constraint, Version): - marker = '{} == "{}"'.format(name, constraint.text) - else: - if constraint.min is not None: - op = ">=" - if not constraint.include_min: - op = ">" - - version = constraint.min.text - if constraint.max is not None: - text = '{} {} "{}"'.format(name, op, version) - - op = "<=" - if not constraint.include_max: - op = "<" - - version = constraint.max - - text += ' and {} {} "{}"'.format(name, op, version) - - return text - elif constraint.max is not None: - op = "<=" - if not constraint.include_max: - op = "<" - - version = constraint.max - else: - return "" - - marker = '{} {} "{}"'.format(name, op, version) - - return marker - - def activate(self): - """ - Set the dependency as mandatory. - """ - self._activated = True - - def deactivate(self): - """ - Set the dependency as optional. - """ - if not self._optional: - self._optional = True - - self._activated = False - - def with_constraint(self, constraint): - new = Dependency( - self.pretty_name, - constraint, - optional=self.is_optional(), - category=self.category, - allows_prereleases=self.allows_prereleases(), - ) - - new.is_root = self.is_root - new.python_versions = self.python_versions - - for extra in self.extras: - new.extras.append(extra) - - for in_extra in self.in_extras: - new.in_extras.append(in_extra) - - return new - - def __eq__(self, other): - if not isinstance(other, Dependency): - return NotImplemented - - return self._name == other.name and self._constraint == other.constraint - - def __ne__(self, other): - return not self == other - - def __hash__(self): - return hash((self._name, self._pretty_constraint)) - - def __str__(self): - if self.is_root: - return self._pretty_name - - return "{} ({})".format(self._pretty_name, self._pretty_constraint) - - def __repr__(self): - return "<{} {}>".format(self.__class__.__name__, str(self)) diff --git a/poetry/packages/directory_dependency.py b/poetry/packages/directory_dependency.py deleted file mode 100644 index ac4bca8ea82..00000000000 --- a/poetry/packages/directory_dependency.py +++ /dev/null @@ -1,81 +0,0 @@ -from pkginfo.distribution import HEADER_ATTRS -from pkginfo.distribution import HEADER_ATTRS_2_0 - -from poetry.utils._compat import Path -from poetry.utils.toml_file import TomlFile - -from .dependency import Dependency - - -# Patching pkginfo to support Metadata version 2.1 (PEP 566) -HEADER_ATTRS.update( - {"2.1": HEADER_ATTRS_2_0 + (("Provides-Extra", "provides_extra", True),)} -) - - -class DirectoryDependency(Dependency): - def __init__( - self, - name, - path, # type: Path - category="main", # type: str - optional=False, # type: bool - base=None, # type: Path - develop=True, # type: bool - ): - self._path = path - self._base = base - self._full_path = path - self._develop = develop - self._supports_poetry = False - - if self._base and not self._path.is_absolute(): - self._full_path = self._base / self._path - - if not self._full_path.exists(): - raise ValueError("Directory {} does not exist".format(self._path)) - - if self._full_path.is_file(): - raise ValueError("{} is a file, expected a directory".format(self._path)) - - # Checking content to determine actions - setup = self._full_path / "setup.py" - pyproject = TomlFile(self._full_path / "pyproject.toml") - if pyproject.exists(): - pyproject_content = pyproject.read() - self._supports_poetry = ( - "tool" in pyproject_content and "poetry" in pyproject_content["tool"] - ) - - if not setup.exists() and not self._supports_poetry: - raise ValueError( - "Directory {} does not seem to be a Python package".format( - self._full_path - ) - ) - - super(DirectoryDependency, self).__init__( - name, "*", category=category, optional=optional, allows_prereleases=True - ) - - @property - def path(self): - return self._path - - @property - def full_path(self): - return self._full_path.resolve() - - @property - def base(self): - return self._base - - @property - def develop(self): - return self._develop - - def supports_poetry(self): - return self._supports_poetry - - def is_directory(self): - return True diff --git a/poetry/packages/file_dependency.py b/poetry/packages/file_dependency.py deleted file mode 100644 index b91d296a512..00000000000 --- a/poetry/packages/file_dependency.py +++ /dev/null @@ -1,61 +0,0 @@ -import hashlib -import io - -from pkginfo.distribution import HEADER_ATTRS -from pkginfo.distribution import HEADER_ATTRS_2_0 - -from poetry.utils._compat import Path - -from .dependency import Dependency - - -# Patching pkginfo to support Metadata version 2.1 (PEP 566) -HEADER_ATTRS.update( - {"2.1": HEADER_ATTRS_2_0 + (("Provides-Extra", "provides_extra", True),)} -) - - -class FileDependency(Dependency): - def __init__( - self, - name, - path, # type: Path - category="main", # type: str - optional=False, # type: bool - base=None, # type: Path - ): - self._path = path - self._base = base - self._full_path = path - - if self._base and not self._path.is_absolute(): - self._full_path = self._base / self._path - - if not self._full_path.exists(): - raise ValueError("File {} does not exist".format(self._path)) - - if self._full_path.is_dir(): - raise ValueError("{} is a directory, expected a file".format(self._path)) - - super(FileDependency, self).__init__( - name, "*", category=category, optional=optional, allows_prereleases=True - ) - - @property - def path(self): - return self._path - - @property - def full_path(self): - return self._full_path.resolve() - - def is_file(self): - return True - - def hash(self): - h = hashlib.sha256() - with self._full_path.open("rb") as fp: - for content in iter(lambda: fp.read(io.DEFAULT_BUFFER_SIZE), b""): - h.update(content) - - return h.hexdigest() diff --git a/poetry/packages/locker.py b/poetry/packages/locker.py index f2eca202e81..722df01245c 100644 --- a/poetry/packages/locker.py +++ b/poetry/packages/locker.py @@ -10,12 +10,13 @@ from tomlkit import table from tomlkit.exceptions import TOMLKitError -import poetry.packages import poetry.repositories +from poetry.core.packages.package import Dependency +from poetry.core.packages.package import Package +from poetry.core.version.markers import parse_marker from poetry.utils._compat import Path from poetry.utils.toml_file import TomlFile -from poetry.version.markers import parse_marker class Locker(object): @@ -83,9 +84,7 @@ def locked_repository( return packages for info in locked_packages: - package = poetry.packages.Package( - info["name"], info["version"], info["version"] - ) + package = Package(info["name"], info["version"], info["version"]) package.description = info.get("description", "") package.category = info["category"] package.optional = info["optional"] @@ -109,16 +108,14 @@ def locked_repository( dep_name = m.group(1) constraint = m.group(2) or "*" - package.extras[name].append( - poetry.packages.Dependency(dep_name, constraint) - ) + package.extras[name].append(Dependency(dep_name, constraint)) if "marker" in info: package.marker = parse_marker(info["marker"]) else: # Compatibility for old locks if "requirements" in info: - dep = poetry.packages.Dependency("foo", "0.0.0") + dep = Dependency("foo", "0.0.0") for name, value in info["requirements"].items(): if name == "python": dep.python_versions = value @@ -238,7 +235,7 @@ def _lock_packages( return locked - def _dump_package(self, package): # type: (poetry.packages.Package) -> dict + def _dump_package(self, package): # type: (Package) -> dict dependencies = {} for dependency in sorted(package.requires, key=lambda d: d.name): if dependency.is_optional() and not dependency.is_activated(): @@ -250,7 +247,7 @@ def _dump_package(self, package): # type: (poetry.packages.Package) -> dict constraint = {"version": str(dependency.pretty_constraint)} if dependency.extras: - constraint["extras"] = dependency.extras + constraint["extras"] = sorted(dependency.extras) if dependency.is_optional(): constraint["optional"] = True diff --git a/poetry/packages/package.py b/poetry/packages/package.py deleted file mode 100644 index 5b7dfea09d1..00000000000 --- a/poetry/packages/package.py +++ /dev/null @@ -1,439 +0,0 @@ -# -*- coding: utf-8 -*- -import copy -import logging -import re - -from contextlib import contextmanager -from typing import Union -from warnings import warn - -from poetry.semver import Version -from poetry.semver import parse_constraint -from poetry.spdx import License -from poetry.spdx import license_by_id -from poetry.utils._compat import Path -from poetry.utils.helpers import canonicalize_name -from poetry.version.markers import AnyMarker -from poetry.version.markers import parse_marker - -from .constraints import parse_constraint as parse_generic_constraint -from .dependency import Dependency -from .directory_dependency import DirectoryDependency -from .file_dependency import FileDependency -from .url_dependency import URLDependency -from .utils.utils import create_nested_marker -from .vcs_dependency import VCSDependency - - -AUTHOR_REGEX = re.compile(r"(?u)^(?P[- .,\w\d'’\"()]+)(?: <(?P.+?)>)?$") - -logger = logging.getLogger(__name__) - - -class Package(object): - - AVAILABLE_PYTHONS = {"2", "2.7", "3", "3.4", "3.5", "3.6", "3.7", "3.8"} - - def __init__(self, name, version, pretty_version=None): - """ - Creates a new in memory package. - """ - self._pretty_name = name - self._name = canonicalize_name(name) - - if not isinstance(version, Version): - self._version = Version.parse(version) - self._pretty_version = pretty_version or version - else: - self._version = version - self._pretty_version = pretty_version or self._version.text - - self.description = "" - - self._authors = [] - self._maintainers = [] - - self.homepage = None - self.repository_url = None - self.documentation_url = None - self.keywords = [] - self._license = None - self.readme = None - - self.source_name = "" - self.source_type = "" - self.source_reference = "" - self.source_url = "" - - self.requires = [] - self.dev_requires = [] - self.extras = {} - self.requires_extras = [] - - self.category = "main" - self.files = [] - self.optional = False - - self.classifiers = [] - - self._python_versions = "*" - self._python_constraint = parse_constraint("*") - self._python_marker = AnyMarker() - - self.platform = None - self.marker = AnyMarker() - - self.root_dir = None - - self.develop = True - - @property - def name(self): - return self._name - - @property - def pretty_name(self): - return self._pretty_name - - @property - def version(self): - return self._version - - @property - def pretty_version(self): - return self._pretty_version - - @property - def unique_name(self): - if self.is_root(): - return self._name - - return self.name + "-" + self._version.text - - @property - def pretty_string(self): - return self.pretty_name + " " + self.pretty_version - - @property - def full_pretty_version(self): - if self.source_type in ["file", "directory", "url"]: - return "{} {}".format(self._pretty_version, self.source_url) - - if self.source_type not in ["hg", "git"]: - return self._pretty_version - - # if source reference is a sha1 hash -- truncate - if len(self.source_reference) == 40: - return "{} {}".format(self._pretty_version, self.source_reference[0:7]) - - return "{} {}".format(self._pretty_version, self.source_reference) - - @property - def authors(self): # type: () -> list - return self._authors - - @property - def author_name(self): # type: () -> str - return self._get_author()["name"] - - @property - def author_email(self): # type: () -> str - return self._get_author()["email"] - - @property - def maintainers(self): # type: () -> list - return self._maintainers - - @property - def maintainer_name(self): # type: () -> str - return self._get_maintainer()["name"] - - @property - def maintainer_email(self): # type: () -> str - return self._get_maintainer()["email"] - - @property - def all_requires(self): - return self.requires + self.dev_requires - - def _get_author(self): # type: () -> dict - if not self._authors: - return {"name": None, "email": None} - - m = AUTHOR_REGEX.match(self._authors[0]) - - name = m.group("name") - email = m.group("email") - - return {"name": name, "email": email} - - def _get_maintainer(self): # type: () -> dict - if not self._maintainers: - return {"name": None, "email": None} - - m = AUTHOR_REGEX.match(self._maintainers[0]) - - name = m.group("name") - email = m.group("email") - - return {"name": name, "email": email} - - @property - def python_versions(self): - return self._python_versions - - @python_versions.setter - def python_versions(self, value): - self._python_versions = value - self._python_constraint = parse_constraint(value) - self._python_marker = parse_marker( - create_nested_marker("python_version", self._python_constraint) - ) - - @property - def python_constraint(self): - return self._python_constraint - - @property - def python_marker(self): - return self._python_marker - - @property - def license(self): - return self._license - - @license.setter - def license(self, value): - if value is None: - self._license = value - elif isinstance(value, License): - self._license = value - else: - self._license = license_by_id(value) - - @property - def all_classifiers(self): - classifiers = copy.copy(self.classifiers) - - # Automatically set python classifiers - if self.python_versions == "*": - python_constraint = parse_constraint("~2.7 || ^3.4") - else: - python_constraint = self.python_constraint - - for version in sorted(self.AVAILABLE_PYTHONS): - if len(version) == 1: - constraint = parse_constraint(version + ".*") - else: - constraint = Version.parse(version) - - if python_constraint.allows_any(constraint): - classifiers.append( - "Programming Language :: Python :: {}".format(version) - ) - - # Automatically set license classifiers - if self.license: - classifiers.append(self.license.classifier) - - classifiers = set(classifiers) - - return sorted(classifiers) - - @property - def urls(self): - urls = {} - - if self.homepage: - urls["Homepage"] = self.homepage - - if self.repository_url: - urls["Repository"] = self.repository_url - - if self.documentation_url: - urls["Documentation"] = self.documentation_url - - return urls - - def is_prerelease(self): - return self._version.is_prerelease() - - def is_root(self): - return False - - def add_dependency( - self, - name, # type: str - constraint=None, # type: Union[str, dict, None] - category="main", # type: str - ): # type: (...) -> Dependency - if constraint is None: - constraint = "*" - - if isinstance(constraint, dict): - optional = constraint.get("optional", False) - python_versions = constraint.get("python") - platform = constraint.get("platform") - markers = constraint.get("markers") - if "allows-prereleases" in constraint: - message = ( - 'The "{}" dependency specifies ' - 'the "allows-prereleases" property, which is deprecated. ' - 'Use "allow-prereleases" instead.'.format(name) - ) - warn(message, DeprecationWarning) - logger.warning(message) - - allows_prereleases = constraint.get( - "allow-prereleases", constraint.get("allows-prereleases", False) - ) - - if "git" in constraint: - # VCS dependency - dependency = VCSDependency( - name, - "git", - constraint["git"], - branch=constraint.get("branch", None), - tag=constraint.get("tag", None), - rev=constraint.get("rev", None), - category=category, - optional=optional, - ) - elif "file" in constraint: - file_path = Path(constraint["file"]) - - dependency = FileDependency( - name, file_path, category=category, base=self.root_dir - ) - elif "path" in constraint: - path = Path(constraint["path"]) - - if self.root_dir: - is_file = (self.root_dir / path).is_file() - else: - is_file = path.is_file() - - if is_file: - dependency = FileDependency( - name, - path, - category=category, - optional=optional, - base=self.root_dir, - ) - else: - dependency = DirectoryDependency( - name, - path, - category=category, - optional=optional, - base=self.root_dir, - develop=constraint.get("develop", True), - ) - elif "url" in constraint: - dependency = URLDependency(name, constraint["url"], category=category) - else: - version = constraint["version"] - - dependency = Dependency( - name, - version, - optional=optional, - category=category, - allows_prereleases=allows_prereleases, - source_name=constraint.get("source"), - ) - - if not markers: - marker = AnyMarker() - if python_versions: - dependency.python_versions = python_versions - marker = marker.intersect( - parse_marker( - create_nested_marker( - "python_version", dependency.python_constraint - ) - ) - ) - - if platform: - marker = marker.intersect( - parse_marker( - create_nested_marker( - "sys_platform", parse_generic_constraint(platform) - ) - ) - ) - else: - marker = parse_marker(markers) - - if not marker.is_any(): - dependency.marker = marker - - if "extras" in constraint: - for extra in constraint["extras"]: - dependency.extras.append(extra) - else: - dependency = Dependency(name, constraint, category=category) - - if category == "dev": - self.dev_requires.append(dependency) - else: - self.requires.append(dependency) - - return dependency - - def to_dependency(self): - from . import dependency_from_pep_508 - - name = "{} (=={})".format(self._name, self._version) - - if not self.marker.is_any(): - name += " ; {}".format(str(self.marker)) - - return dependency_from_pep_508(name) - - @contextmanager - def with_python_versions(self, python_versions): - original_python_versions = self.python_versions - - self.python_versions = python_versions - - yield - - self.python_versions = original_python_versions - - def clone(self): # type: () -> Package - clone = self.__class__(self.pretty_name, self.version) - clone.category = self.category - clone.optional = self.optional - clone.python_versions = self.python_versions - clone.marker = self.marker - clone.extras = self.extras - clone.source_type = self.source_type - clone.source_url = self.source_url - clone.source_reference = self.source_reference - - for dep in self.requires: - clone.requires.append(dep) - - for dep in self.dev_requires: - clone.dev_requires.append(dep) - - return clone - - def __hash__(self): - return hash((self._name, self._version)) - - def __eq__(self, other): - if not isinstance(other, Package): - return NotImplemented - - return self._name == other.name and self._version == other.version - - def __str__(self): - return self.unique_name - - def __repr__(self): - return "".format(self.unique_name) diff --git a/poetry/packages/project_package.py b/poetry/packages/project_package.py deleted file mode 100644 index 584da3a8ed4..00000000000 --- a/poetry/packages/project_package.py +++ /dev/null @@ -1,64 +0,0 @@ -from poetry.semver import VersionRange -from poetry.semver import parse_constraint -from poetry.version.markers import parse_marker - -from .package import Package -from .utils.utils import create_nested_marker - - -class ProjectPackage(Package): - def __init__(self, name, version, pretty_version=None): - super(ProjectPackage, self).__init__(name, version, pretty_version) - - self.build = None - self.packages = [] - self.include = [] - self.exclude = [] - self.custom_urls = {} - - if self._python_versions == "*": - self._python_constraint = parse_constraint("~2.7 || >=3.4") - - def is_root(self): - return True - - def to_dependency(self): - dependency = super(ProjectPackage, self).to_dependency() - - dependency.is_root = True - - return dependency - - @property - def python_versions(self): - return self._python_versions - - @python_versions.setter - def python_versions(self, value): - self._python_versions = value - - if value == "*" or value == VersionRange(): - value = "~2.7 || >=3.4" - - self._python_constraint = parse_constraint(value) - self._python_marker = parse_marker( - create_nested_marker("python_version", self._python_constraint) - ) - - @property - def urls(self): - urls = super(ProjectPackage, self).urls - - urls.update(self.custom_urls) - - return urls - - def clone(self): # type: () -> ProjectPackage - package = super(ProjectPackage, self).clone() - - package.build = self.build - package.packages = self.packages[:] - package.include = self.include[:] - package.exclude = self.exclude[:] - - return package diff --git a/poetry/packages/url_dependency.py b/poetry/packages/url_dependency.py deleted file mode 100644 index f128dc49366..00000000000 --- a/poetry/packages/url_dependency.py +++ /dev/null @@ -1,40 +0,0 @@ -from poetry.utils._compat import urlparse - -from .dependency import Dependency - - -class URLDependency(Dependency): - def __init__( - self, - name, - url, # type: str - category="main", # type: str - optional=False, # type: bool - ): - self._url = url - - parsed = urlparse.urlparse(url) - if not parsed.scheme or not parsed.netloc: - raise ValueError("{} does not seem like a valid url".format(url)) - - super(URLDependency, self).__init__( - name, "*", category=category, optional=optional, allows_prereleases=True - ) - - @property - def url(self): - return self._url - - @property - def base_pep_508_name(self): # type: () -> str - requirement = self.pretty_name - - if self.extras: - requirement += "[{}]".format(",".join(self.extras)) - - requirement += " @ {}".format(self._url) - - return requirement - - def is_url(self): # type: () -> bool - return True diff --git a/poetry/packages/utils/link.py b/poetry/packages/utils/link.py deleted file mode 100644 index 86f0b7ac810..00000000000 --- a/poetry/packages/utils/link.py +++ /dev/null @@ -1,166 +0,0 @@ -import posixpath -import re - -from .utils import path_to_url -from .utils import splitext - - -try: - import urllib.parse as urlparse -except ImportError: - import urlparse - - -class Link: - def __init__(self, url, comes_from=None, requires_python=None): - """ - Object representing a parsed link from https://pypi.python.org/simple/* - - url: - url of the resource pointed to (href of the link) - comes_from: - instance of HTMLPage where the link was found, or string. - requires_python: - String containing the `Requires-Python` metadata field, specified - in PEP 345. This may be specified by a data-requires-python - attribute in the HTML link tag, as described in PEP 503. - """ - - # url can be a UNC windows share - if url.startswith("\\\\"): - url = path_to_url(url) - - self.url = url - self.comes_from = comes_from - self.requires_python = requires_python if requires_python else None - - def __str__(self): - if self.requires_python: - rp = " (requires-python:%s)" % self.requires_python - else: - rp = "" - if self.comes_from: - return "%s (from %s)%s" % (self.url, self.comes_from, rp) - else: - return str(self.url) - - def __repr__(self): - return "" % self - - def __eq__(self, other): - if not isinstance(other, Link): - return NotImplemented - return self.url == other.url - - def __ne__(self, other): - if not isinstance(other, Link): - return NotImplemented - return self.url != other.url - - def __lt__(self, other): - if not isinstance(other, Link): - return NotImplemented - return self.url < other.url - - def __le__(self, other): - if not isinstance(other, Link): - return NotImplemented - return self.url <= other.url - - def __gt__(self, other): - if not isinstance(other, Link): - return NotImplemented - return self.url > other.url - - def __ge__(self, other): - if not isinstance(other, Link): - return NotImplemented - return self.url >= other.url - - def __hash__(self): - return hash(self.url) - - @property - def filename(self): - _, netloc, path, _, _ = urlparse.urlsplit(self.url) - name = posixpath.basename(path.rstrip("/")) or netloc - name = urlparse.unquote(name) - assert name, "URL %r produced no filename" % self.url - return name - - @property - def scheme(self): - return urlparse.urlsplit(self.url)[0] - - @property - def netloc(self): - return urlparse.urlsplit(self.url)[1] - - @property - def path(self): - return urlparse.unquote(urlparse.urlsplit(self.url)[2]) - - def splitext(self): - return splitext(posixpath.basename(self.path.rstrip("/"))) - - @property - def ext(self): - return self.splitext()[1] - - @property - def url_without_fragment(self): - scheme, netloc, path, query, fragment = urlparse.urlsplit(self.url) - return urlparse.urlunsplit((scheme, netloc, path, query, None)) - - _egg_fragment_re = re.compile(r"[#&]egg=([^&]*)") - - @property - def egg_fragment(self): - match = self._egg_fragment_re.search(self.url) - if not match: - return None - return match.group(1) - - _subdirectory_fragment_re = re.compile(r"[#&]subdirectory=([^&]*)") - - @property - def subdirectory_fragment(self): - match = self._subdirectory_fragment_re.search(self.url) - if not match: - return None - return match.group(1) - - _hash_re = re.compile(r"(sha1|sha224|sha384|sha256|sha512|md5)=([a-f0-9]+)") - - @property - def hash(self): - match = self._hash_re.search(self.url) - if match: - return match.group(2) - return None - - @property - def hash_name(self): - match = self._hash_re.search(self.url) - if match: - return match.group(1) - return None - - @property - def show_url(self): - return posixpath.basename(self.url.split("#", 1)[0].split("?", 1)[0]) - - @property - def is_wheel(self): - return self.ext == ".whl" - - @property - def is_artifact(self): - """ - Determines if this points to an actual artifact (e.g. a tarball) or if - it points to an "abstract" thing like a path or a VCS location. - """ - if self.scheme in ["ssh", "git", "hg", "bzr", "sftp", "svn"]: - return False - - return True diff --git a/poetry/packages/utils/utils.py b/poetry/packages/utils/utils.py deleted file mode 100644 index 03dfb84fda6..00000000000 --- a/poetry/packages/utils/utils.py +++ /dev/null @@ -1,306 +0,0 @@ -import os -import posixpath -import re - -from poetry.packages.constraints.constraint import Constraint -from poetry.packages.constraints.multi_constraint import MultiConstraint -from poetry.packages.constraints.union_constraint import UnionConstraint -from poetry.semver import EmptyConstraint -from poetry.semver import Version -from poetry.semver import VersionConstraint -from poetry.semver import VersionRange -from poetry.semver import VersionUnion -from poetry.semver import parse_constraint -from poetry.version.markers import BaseMarker -from poetry.version.markers import MarkerUnion -from poetry.version.markers import MultiMarker -from poetry.version.markers import SingleMarker - - -try: - import urllib.parse as urlparse -except ImportError: - import urlparse - - -try: - import urllib.request as urllib2 -except ImportError: - import urllib2 - - -BZ2_EXTENSIONS = (".tar.bz2", ".tbz") -XZ_EXTENSIONS = (".tar.xz", ".txz", ".tlz", ".tar.lz", ".tar.lzma") -ZIP_EXTENSIONS = (".zip", ".whl") -TAR_EXTENSIONS = (".tar.gz", ".tgz", ".tar") -ARCHIVE_EXTENSIONS = ZIP_EXTENSIONS + BZ2_EXTENSIONS + TAR_EXTENSIONS + XZ_EXTENSIONS -SUPPORTED_EXTENSIONS = ZIP_EXTENSIONS + TAR_EXTENSIONS - -try: - import bz2 # noqa - - SUPPORTED_EXTENSIONS += BZ2_EXTENSIONS -except ImportError: - pass - -try: - # Only for Python 3.3+ - import lzma # noqa - - SUPPORTED_EXTENSIONS += XZ_EXTENSIONS -except ImportError: - pass - - -def path_to_url(path): - """ - Convert a path to a file: URL. The path will be made absolute and have - quoted path parts. - """ - path = os.path.normpath(os.path.abspath(path)) - url = urlparse.urljoin("file:", urllib2.pathname2url(path)) - return url - - -def is_url(name): - if ":" not in name: - return False - scheme = name.split(":", 1)[0].lower() - - return scheme in [ - "http", - "https", - "file", - "ftp", - "ssh", - "git", - "hg", - "bzr", - "sftp", - "svn" "ssh", - ] - - -def strip_extras(path): - m = re.match(r"^(.+)(\[[^\]]+\])$", path) - extras = None - if m: - path_no_extras = m.group(1) - extras = m.group(2) - else: - path_no_extras = path - - return path_no_extras, extras - - -def is_installable_dir(path): - """Return True if `path` is a directory containing a setup.py file.""" - if not os.path.isdir(path): - return False - setup_py = os.path.join(path, "setup.py") - if os.path.isfile(setup_py): - return True - return False - - -def is_archive_file(name): - """Return True if `name` is a considered as an archive file.""" - ext = splitext(name)[1].lower() - if ext in ARCHIVE_EXTENSIONS: - return True - return False - - -def splitext(path): - """Like os.path.splitext, but take off .tar too""" - base, ext = posixpath.splitext(path) - if base.lower().endswith(".tar"): - ext = base[-4:] + ext - base = base[:-4] - return base, ext - - -def group_markers(markers, or_=False): - groups = [[]] - - for marker in markers: - if or_: - groups.append([]) - - if isinstance(marker, (MultiMarker, MarkerUnion)): - groups[-1].append( - group_markers(marker.markers, isinstance(marker, MarkerUnion)) - ) - elif isinstance(marker, SingleMarker): - lhs, op, rhs = marker.name, marker.operator, marker.value - - groups[-1].append((lhs, op, rhs)) - - return groups - - -def convert_markers(marker): - groups = group_markers([marker]) - - requirements = {} - - def _group(_groups, or_=False): - ors = {} - for group in _groups: - if isinstance(group, list): - _group(group, or_=True) - else: - variable, op, value = group - group_name = str(variable) - - # python_full_version is equivalent to python_version - # for Poetry so we merge them - if group_name == "python_full_version": - group_name = "python_version" - - if group_name not in requirements: - requirements[group_name] = [] - - if group_name not in ors: - ors[group_name] = or_ - - if ors[group_name] or not requirements[group_name]: - requirements[group_name].append([]) - - requirements[group_name][-1].append((str(op), str(value))) - - ors[group_name] = False - - _group(groups, or_=True) - - return requirements - - -def create_nested_marker(name, constraint): - if constraint.is_any(): - return "" - - if isinstance(constraint, (MultiConstraint, UnionConstraint)): - parts = [] - for c in constraint.constraints: - multi = False - if isinstance(c, (MultiConstraint, UnionConstraint)): - multi = True - - parts.append((multi, create_nested_marker(name, c))) - - glue = " and " - if isinstance(constraint, UnionConstraint): - parts = ["({})".format(part[1]) if part[0] else part[1] for part in parts] - glue = " or " - else: - parts = [part[1] for part in parts] - - marker = glue.join(parts) - elif isinstance(constraint, Constraint): - marker = '{} {} "{}"'.format(name, constraint.operator, constraint.version) - elif isinstance(constraint, VersionUnion): - parts = [] - for c in constraint.ranges: - parts.append(create_nested_marker(name, c)) - - glue = " or " - parts = ["({})".format(part) for part in parts] - - marker = glue.join(parts) - elif isinstance(constraint, Version): - marker = '{} == "{}"'.format(name, constraint.text) - else: - if constraint.min is not None: - op = ">=" - if not constraint.include_min: - op = ">" - - version = constraint.min.text - if constraint.max is not None: - text = '{} {} "{}"'.format(name, op, version) - - op = "<=" - if not constraint.include_max: - op = "<" - - version = constraint.max - - text += ' and {} {} "{}"'.format(name, op, version) - - return text - elif constraint.max is not None: - op = "<=" - if not constraint.include_max: - op = "<" - - version = constraint.max - else: - return "" - - marker = '{} {} "{}"'.format(name, op, version) - - return marker - - -def get_python_constraint_from_marker( - marker, -): # type: (BaseMarker) -> VersionConstraint - python_marker = marker.only("python_version") - if python_marker.is_any(): - return VersionRange() - - if python_marker.is_empty(): - return EmptyConstraint() - - markers = convert_markers(marker) - - ors = [] - for or_ in markers["python_version"]: - ands = [] - for op, version in or_: - # Expand python version - if op == "==": - version = "~" + version - op = "" - elif op == "!=": - 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"): - versions = [] - for v in re.split("[ ,]+", version): - split = v.split(".") - if len(split) in [1, 2]: - split.append("*") - op_ = "" if op == "in" else "!=" - else: - op_ = "==" if op == "in" else "!=" - - versions.append(op_ + ".".join(split)) - - glue = " || " if op == "in" else ", " - if versions: - ands.append(glue.join(versions)) - - continue - - ands.append("{}{}".format(op, version)) - - ors.append(" ".join(ands)) - - return parse_constraint(" || ".join(ors)) diff --git a/poetry/packages/vcs_dependency.py b/poetry/packages/vcs_dependency.py deleted file mode 100644 index 7574b8dbac3..00000000000 --- a/poetry/packages/vcs_dependency.py +++ /dev/null @@ -1,96 +0,0 @@ -from poetry.vcs import git - -from .dependency import Dependency - - -class VCSDependency(Dependency): - """ - Represents a VCS dependency - """ - - def __init__( - self, - name, - vcs, - source, - branch=None, - tag=None, - rev=None, - category="main", - optional=False, - ): - self._vcs = vcs - self._source = source - - if not any([branch, tag, rev]): - # If nothing has been specified, we assume master - branch = "master" - - self._branch = branch - self._tag = tag - self._rev = rev - - super(VCSDependency, self).__init__( - name, "*", category=category, optional=optional, allows_prereleases=True - ) - - @property - def vcs(self): - return self._vcs - - @property - def source(self): - return self._source - - @property - def branch(self): - return self._branch - - @property - def tag(self): - return self._tag - - @property - def rev(self): - return self._rev - - @property - def reference(self): # type: () -> str - return self._branch or self._tag or self._rev - - @property - def pretty_constraint(self): # type: () -> str - if self._branch: - what = "branch" - version = self._branch - elif self._tag: - what = "tag" - version = self._tag - else: - what = "rev" - version = self._rev - - return "{} {}".format(what, version) - - @property - def base_pep_508_name(self): # type: () -> str - requirement = self.pretty_name - parsed_url = git.ParsedUrl.parse(self._source) - - if self.extras: - requirement += "[{}]".format(",".join(self.extras)) - - if parsed_url.protocol is not None: - requirement += " @ {}+{}@{}".format(self._vcs, self._source, self.reference) - else: - requirement += " @ {}+ssh://{}@{}".format( - self._vcs, parsed_url.format(), self.reference - ) - - return requirement - - def is_vcs(self): # type: () -> bool - return True - - def accepts_prereleases(self): # type: () -> bool - return True diff --git a/poetry/poetry.py b/poetry/poetry.py index 157e2488cf2..4878f0a22aa 100644 --- a/poetry/poetry.py +++ b/poetry/poetry.py @@ -1,16 +1,17 @@ from __future__ import absolute_import from __future__ import unicode_literals +from poetry.core.packages import ProjectPackage +from poetry.core.poetry import Poetry as BasePoetry + from .__version__ import __version__ from .config.config import Config from .packages import Locker -from .packages import ProjectPackage from .repositories.pool import Pool from .utils._compat import Path -from .utils.toml_file import TomlFile -class Poetry: +class Poetry(BasePoetry): VERSION = __version__ @@ -22,25 +23,12 @@ def __init__( locker, # type: Locker config, # type: Config ): - self._file = TomlFile(file) - self._package = package - self._local_config = local_config + super(Poetry, self).__init__(file, local_config, package) + self._locker = locker self._config = config self._pool = Pool() - @property - def file(self): - return self._file - - @property - def package(self): # type: () -> ProjectPackage - return self._package - - @property - def local_config(self): # type: () -> dict - return self._local_config - @property def locker(self): # type: () -> Locker return self._locker diff --git a/poetry/masonry/publishing/__init__.py b/poetry/publishing/__init__.py similarity index 100% rename from poetry/masonry/publishing/__init__.py rename to poetry/publishing/__init__.py diff --git a/poetry/masonry/publishing/publisher.py b/poetry/publishing/publisher.py similarity index 71% rename from poetry/masonry/publishing/publisher.py rename to poetry/publishing/publisher.py index 3ff39a7c840..d30a9a47119 100644 --- a/poetry/masonry/publishing/publisher.py +++ b/poetry/publishing/publisher.py @@ -1,5 +1,8 @@ import logging +from typing import Optional + +from poetry.utils._compat import Path from poetry.utils.helpers import get_cert from poetry.utils.helpers import get_client_cert from poetry.utils.password_manager import PasswordManager @@ -26,39 +29,26 @@ def __init__(self, poetry, io): def files(self): return self._uploader.files - def publish(self, repository_name, username, password, cert=None, client_cert=None): - if repository_name: - self._io.write_line( - "Publishing {} ({}) " - "to {}".format( - self._package.pretty_name, - self._package.pretty_version, - repository_name, - ) - ) - else: - self._io.write_line( - "Publishing {} ({}) " - "to PyPI".format( - self._package.pretty_name, self._package.pretty_version - ) - ) - + def publish( + self, + repository_name, + username, + password, + cert=None, + client_cert=None, + dry_run=False, + ): # type: (Optional[str], Optional[str], Optional[str], Optional[Path], Optional[Path], Optional[bool]) -> None if not repository_name: url = "https://upload.pypi.org/legacy/" repository_name = "pypi" else: # Retrieving config information - repository = self._poetry.config.get( - "repositories.{}".format(repository_name) - ) - if repository is None: + url = self._poetry.config.get("repositories.{}.url".format(repository_name)) + if url is None: raise RuntimeError( "Repository {} is not defined".format(repository_name) ) - url = repository["url"] - if not (username and password): # Check if we have a token first token = self._password_manager.get_pypi_token(repository_name) @@ -85,13 +75,24 @@ def publish(self, repository_name, username, password, cert=None, client_cert=No if username is None: username = self._io.ask("Username:") - if password is None: + # skip password input if no username is provided, assume unauthenticated + if username and password is None: password = self._io.ask_hidden("Password:") self._uploader.auth(username, password) - return self._uploader.upload( + self._io.write_line( + "Publishing {} ({}) " + "to {}".format( + self._package.pretty_name, + self._package.pretty_version, + {"pypi": "PyPI"}.get(repository_name, "PyPI"), + ) + ) + + self._uploader.upload( url, cert=cert or get_cert(self._poetry.config, repository_name), client_cert=resolved_client_cert, + dry_run=dry_run, ) diff --git a/poetry/masonry/publishing/uploader.py b/poetry/publishing/uploader.py similarity index 75% rename from poetry/masonry/publishing/uploader.py rename to poetry/publishing/uploader.py index 7e534cc30ae..b817676f956 100644 --- a/poetry/masonry/publishing/uploader.py +++ b/poetry/publishing/uploader.py @@ -1,13 +1,16 @@ import hashlib import io -import math +from typing import Any +from typing import Dict from typing import List from typing import Optional +from typing import Union import requests from requests import adapters +from requests.exceptions import ConnectionError from requests.exceptions import HTTPError from requests.packages.urllib3 import util from requests_toolbelt import user_agent @@ -15,25 +18,31 @@ from requests_toolbelt.multipart import MultipartEncoderMonitor from poetry.__version__ import __version__ +from poetry.core.masonry.metadata import Metadata +from poetry.core.masonry.utils.helpers import escape_name +from poetry.core.masonry.utils.helpers import escape_version from poetry.utils._compat import Path from poetry.utils.helpers import normalize_version from poetry.utils.patterns import wheel_file_re -from ..metadata import Metadata -from ..utils.helpers import escape_name -from ..utils.helpers import escape_version - _has_blake2 = hasattr(hashlib, "blake2b") class UploadError(Exception): - def __init__(self, error): # type: (HTTPError) -> None - super(UploadError, self).__init__( - "HTTP Error {}: {}".format( + def __init__(self, error): # type: (Union[ConnectionError, HTTPError]) -> None + if isinstance(error, HTTPError): + message = "HTTP Error {}: {}".format( error.response.status_code, error.response.reason ) - ) + elif isinstance(error, ConnectionError): + message = ( + "Connection Error: We were unable to connect to the repository, " + "ensure the url is correct and can be reached." + ) + else: + message = str(error) + super(UploadError, self).__init__(message) class Uploader: @@ -60,7 +69,7 @@ def adapter(self): return adapters.HTTPAdapter(max_retries=retry) @property - def files(self): # type: () -> List[str] + def files(self): # type: () -> List[Path] dist = self._poetry.file.parent / "dist" version = normalize_version(self._package.version.text) @@ -81,7 +90,7 @@ def auth(self, username, password): self._username = username self._password = password - def make_session(self): + def make_session(self): # type: () -> requests.Session session = requests.session() if self.is_authenticated(): session.auth = (self._username, self._password) @@ -96,8 +105,8 @@ def is_authenticated(self): return self._username is not None and self._password is not None def upload( - self, url, cert=None, client_cert=None - ): # type: (str, Optional[Path], Optional[Path]) -> None + self, url, cert=None, client_cert=None, dry_run=False + ): # type: (str, Optional[Path], Optional[Path], bool) -> None session = self.make_session() if cert: @@ -107,11 +116,11 @@ def upload( session.cert = str(client_cert) try: - self._upload(session, url) + self._upload(session, url, dry_run) finally: session.close() - def post_data(self, file): + def post_data(self, file): # type: (Path) -> Dict[str, Any] meta = Metadata.from_package(self._package) file_type = self._get_type(file) @@ -189,9 +198,11 @@ def post_data(self, file): return data - def _upload(self, session, url): + def _upload( + self, session, url, dry_run=False + ): # type: (requests.Session, str, Optional[bool]) -> None try: - self._do_upload(session, url) + self._do_upload(session, url, dry_run) except HTTPError as e: if ( e.response.status_code == 400 @@ -204,15 +215,20 @@ def _upload(self, session, url): raise UploadError(e) - def _do_upload(self, session, url): + def _do_upload( + self, session, url, dry_run=False + ): # type: (requests.Session, str, Optional[bool]) -> None for file in self.files: # TODO: Check existence - resp = self._upload_file(session, url, file) + resp = self._upload_file(session, url, file, dry_run) - resp.raise_for_status() + if not dry_run: + resp.raise_for_status() - def _upload_file(self, session, url, file): + def _upload_file( + self, session, url, file, dry_run=False + ): # type: (requests.Session, str, Path, Optional[bool]) -> requests.Response data = self.post_data(file) data.update( { @@ -239,35 +255,39 @@ def _upload_file(self, session, url, file): bar.start() - resp = session.post( - url, - data=monitor, - allow_redirects=False, - headers={"Content-Type": monitor.content_type}, - ) + resp = None - if resp.ok: - bar.set_format( - " - Uploading {0} %percent%%".format( - file.name + try: + if not dry_run: + resp = session.post( + url, + data=monitor, + allow_redirects=False, + headers={"Content-Type": monitor.content_type}, ) - ) - bar.finish() - - self._io.write_line("") - else: + if dry_run or resp.ok: + bar.set_format( + " - Uploading {0} %percent%%".format( + file.name + ) + ) + bar.finish() + except (requests.ConnectionError, requests.HTTPError) as e: if self._io.output.supports_ansi(): self._io.overwrite( - " - Uploading {0} {1}%".format( - file.name, int(math.floor(bar._percent * 100)) + " - Uploading {0} {1}".format( + file.name, "FAILED" ) ) - + raise UploadError(e) + finally: self._io.write_line("") return resp - def _register(self, session, url): + def _register( + self, session, url + ): # type: (requests.Session, str) -> requests.Response """ Register a package to a repository. """ diff --git a/poetry/puzzle/dependencies.py b/poetry/puzzle/dependencies.py deleted file mode 100644 index 18292549a91..00000000000 --- a/poetry/puzzle/dependencies.py +++ /dev/null @@ -1,36 +0,0 @@ -class Dependencies: - """ - Proxy to package dependencies to only require them when needed. - """ - - def __init__(self, package, provider): - self._package = package - self._provider = provider - self._dependencies = None - - @property - def dependencies(self): - if self._dependencies is None: - self._dependencies = self._get_dependencies() - - return self._dependencies - - def _get_dependencies(self): - self._provider.debug("Getting dependencies for {}".format(self._package), 0) - dependencies = self._provider._dependencies_for(self._package) - - if dependencies is None: - dependencies = [] - - return dependencies - - def __len__(self): - return len(self.dependencies) - - def __iter__(self): - return self.dependencies.__iter__() - - def __add__(self, other): - return self.dependencies + other - - __radd__ = __add__ diff --git a/poetry/puzzle/exceptions.py b/poetry/puzzle/exceptions.py index 5fd8960c665..e2e0b0dcce7 100644 --- a/poetry/puzzle/exceptions.py +++ b/poetry/puzzle/exceptions.py @@ -1,12 +1,3 @@ -class CompatibilityError(Exception): - def __init__(self, *constraints): - self._constraints = list(constraints) - - @property - def constraints(self): - return self._constraints - - class SolverProblemError(Exception): def __init__(self, error): self._error = error @@ -16,3 +7,12 @@ def __init__(self, error): @property def error(self): return self._error + + +class OverrideNeeded(Exception): + def __init__(self, *overrides): + self._overrides = overrides + + @property + def overrides(self): + return self._overrides diff --git a/poetry/puzzle/provider.py b/poetry/puzzle/provider.py index 989a592912b..71266538330 100644 --- a/poetry/puzzle/provider.py +++ b/poetry/puzzle/provider.py @@ -1,4 +1,3 @@ -import glob import logging import os import re @@ -10,43 +9,33 @@ from typing import List from typing import Optional -import pkginfo - from clikit.ui.components import ProgressIndicator -from poetry.factory import Factory +from poetry.core.packages import Dependency +from poetry.core.packages import DirectoryDependency +from poetry.core.packages import FileDependency +from poetry.core.packages import Package +from poetry.core.packages import URLDependency +from poetry.core.packages import VCSDependency +from poetry.core.packages.utils.utils import get_python_constraint_from_marker +from poetry.core.vcs.git import Git +from poetry.core.version.markers import MarkerUnion +from poetry.inspection.info import PackageInfo +from poetry.inspection.info import PackageInfoError from poetry.mixology.incompatibility import Incompatibility from poetry.mixology.incompatibility_cause import DependencyCause from poetry.mixology.incompatibility_cause import PythonCause from poetry.mixology.term import Term -from poetry.packages import Dependency from poetry.packages import DependencyPackage -from poetry.packages import DirectoryDependency -from poetry.packages import FileDependency -from poetry.packages import Package -from poetry.packages import PackageCollection -from poetry.packages import URLDependency -from poetry.packages import VCSDependency -from poetry.packages import dependency_from_pep_508 -from poetry.packages.utils.utils import get_python_constraint_from_marker +from poetry.packages.package_collection import PackageCollection +from poetry.puzzle.exceptions import OverrideNeeded from poetry.repositories import Pool -from poetry.utils._compat import PY35 from poetry.utils._compat import OrderedDict from poetry.utils._compat import Path from poetry.utils._compat import urlparse -from poetry.utils.env import EnvCommandError -from poetry.utils.env import EnvManager -from poetry.utils.env import VirtualEnv -from poetry.utils.helpers import parse_requires +from poetry.utils.helpers import download_file from poetry.utils.helpers import safe_rmtree from poetry.utils.helpers import temporary_directory -from poetry.utils.inspector import Inspector -from poetry.utils.setup_reader import SetupReader -from poetry.utils.toml_file import TomlFile -from poetry.vcs.git import Git -from poetry.version.markers import MarkerUnion - -from .exceptions import CompatibilityError logger = logging.getLogger(__name__) @@ -67,11 +56,11 @@ def __init__(self, package, pool, io): # type: (Package, Pool, Any) -> None self._package = package self._pool = pool self._io = io - self._inspector = Inspector() self._python_constraint = package.python_constraint self._search_for = {} self._is_debugging = self._io.is_debug() or self._io.is_very_verbose() self._in_progress = False + self._overrides = {} @property def pool(self): # type: () -> Pool @@ -88,6 +77,9 @@ def name_for_locking_dependency_source(self): # type: () -> str def is_debugging(self): return self._is_debugging + def set_overrides(self, overrides): + self._overrides = overrides + def name_for(self, dependency): # type: (Dependency) -> str """ Returns the name for the given dependency. @@ -240,31 +232,18 @@ def search_for_file(self, dependency): # type: (FileDependency) -> List[Package @classmethod def get_package_from_file(cls, file_path): # type: (Path) -> Package - info = Inspector().inspect(file_path) - if not info["name"]: + try: + package = PackageInfo.from_path(path=file_path).to_package( + root_dir=file_path + ) + except PackageInfoError: raise RuntimeError( - "Unable to determine the package name of {}".format(file_path) + "Unable to determine package info from path: {}".format(file_path) ) - package = Package(info["name"], info["version"]) package.source_type = "file" package.source_url = file_path.as_posix() - package.description = info["summary"] - for req in info["requires_dist"]: - dep = dependency_from_pep_508(req) - for extra in dep.in_extras: - if extra not in package.extras: - package.extras[extra] = [] - - package.extras[extra].append(dep) - - if not dep.is_optional(): - package.requires.append(dep) - - if info["requires_python"]: - package.python_versions = info["requires_python"] - return package def search_for_directory( @@ -293,136 +272,9 @@ def search_for_directory( def get_package_from_directory( cls, directory, name=None ): # type: (Path, Optional[str]) -> Package - supports_poetry = False - pyproject = directory.joinpath("pyproject.toml") - if pyproject.exists(): - pyproject = TomlFile(pyproject) - pyproject_content = pyproject.read() - supports_poetry = ( - "tool" in pyproject_content and "poetry" in pyproject_content["tool"] - ) - - if supports_poetry: - poetry = Factory().create_poetry(directory) - - pkg = poetry.package - package = Package(pkg.name, pkg.version) - - for dep in pkg.requires: - if not dep.is_optional(): - package.requires.append(dep) - - for extra, deps in pkg.extras.items(): - if extra not in package.extras: - package.extras[extra] = [] - - for dep in deps: - package.extras[extra].append(dep) - - package.python_versions = pkg.python_versions - else: - # Execute egg_info - current_dir = os.getcwd() - os.chdir(str(directory)) - - try: - with temporary_directory() as tmp_dir: - EnvManager.build_venv(tmp_dir) - venv = VirtualEnv(Path(tmp_dir), Path(tmp_dir)) - venv.run("python", "setup.py", "egg_info") - except EnvCommandError: - result = SetupReader.read_from_directory(directory) - if not result["name"]: - # The name could not be determined - # We use the dependency name - result["name"] = name - - if not result["version"]: - # The version could not be determined - # so we raise an error since it is mandatory - raise RuntimeError( - "Unable to retrieve the package version for {}".format( - directory - ) - ) - - package_name = result["name"] - package_version = result["version"] - python_requires = result["python_requires"] - if python_requires is None: - python_requires = "*" - - package_summary = "" - - requires = "" - for dep in result["install_requires"]: - requires += dep + "\n" - - if result["extras_require"]: - requires += "\n" - - for extra_name, deps in result["extras_require"].items(): - requires += "[{}]\n".format(extra_name) - - for dep in deps: - requires += dep + "\n" - - requires += "\n" - - reqs = parse_requires(requires) - else: - os.chdir(current_dir) - # Sometimes pathlib will fail on recursive - # symbolic links, so we need to workaround it - # and use the glob module instead. - # Note that this does not happen with pathlib2 - # so it's safe to use it for Python < 3.4. - if PY35: - egg_info = next( - Path(p) - for p in glob.glob( - os.path.join(str(directory), "**", "*.egg-info"), - recursive=True, - ) - ) - else: - egg_info = next(directory.glob("**/*.egg-info")) - - meta = pkginfo.UnpackedSDist(str(egg_info)) - package_name = meta.name - package_version = meta.version - package_summary = meta.summary - python_requires = meta.requires_python - - if meta.requires_dist: - reqs = list(meta.requires_dist) - else: - reqs = [] - requires = egg_info / "requires.txt" - if requires.exists(): - with requires.open(encoding="utf-8") as f: - reqs = parse_requires(f.read()) - finally: - os.chdir(current_dir) - - package = Package(package_name, package_version) - package.description = package_summary - - for req in reqs: - dep = dependency_from_pep_508(req) - if dep.in_extras: - for extra in dep.in_extras: - if extra not in package.extras: - package.extras[extra] = [] - - package.extras[extra].append(dep) - - if not dep.is_optional(): - package.requires.append(dep) - - if python_requires: - package.python_versions = python_requires - + package = PackageInfo.from_directory( + path=directory, allow_build=True + ).to_package(root_dir=directory) if name and name != package.name: # For now, the dependency's name must match the actual package's name raise RuntimeError( @@ -461,7 +313,7 @@ def get_package_from_url(cls, url): # type: (str) -> Package with temporary_directory() as temp_dir: temp_dir = Path(temp_dir) file_name = os.path.basename(urlparse.urlparse(url).path) - Inspector().download(url, temp_dir / file_name) + download_file(url, temp_dir / file_name) package = cls.get_package_from_file(temp_dir / file_name) @@ -514,13 +366,28 @@ def incompatibilities_for( ) ] - dependencies = [ + _dependencies = [ dep for dep in dependencies if dep.name not in self.UNSAFE_PACKAGES and self._package.python_constraint.allows_any(dep.python_constraint) ] + overrides = self._overrides.get(package, {}) + dependencies = [] + overridden = [] + for dep in _dependencies: + if dep.name in overrides: + if dep.name in overridden: + continue + + dependencies.append(overrides[dep.name]) + overridden.append(dep.name) + + continue + + dependencies.append(dep) + return [ Incompatibility( [Term(package.to_dependency(), True), Term(dep, False)], @@ -554,12 +421,28 @@ def complete_package( else: requires = package.requires - dependencies = [ + _dependencies = [ r for r in requires if self._package.python_constraint.allows_any(r.python_constraint) + and r.name not in self.UNSAFE_PACKAGES ] + overrides = self._overrides.get(package, {}) + dependencies = [] + overridden = [] + for dep in _dependencies: + if dep.name in overrides: + if dep.name in overridden: + continue + + dependencies.append(overrides[dep.name]) + overridden.append(dep.name) + + continue + + dependencies.append(dep) + # Searching for duplicate dependencies # # If the duplicate dependencies have the same constraint, @@ -651,26 +534,70 @@ def complete_package( continue # At this point, we raise an exception that will - # tell the solver to enter compatibility mode - # which means it will resolve for subsets - # Python constraints + # tell the solver to make new resolutions with specific overrides. # - # For instance, if our root package requires Python ~2.7 || ^3.6 - # And we have one dependency that requires Python <3.6 - # and the other Python >=3.6 than the solver will solve - # dependencies for Python >=2.7,<2.8 || >=3.4,<3.6 - # and Python >=3.6,<4.0 - python_constraints = [] + # For instance, if the foo (1.2.3) package has the following dependencies: + # - bar (>=2.0) ; python_version >= "3.6" + # - bar (<2.0) ; python_version < "3.6" + # + # then the solver will need to make two new resolutions + # with the following overrides: + # - {=2.0)>} + # - {} + markers = [] for constraint, _deps in by_constraint.items(): - python_constraints.append(_deps[0].python_versions) + markers.append(_deps[0].marker) - _deps = [str(_dep[0]) for _dep in by_constraint.values()] + _deps = [_dep[0] for _dep in by_constraint.values()] self.debug( "Different requirements found for {}.".format( - ", ".join(_deps[:-1]) + " and " + _deps[-1] + ", ".join( + "{} ({}) with markers {}".format( + d.name, + d.pretty_constraint, + d.marker if not d.marker.is_any() else "*", + ) + for d in _deps[:-1] + ) + + " and " + + "{} ({}) with markers {}".format( + _deps[-1].name, + _deps[-1].pretty_constraint, + _deps[-1].marker if not _deps[-1].marker.is_any() else "*", + ) ) ) - raise CompatibilityError(*python_constraints) + + # We need to check if one of the duplicate dependencies + # has no markers. If there is one, we need to change its + # environment markers to the inverse of the union of the + # other dependencies markers. + # For instance, if we have the following dependencies: + # - ipython + # - ipython (1.2.4) ; implementation_name == "pypy" + # + # the marker for `ipython` will become `implementation_name != "pypy"`. + any_markers_dependencies = [d for d in _deps if d.marker.is_any()] + other_markers_dependencies = [d for d in _deps if not d.marker.is_any()] + + if any_markers_dependencies: + marker = other_markers_dependencies[0].marker + for other_dep in other_markers_dependencies[1:]: + marker = marker.union(other_dep.marker) + + for i, d in enumerate(_deps): + if d.marker.is_any(): + _deps[i].marker = marker.invert() + + overrides = [] + for _dep in _deps: + current_overrides = self._overrides.copy() + package_overrides = current_overrides.get(package, {}) + package_overrides.update({_dep.name: _dep}) + current_overrides.update({package: package_overrides}) + overrides.append(current_overrides) + + raise OverrideNeeded(*overrides) # Modifying dependencies as needed clean_dependencies = [] @@ -724,38 +651,38 @@ def debug(self, message, depth=0): m2 = re.match(r"(.+?) \((.+?)\)", m.group(1)) if m2: name = m2.group(1) - version = " ({})".format(m2.group(2)) + version = " ({})".format(m2.group(2)) else: name = m.group(1) version = "" message = ( "fact: {}{} " - "depends on {} ({})".format( + "depends on {} ({})".format( name, version, m.group(2), m.group(3) ) ) elif " is " in message: message = re.sub( "fact: (.+) is (.+)", - "fact: \\1 is \\2", + "fact: \\1 is \\2", message, ) else: message = re.sub( - r"(?<=: )(.+?) \((.+?)\)", "\\1 (\\2)", message + r"(?<=: )(.+?) \((.+?)\)", "\\1 (\\2)", message ) message = "fact: {}".format(message.split("fact: ")[1]) elif message.startswith("selecting "): message = re.sub( r"selecting (.+?) \((.+?)\)", - "selecting \\1 (\\2)", + "selecting \\1 (\\2)", message, ) elif message.startswith("derived:"): m = re.match(r"derived: (.+?) \((.+?)\)$", message) if m: - message = "derived: {} ({})".format( + message = "derived: {} ({})".format( m.group(1), m.group(2) ) else: @@ -768,14 +695,14 @@ def debug(self, message, depth=0): m2 = re.match(r"(.+?) \((.+?)\)", m.group(1)) if m2: name = m2.group(1) - version = " ({})".format(m2.group(2)) + version = " ({})".format(m2.group(2)) else: name = m.group(1) version = "" message = ( "conflict: {}{} " - "depends on {} ({})".format( + "depends on {} ({})".format( name, version, m.group(2), m.group(3) ) ) @@ -791,7 +718,7 @@ def debug(self, message, depth=0): debug_info = ( "\n".join( [ - "{}: {}".format(str(depth).rjust(4), s) + "{}: {}".format(str(depth).rjust(4), s) for s in debug_info.split("\n") ] ) @@ -806,9 +733,7 @@ def progress(self): self._io.write_line("Resolving dependencies...") yield else: - indicator = Indicator( - self._io, "{message} ({elapsed:2s})" - ) + indicator = Indicator(self._io, "{message} ({elapsed:2s})") with indicator.auto( "Resolving dependencies...", diff --git a/poetry/puzzle/solver.py b/poetry/puzzle/solver.py index aff19ca6813..36b2b7e04e7 100644 --- a/poetry/puzzle/solver.py +++ b/poetry/puzzle/solver.py @@ -4,14 +4,13 @@ from typing import Dict from typing import List +from poetry.core.packages import Package +from poetry.core.version.markers import AnyMarker from poetry.mixology import resolve_version from poetry.mixology.failure import SolveFailure from poetry.packages import DependencyPackage -from poetry.packages import Package -from poetry.semver import parse_constraint -from poetry.version.markers import AnyMarker -from .exceptions import CompatibilityError +from .exceptions import OverrideNeeded from .exceptions import SolverProblemError from .operations import Install from .operations import Uninstall @@ -28,7 +27,7 @@ def __init__(self, package, pool, installed, locked, io): self._locked = locked self._io = io self._provider = Provider(self._package, self._pool, self._io) - self._branches = [] + self._overrides = [] def solve(self, use_latest=None): # type: (...) -> List[Operation] with self._provider.progress(): @@ -36,15 +35,15 @@ def solve(self, use_latest=None): # type: (...) -> List[Operation] packages, depths = self._solve(use_latest=use_latest) end = time.time() - if len(self._branches) > 1: + if len(self._overrides) > 1: self._provider.debug( - "Complete version solving took {:.3f} seconds for {} branches".format( - end - start, len(self._branches[1:]) + "Complete version solving took {:.3f} seconds with {} overrides".format( + end - start, len(self._overrides) ) ) self._provider.debug( - "Resolved for branches: {}".format( - ", ".join("({})".format(b) for b in self._branches[1:]) + "Resolved with overrides: {}".format( + ", ".join("({})".format(b) for b in self._overrides) ) ) @@ -56,7 +55,7 @@ def solve(self, use_latest=None): # type: (...) -> List[Operation] installed = True if pkg.source_type == "git" and package.source_type == "git": - from poetry.vcs.git import Git + from poetry.core.vcs.git import Git # Trying to find the currently installed version pkg_source_url = Git.normalize_url(pkg.source_url) @@ -135,42 +134,40 @@ def solve(self, use_latest=None): # type: (...) -> List[Operation] ), ) - def solve_in_compatibility_mode(self, constraints, use_latest=None): + def solve_in_compatibility_mode(self, overrides, use_latest=None): locked = {} for package in self._locked.packages: locked[package.name] = DependencyPackage(package.to_dependency(), package) packages = [] depths = [] - for constraint in constraints: - constraint = parse_constraint(constraint) - intersection = constraint.intersect(self._package.python_constraint) - + for override in overrides: self._provider.debug( "Retrying dependency resolution " - "for Python ({}).".format(intersection) + "with the following overrides ({}).".format(override) ) - with self._package.with_python_versions(str(intersection)): - _packages, _depths = self._solve(use_latest=use_latest) - for index, package in enumerate(_packages): - if package not in packages: - packages.append(package) - depths.append(_depths[index]) - continue - else: - idx = packages.index(package) - pkg = packages[idx] - depths[idx] = max(depths[idx], _depths[index]) - pkg.marker = pkg.marker.union(package.marker) + self._provider.set_overrides(override) + _packages, _depths = self._solve(use_latest=use_latest) + for index, package in enumerate(_packages): + if package not in packages: + packages.append(package) + depths.append(_depths[index]) + continue + else: + idx = packages.index(package) + pkg = packages[idx] + depths[idx] = max(depths[idx], _depths[index]) + pkg.marker = pkg.marker.union(package.marker) - for dep in package.requires: - if dep not in pkg.requires: - pkg.requires.append(dep) + for dep in package.requires: + if dep not in pkg.requires: + pkg.requires.append(dep) return packages, depths def _solve(self, use_latest=None): - self._branches.append(self._package.python_versions) + if self._provider._overrides: + self._overrides.append(self._provider._overrides) locked = {} for package in self._locked.packages: @@ -182,10 +179,8 @@ def _solve(self, use_latest=None): ) packages = result.packages - except CompatibilityError as e: - return self.solve_in_compatibility_mode( - e.constraints, use_latest=use_latest - ) + except OverrideNeeded as e: + return self.solve_in_compatibility_mode(e.overrides, use_latest=use_latest) except SolveFailure as e: raise SolverProblemError(e) diff --git a/poetry/repositories/installed_repository.py b/poetry/repositories/installed_repository.py index 65d194b745d..74a6af5cce6 100644 --- a/poetry/repositories/installed_repository.py +++ b/poetry/repositories/installed_repository.py @@ -1,4 +1,4 @@ -from poetry.packages import Package +from poetry.core.packages import Package from poetry.utils._compat import Path from poetry.utils._compat import metadata from poetry.utils.env import Env @@ -6,6 +6,9 @@ from .repository import Repository +_VENDORS = Path(__file__).parent.parent.joinpath("_vendor") + + class InstalledRepository(Repository): @classmethod def load(cls, env): # type: (Env) -> InstalledRepository @@ -22,6 +25,7 @@ def load(cls, env): # type: (Env) -> InstalledRepository metadata.distributions(path=[entry]), key=lambda d: str(d._path), ): name = distribution.metadata["name"] + path = Path(str(distribution._path)) version = distribution.metadata["version"] package = Package(name, version, version) package.description = distribution.metadata.get("summary", "") @@ -29,11 +33,17 @@ def load(cls, env): # type: (Env) -> InstalledRepository if package.name in seen: continue + try: + path.relative_to(_VENDORS) + except ValueError: + pass + else: + continue + seen.add(package.name) repo.add_package(package) - path = Path(str(distribution._path)) is_standard_package = True try: path.relative_to(env.site_packages) @@ -50,7 +60,7 @@ def load(cls, env): # type: (Env) -> InstalledRepository try: path.relative_to(src_path) - from poetry.vcs.git import Git + from poetry.core.vcs.git import Git git = Git() revision = git.rev_parse("HEAD", src_path / package.name).strip() diff --git a/poetry/repositories/legacy_repository.py b/poetry/repositories/legacy_repository.py index b228fc78764..7baf97ccf86 100644 --- a/poetry/repositories/legacy_repository.py +++ b/poetry/repositories/legacy_repository.py @@ -13,22 +13,18 @@ from cachecontrol.caches.file_cache import FileCache from cachy import CacheManager -import poetry.packages - +from poetry.core.packages import Package +from poetry.core.packages.utils.link import Link +from poetry.core.semver import Version +from poetry.core.semver import VersionConstraint +from poetry.core.semver import VersionRange +from poetry.core.semver import parse_constraint from poetry.locations import REPOSITORY_CACHE_DIR -from poetry.packages import Package -from poetry.packages import dependency_from_pep_508 -from poetry.packages.utils.link import Link -from poetry.semver import Version -from poetry.semver import VersionConstraint -from poetry.semver import VersionRange -from poetry.semver import parse_constraint from poetry.utils._compat import Path from poetry.utils.helpers import canonicalize_name -from poetry.utils.inspector import Inspector from poetry.utils.patterns import wheel_file_re -from poetry.version.markers import InvalidMarker +from ..inspection.info import PackageInfo from .auth import Auth from .exceptions import PackageNotFound from .pypi_repository import PyPiRepository @@ -173,7 +169,6 @@ def __init__( self._auth = auth self._client_cert = client_cert self._cert = cert - self._inspector = Inspector() self._cache_dir = REPOSITORY_CACHE_DIR / name self._cache = CacheManager( { @@ -220,8 +215,8 @@ def authenticated_url(self): # type: () -> str return "{scheme}://{username}:{password}@{netloc}{path}".format( scheme=parsed.scheme, - username=quote(self._auth.auth.username), - password=quote(self._auth.auth.password), + username=quote(self._auth.auth.username, safe=""), + password=quote(self._auth.auth.password, safe=""), netloc=parsed.netloc, path=parsed.path, ) @@ -283,9 +278,7 @@ def find_packages( return packages - def package( - self, name, version, extras=None - ): # type: (...) -> poetry.packages.Package + def package(self, name, version, extras=None): # type: (...) -> Package """ Retrieve the release information. @@ -298,69 +291,12 @@ def package( should be much faster. """ try: - index = self._packages.index( - poetry.packages.Package(name, version, version) - ) + index = self._packages.index(Package(name, version, version)) return self._packages[index] except ValueError: - if extras is None: - extras = [] - - release_info = self.get_release_info(name, version) - - package = poetry.packages.Package(name, version, version) - if release_info["requires_python"]: - package.python_versions = release_info["requires_python"] - + package = super(LegacyRepository, self).package(name, version, extras) package.source_url = self._url - package.source_reference = self.name - - requires_dist = release_info["requires_dist"] or [] - for req in requires_dist: - try: - dependency = dependency_from_pep_508(req) - except InvalidMarker: - # Invalid marker - # We strip the markers hoping for the best - req = req.split(";")[0] - - dependency = dependency_from_pep_508(req) - except ValueError: - # Likely unable to parse constraint so we skip it - self._log( - "Invalid constraint ({}) found in {}-{} dependencies, " - "skipping".format(req, package.name, package.version), - level="debug", - ) - continue - - if dependency.in_extras: - for extra in dependency.in_extras: - if extra not in package.extras: - package.extras[extra] = [] - - package.extras[extra].append(dependency) - - if not dependency.is_optional(): - package.requires.append(dependency) - - # Adding description - package.description = release_info.get("summary", "") - - # Adding hashes information - package.files = release_info["files"] - - # Activate extra dependencies - for extra in extras: - if extra in package.extras: - for dep in package.extras[extra]: - dep.activate() - - package.requires += package.extras[extra] - - self._packages.append(package) - return package def _get_release_info(self, name, version): # type: (str, str) -> dict @@ -368,15 +304,16 @@ def _get_release_info(self, name, version): # type: (str, str) -> dict if page is None: raise PackageNotFound('No package named "{}"'.format(name)) - data = { - "name": name, - "version": version, - "summary": "", - "requires_dist": [], - "requires_python": None, - "files": [], - "_cache_version": str(self.CACHE_VERSION), - } + data = PackageInfo( + name=name, + version=version, + summary="", + platform=None, + requires_dist=[], + requires_python=None, + files=[], + cache_version=str(self.CACHE_VERSION), + ) links = list(page.links_for_version(Version.parse(version))) if not links: @@ -400,26 +337,19 @@ def _get_release_info(self, name, version): # type: (str, str) -> dict h = link.hash_name + ":" + link.hash files.append({"file": link.filename, "hash": h}) - data["files"] = files + data.files = files info = self._get_info_from_urls(urls) - data["summary"] = info["summary"] - data["requires_dist"] = info["requires_dist"] - data["requires_python"] = info["requires_python"] - - return data + data.summary = info.summary + data.requires_dist = info.requires_dist + data.requires_python = info.requires_python - def _download(self, url, dest): # type: (str, str) -> None - r = self._session.get(url, stream=True) - with open(dest, "wb") as f: - for chunk in r.iter_content(chunk_size=1024): - if chunk: - f.write(chunk) + return data.asdict() def _get(self, endpoint): # type: (str) -> Union[Page, None] url = self._url + endpoint - response = self._session.get(url) + response = self.session.get(url) if response.status_code == 404: return diff --git a/poetry/repositories/pypi_repository.py b/poetry/repositories/pypi_repository.py index 9410f124299..e53a2af555e 100644 --- a/poetry/repositories/pypi_repository.py +++ b/poetry/repositories/pypi_repository.py @@ -6,33 +6,32 @@ from typing import List from typing import Union +import requests + from cachecontrol import CacheControl from cachecontrol.caches.file_cache import FileCache from cachecontrol.controller import logger as cache_control_logger from cachy import CacheManager from html5lib.html5parser import parse -from requests import get -from requests import session -from requests.exceptions import TooManyRedirects +from poetry.core.packages import Package +from poetry.core.packages import dependency_from_pep_508 +from poetry.core.packages.utils.link import Link +from poetry.core.semver import VersionConstraint +from poetry.core.semver import VersionRange +from poetry.core.semver import parse_constraint +from poetry.core.semver.exceptions import ParseVersionError +from poetry.core.version.markers import parse_marker from poetry.locations import REPOSITORY_CACHE_DIR -from poetry.packages import Package -from poetry.packages import dependency_from_pep_508 -from poetry.packages.utils.link import Link -from poetry.semver import VersionConstraint -from poetry.semver import VersionRange -from poetry.semver import parse_constraint -from poetry.semver.exceptions import ParseVersionError from poetry.utils._compat import Path from poetry.utils._compat import to_str +from poetry.utils.helpers import download_file from poetry.utils.helpers import temporary_directory -from poetry.utils.inspector import Inspector from poetry.utils.patterns import wheel_file_re -from poetry.version.markers import InvalidMarker -from poetry.version.markers import parse_marker +from ..inspection.info import PackageInfo from .exceptions import PackageNotFound -from .repository import Repository +from .remote_repository import RemoteRepository try: @@ -46,12 +45,14 @@ logger = logging.getLogger(__name__) -class PyPiRepository(Repository): +class PyPiRepository(RemoteRepository): CACHE_VERSION = parse_constraint("1.0.0") def __init__(self, url="https://pypi.org/", disable_cache=False, fallback=True): - self._url = url + super(PyPiRepository, self).__init__(url.rstrip("/") + "/simple/") + + self._base_url = url self._disable_cache = disable_cache self._fallback = fallback @@ -68,20 +69,15 @@ def __init__(self, url="https://pypi.org/", disable_cache=False, fallback=True): ) self._cache_control_cache = FileCache(str(release_cache_dir / "_http")) - self._session = CacheControl(session(), cache=self._cache_control_cache) - self._inspector = Inspector() - - super(PyPiRepository, self).__init__() + self._session = CacheControl( + requests.session(), cache=self._cache_control_cache + ) self._name = "PyPI" @property - def url(self): # type: () -> str - return self._url - - @property - def authenticated_url(self): # type: () -> str - return self._url + def session(self): + return self._session def find_packages( self, @@ -162,69 +158,15 @@ def package( name, # type: str version, # type: str extras=None, # type: (Union[list, None]) - ): # type: (...) -> Union[Package, None] - if extras is None: - extras = [] - - release_info = self.get_release_info(name, version) - package = Package(name, version, version) - requires_dist = release_info["requires_dist"] or [] - for req in requires_dist: - try: - dependency = dependency_from_pep_508(req) - except InvalidMarker: - # Invalid marker - # We strip the markers hoping for the best - req = req.split(";")[0] - - dependency = dependency_from_pep_508(req) - except ValueError: - # Likely unable to parse constraint so we skip it - self._log( - "Invalid constraint ({}) found in {}-{} dependencies, " - "skipping".format(req, package.name, package.version), - level="debug", - ) - continue - - if dependency.in_extras: - for extra in dependency.in_extras: - if extra not in package.extras: - package.extras[extra] = [] - - package.extras[extra].append(dependency) - - if not dependency.is_optional(): - package.requires.append(dependency) - - # Adding description - package.description = release_info.get("summary", "") - - if release_info["requires_python"]: - package.python_versions = release_info["requires_python"] - - if release_info["platform"]: - package.platform = release_info["platform"] - - # Adding hashes information - package.files = release_info["files"] - - # Activate extra dependencies - for extra in extras: - if extra in package.extras: - for dep in package.extras[extra]: - dep.activate() - - package.requires += package.extras[extra] - - return package + ): # type: (...) -> Package + return self.get_release_info(name, version).to_package(name=name, extras=extras) def search(self, query): results = [] search = {"q": query} - response = session().get(self._url + "search", params=search) + response = requests.session().get(self._base_url + "search", params=search) content = parse(response.content, namespaceHTMLElements=False) for result in content.findall(".//*[@class='package-snippet']"): name = result.find("h3/*[@class='package-snippet__name']").text @@ -272,7 +214,7 @@ def _get_package_info(self, name): # type: (str) -> dict return data - def get_release_info(self, name, version): # type: (str, str) -> dict + def get_release_info(self, name, version): # type: (str, str) -> PackageInfo """ Return the release information given a package name and a version. @@ -280,7 +222,7 @@ def get_release_info(self, name, version): # type: (str, str) -> dict or retrieved from the remote server. """ if self._disable_cache: - return self._get_release_info(name, version) + return PackageInfo.load(self._get_release_info(name, version)) cached = self._cache.remember_forever( "{}:{}".format(name, version), lambda: self._get_release_info(name, version) @@ -297,7 +239,7 @@ def get_release_info(self, name, version): # type: (str, str) -> dict self._cache.forever("{}:{}".format(name, version), cached) - return cached + return PackageInfo.load(cached) def _get_release_info(self, name, version): # type: (str, str) -> dict self._log("Getting info for {} ({}) from PyPI".format(name, version), "debug") @@ -307,16 +249,17 @@ def _get_release_info(self, name, version): # type: (str, str) -> dict raise PackageNotFound("Package [{}] not found.".format(name)) info = json_data["info"] - data = { - "name": info["name"], - "version": info["version"], - "summary": info["summary"], - "platform": info["platform"], - "requires_dist": info["requires_dist"], - "requires_python": info["requires_python"], - "files": [], - "_cache_version": str(self.CACHE_VERSION), - } + + data = PackageInfo( + name=info["name"], + version=info["version"], + summary=info["summary"], + platform=info["platform"], + requires_dist=info["requires_dist"], + requires_python=info["requires_python"], + files=info.get("files", []), + cache_version=str(self.CACHE_VERSION), + ) try: version_info = json_data["releases"][version] @@ -324,14 +267,14 @@ def _get_release_info(self, name, version): # type: (str, str) -> dict version_info = [] for file_info in version_info: - data["files"].append( + data.files.append( { "file": file_info["filename"], "hash": "sha256:" + file_info["digests"]["sha256"], } ) - if self._fallback and data["requires_dist"] is None: + if self._fallback and data.requires_dist is None: self._log("No dependencies found, downloading archives", level="debug") # No dependencies set (along with other information) # This might be due to actually no dependencies @@ -348,25 +291,25 @@ def _get_release_info(self, name, version): # type: (str, str) -> dict urls[dist_type].append(url["url"]) if not urls: - return data + return data.asdict() info = self._get_info_from_urls(urls) - data["requires_dist"] = info["requires_dist"] + data.requires_dist = info.requires_dist - if not data["requires_python"]: - data["requires_python"] = info["requires_python"] + if not data.requires_python: + data.requires_python = info.requires_python - return data + return data.asdict() def _get(self, endpoint): # type: (str) -> Union[dict, None] try: - json_response = self._session.get(self._url + endpoint) - except TooManyRedirects: + json_response = self.session.get(self._base_url + endpoint) + except requests.exceptions.TooManyRedirects: # Cache control redirect loop. # We try to remove the cache and try again - self._cache_control_cache.delete(self._url + endpoint) - json_response = self._session.get(self._url + endpoint) + self._cache_control_cache.delete(self._base_url + endpoint) + json_response = self.session.get(self._base_url + endpoint) if json_response.status_code == 404: return None @@ -375,9 +318,7 @@ def _get(self, endpoint): # type: (str) -> Union[dict, None] return json_data - def _get_info_from_urls( - self, urls - ): # type: (Dict[str, List[str]]) -> Dict[str, Union[str, List, None]] + def _get_info_from_urls(self, urls): # type: (Dict[str, List[str]]) -> PackageInfo # Checking wheels first as they are more likely to hold # the necessary information if "bdist_wheel" in urls: @@ -412,24 +353,24 @@ def _get_info_from_urls( if universal_wheel is not None: return self._get_info_from_wheel(universal_wheel) - info = {} + info = None if universal_python2_wheel and universal_python3_wheel: info = self._get_info_from_wheel(universal_python2_wheel) py3_info = self._get_info_from_wheel(universal_python3_wheel) - if py3_info["requires_dist"]: - if not info["requires_dist"]: - info["requires_dist"] = py3_info["requires_dist"] + if py3_info.requires_dist: + if not info.requires_dist: + info.requires_dist = py3_info.requires_dist return info py2_requires_dist = set( dependency_from_pep_508(r).to_pep_508() - for r in info["requires_dist"] + for r in info.requires_dist ) py3_requires_dist = set( dependency_from_pep_508(r).to_pep_508() - for r in py3_info["requires_dist"] + for r in py3_info.requires_dist ) base_requires_dist = py2_requires_dist & py3_requires_dist py2_only_requires_dist = py2_requires_dist - py3_requires_dist @@ -451,7 +392,7 @@ def _get_info_from_urls( ) requires_dist.append(dep.to_pep_508()) - info["requires_dist"] = sorted(list(set(requires_dist))) + info.requires_dist = sorted(list(set(requires_dist))) if info: return info @@ -469,9 +410,7 @@ def _get_info_from_urls( return self._get_info_from_sdist(urls["sdist"][0]) - def _get_info_from_wheel( - self, url - ): # type: (str) -> Dict[str, Union[str, List, None]] + def _get_info_from_wheel(self, url): # type: (str) -> PackageInfo self._log( "Downloading wheel: {}".format(urlparse.urlparse(url).path.rsplit("/")[-1]), level="debug", @@ -483,11 +422,9 @@ def _get_info_from_wheel( filepath = Path(temp_dir) / filename self._download(url, str(filepath)) - return self._inspector.inspect_wheel(filepath) + return PackageInfo.from_wheel(filepath) - def _get_info_from_sdist( - self, url - ): # type: (str) -> Dict[str, Union[str, List, None]] + def _get_info_from_sdist(self, url): # type: (str) -> PackageInfo self._log( "Downloading sdist: {}".format(urlparse.urlparse(url).path.rsplit("/")[-1]), level="debug", @@ -499,16 +436,10 @@ def _get_info_from_sdist( filepath = Path(temp_dir) / filename self._download(url, str(filepath)) - return self._inspector.inspect_sdist(filepath) + return PackageInfo.from_sdist(filepath) def _download(self, url, dest): # type: (str, str) -> None - r = get(url, stream=True) - r.raise_for_status() - - with open(dest, "wb") as f: - for chunk in r.iter_content(chunk_size=1024): - if chunk: - f.write(chunk) + return download_file(url, dest, session=self.session) def _log(self, msg, level="info"): - getattr(logger, level)("{}: {}".format(self._name, msg)) + getattr(logger, level)("{}: {}".format(self._name, msg)) diff --git a/poetry/repositories/remote_repository.py b/poetry/repositories/remote_repository.py new file mode 100644 index 00000000000..7717740d87c --- /dev/null +++ b/poetry/repositories/remote_repository.py @@ -0,0 +1,16 @@ +from .repository import Repository + + +class RemoteRepository(Repository): + def __init__(self, url): # type: (str) -> None + self._url = url + + super(RemoteRepository, self).__init__() + + @property + def url(self): # type: () -> str + return self._url + + @property + def authenticated_url(self): # type: () -> str + return self._url diff --git a/poetry/repositories/repository.py b/poetry/repositories/repository.py index 0432cfa1ed5..00b43207d62 100644 --- a/poetry/repositories/repository.py +++ b/poetry/repositories/repository.py @@ -1,6 +1,6 @@ -from poetry.semver import VersionConstraint -from poetry.semver import VersionRange -from poetry.semver import parse_constraint +from poetry.core.semver import VersionConstraint +from poetry.core.semver import VersionRange +from poetry.core.semver import parse_constraint from .base_repository import BaseRepository diff --git a/poetry/semver/__init__.py b/poetry/semver/__init__.py deleted file mode 100644 index 725b7d43f58..00000000000 --- a/poetry/semver/__init__.py +++ /dev/null @@ -1,162 +0,0 @@ -import re - -from .empty_constraint import EmptyConstraint -from .patterns import BASIC_CONSTRAINT -from .patterns import CARET_CONSTRAINT -from .patterns import TILDE_CONSTRAINT -from .patterns import TILDE_PEP440_CONSTRAINT -from .patterns import X_CONSTRAINT -from .version import Version -from .version_constraint import VersionConstraint -from .version_range import VersionRange -from .version_union import VersionUnion - - -def parse_constraint(constraints): # type: (str) -> VersionConstraint - if constraints == "*": - return VersionRange() - - or_constraints = re.split(r"\s*\|\|?\s*", constraints.strip()) - or_groups = [] - for constraints in or_constraints: - and_constraints = re.split( - "(?< ,]) *(? 1: - for constraint in and_constraints: - constraint_objects.append(parse_single_constraint(constraint)) - else: - constraint_objects.append(parse_single_constraint(and_constraints[0])) - - if len(constraint_objects) == 1: - constraint = constraint_objects[0] - else: - constraint = constraint_objects[0] - for next_constraint in constraint_objects[1:]: - constraint = constraint.intersect(next_constraint) - - or_groups.append(constraint) - - if len(or_groups) == 1: - return or_groups[0] - else: - return VersionUnion.of(*or_groups) - - -def parse_single_constraint(constraint): # type: (str) -> VersionConstraint - m = re.match(r"(?i)^v?[xX*](\.[xX*])*$", constraint) - if m: - return VersionRange() - - # Tilde range - m = TILDE_CONSTRAINT.match(constraint) - if m: - version = Version.parse(m.group(1)) - - high = version.stable.next_minor - if len(m.group(1).split(".")) == 1: - high = version.stable.next_major - - return VersionRange( - version, high, include_min=True, always_include_max_prerelease=True - ) - - # PEP 440 Tilde range (~=) - m = TILDE_PEP440_CONSTRAINT.match(constraint) - if m: - precision = 1 - if m.group(3): - precision += 1 - - if m.group(4): - precision += 1 - - version = Version.parse(m.group(1)) - - if precision == 2: - high = version.stable.next_major - else: - high = version.stable.next_minor - - return VersionRange( - version, high, include_min=True, always_include_max_prerelease=True - ) - - # Caret range - m = CARET_CONSTRAINT.match(constraint) - if m: - version = Version.parse(m.group(1)) - - return VersionRange( - version, - version.next_breaking, - include_min=True, - always_include_max_prerelease=True, - ) - - # X Range - m = X_CONSTRAINT.match(constraint) - if m: - op = m.group(1) - major = int(m.group(2)) - minor = m.group(3) - - if minor is not None: - version = Version(major, int(minor), 0) - - result = VersionRange( - version, - version.next_minor, - include_min=True, - always_include_max_prerelease=True, - ) - else: - if major == 0: - result = VersionRange(max=Version(1, 0, 0)) - else: - version = Version(major, 0, 0) - - result = VersionRange( - version, - version.next_major, - include_min=True, - always_include_max_prerelease=True, - ) - - if op == "!=": - result = VersionRange().difference(result) - - return result - - # Basic comparator - m = BASIC_CONSTRAINT.match(constraint) - if m: - op = m.group(1) - version = m.group(2) - - if version == "dev": - version = "0.0-dev" - - try: - version = Version.parse(version) - except ValueError: - raise ValueError( - "Could not parse version constraint: {}".format(constraint) - ) - - if op == "<": - return VersionRange(max=version) - elif op == "<=": - return VersionRange(max=version, include_max=True) - elif op == ">": - return VersionRange(min=version) - elif op == ">=": - return VersionRange(min=version, include_min=True) - elif op == "!=": - return VersionUnion(VersionRange(max=version), VersionRange(min=version)) - else: - return version - - raise ValueError("Could not parse version constraint: {}".format(constraint)) diff --git a/poetry/semver/empty_constraint.py b/poetry/semver/empty_constraint.py deleted file mode 100644 index 3c5e27e1027..00000000000 --- a/poetry/semver/empty_constraint.py +++ /dev/null @@ -1,30 +0,0 @@ -from .version_constraint import VersionConstraint - - -class EmptyConstraint(VersionConstraint): - def is_empty(self): - return True - - def is_any(self): - return False - - def allows(self, version): - return False - - def allows_all(self, other): - return other.is_empty() - - def allows_any(self, other): - return False - - def intersect(self, other): - return self - - def union(self, other): - return other - - def difference(self, other): - return self - - def __str__(self): - return "" diff --git a/poetry/semver/exceptions.py b/poetry/semver/exceptions.py deleted file mode 100644 index f0eab0db7ea..00000000000 --- a/poetry/semver/exceptions.py +++ /dev/null @@ -1,2 +0,0 @@ -class ParseVersionError(ValueError): - pass diff --git a/poetry/semver/patterns.py b/poetry/semver/patterns.py deleted file mode 100644 index 63cce5487d5..00000000000 --- a/poetry/semver/patterns.py +++ /dev/null @@ -1,22 +0,0 @@ -import re - - -MODIFIERS = ( - "[._-]?" - r"((?!post)(?:beta|b|c|pre|RC|alpha|a|patch|pl|p|dev)(?:(?:[.-]?\d+)*)?)?" - r"([+-]?([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?" -) - -_COMPLETE_VERSION = r"v?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:\.(\d+))?{}(?:\+[^\s]+)?".format( - MODIFIERS -) - -COMPLETE_VERSION = re.compile("(?i)" + _COMPLETE_VERSION) - -CARET_CONSTRAINT = re.compile(r"(?i)^\^({})$".format(_COMPLETE_VERSION)) -TILDE_CONSTRAINT = re.compile("(?i)^~(?!=)({})$".format(_COMPLETE_VERSION)) -TILDE_PEP440_CONSTRAINT = re.compile("(?i)^~=({})$".format(_COMPLETE_VERSION)) -X_CONSTRAINT = re.compile(r"^(!=|==)?\s*v?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:\.[xX*])+$") -BASIC_CONSTRAINT = re.compile( - r"(?i)^(<>|!=|>=?|<=?|==?)?\s*({}|dev)".format(_COMPLETE_VERSION) -) diff --git a/poetry/semver/version.py b/poetry/semver/version.py deleted file mode 100644 index 143dbd2e463..00000000000 --- a/poetry/semver/version.py +++ /dev/null @@ -1,467 +0,0 @@ -import re - -from typing import List -from typing import Optional -from typing import Union - -from .empty_constraint import EmptyConstraint -from .exceptions import ParseVersionError -from .patterns import COMPLETE_VERSION -from .version_constraint import VersionConstraint -from .version_range import VersionRange -from .version_union import VersionUnion - - -class Version(VersionRange): - """ - A parsed semantic version number. - """ - - def __init__( - self, - major, # type: int - minor=None, # type: Optional[int] - patch=None, # type: Optional[int] - rest=None, # type: Optional[int] - pre=None, # type: Optional[str] - build=None, # type: Optional[str] - text=None, # type: Optional[str] - precision=None, # type: Optional[int] - ): # type: (...) -> None - self._major = int(major) - self._precision = None - if precision is None: - self._precision = 1 - - if minor is None: - minor = 0 - else: - if self._precision is not None: - self._precision += 1 - - self._minor = int(minor) - - if patch is None: - patch = 0 - else: - if self._precision is not None: - self._precision += 1 - - if rest is None: - rest = 0 - else: - if self._precision is not None: - self._precision += 1 - - if precision is not None: - self._precision = precision - - self._patch = int(patch) - self._rest = int(rest) - - if text is None: - parts = [str(major)] - if self._precision >= 2 or minor != 0: - parts.append(str(minor)) - - if self._precision >= 3 or patch != 0: - parts.append(str(patch)) - - if self._precision >= 4 or rest != 0: - parts.append(str(rest)) - - text = ".".join(parts) - if pre: - text += "-{}".format(pre) - - if build: - text += "+{}".format(build) - - self._text = text - - pre = self._normalize_prerelease(pre) - - self._prerelease = [] - if pre is not None: - self._prerelease = self._split_parts(pre) - - build = self._normalize_build(build) - - self._build = [] - if build is not None: - if build.startswith(("-", "+")): - build = build[1:] - - self._build = self._split_parts(build) - - @property - def major(self): # type: () -> int - return self._major - - @property - def minor(self): # type: () -> int - return self._minor - - @property - def patch(self): # type: () -> int - return self._patch - - @property - def rest(self): # type: () -> int - return self._rest - - @property - def prerelease(self): # type: () -> List[str] - return self._prerelease - - @property - def build(self): # type: () -> List[str] - return self._build - - @property - def text(self): - return self._text - - @property - def precision(self): # type: () -> int - return self._precision - - @property - def stable(self): - if not self.is_prerelease(): - return self - - return self.next_patch - - @property - def next_major(self): # type: () -> Version - if self.is_prerelease() and self.minor == 0 and self.patch == 0: - return Version(self.major, self.minor, self.patch) - - return self._increment_major() - - @property - def next_minor(self): # type: () -> Version - if self.is_prerelease() and self.patch == 0: - return Version(self.major, self.minor, self.patch) - - return self._increment_minor() - - @property - def next_patch(self): # type: () -> Version - if self.is_prerelease(): - return Version(self.major, self.minor, self.patch) - - return self._increment_patch() - - @property - def next_breaking(self): # type: () -> Version - if self.major == 0: - if self.minor != 0: - return self._increment_minor() - - if self._precision == 1: - return self._increment_major() - elif self._precision == 2: - return self._increment_minor() - - return self._increment_patch() - - return self._increment_major() - - @property - def first_prerelease(self): # type: () -> Version - return Version.parse( - "{}.{}.{}-alpha.0".format(self.major, self.minor, self.patch) - ) - - @property - def min(self): - return self - - @property - def max(self): - return self - - @property - def full_max(self): - return self - - @property - def include_min(self): - return True - - @property - def include_max(self): - return True - - @classmethod - def parse(cls, text): # type: (str) -> Version - try: - match = COMPLETE_VERSION.match(text) - except TypeError: - match = None - - if match is None: - raise ParseVersionError('Unable to parse "{}".'.format(text)) - - text = text.rstrip(".") - - major = int(match.group(1)) - minor = int(match.group(2)) if match.group(2) else None - patch = int(match.group(3)) if match.group(3) else None - rest = int(match.group(4)) if match.group(4) else None - - pre = match.group(5) - build = match.group(6) - - if build: - build = build.lstrip("+") - - return Version(major, minor, patch, rest, pre, build, text) - - def is_any(self): - return False - - def is_empty(self): - return False - - def is_prerelease(self): # type: () -> bool - return len(self._prerelease) > 0 - - def allows(self, version): # type: (Version) -> bool - return self == version - - def allows_all(self, other): # type: (VersionConstraint) -> bool - return other.is_empty() or other == self - - def allows_any(self, other): # type: (VersionConstraint) -> bool - return other.allows(self) - - def intersect(self, other): # type: (VersionConstraint) -> VersionConstraint - if other.allows(self): - return self - - return EmptyConstraint() - - def union(self, other): # type: (VersionConstraint) -> VersionConstraint - from .version_range import VersionRange - - if other.allows(self): - return other - - if isinstance(other, VersionRange): - if other.min == self: - return VersionRange( - other.min, - other.max, - include_min=True, - include_max=other.include_max, - ) - - if other.max == self: - return VersionRange( - other.min, - other.max, - include_min=other.include_min, - include_max=True, - ) - - return VersionUnion.of(self, other) - - def difference(self, other): # type: (VersionConstraint) -> VersionConstraint - if other.allows(self): - return EmptyConstraint() - - return self - - def equals_without_prerelease(self, other): # type: (Version) -> bool - return ( - self.major == other.major - and self.minor == other.minor - and self.patch == other.patch - ) - - def _increment_major(self): # type: () -> Version - return Version(self.major + 1, 0, 0, precision=self._precision) - - def _increment_minor(self): # type: () -> Version - return Version(self.major, self.minor + 1, 0, precision=self._precision) - - def _increment_patch(self): # type: () -> Version - return Version( - self.major, self.minor, self.patch + 1, precision=self._precision - ) - - def _normalize_prerelease(self, pre): # type: (str) -> str - if not pre: - return - - m = re.match(r"(?i)^(a|alpha|b|beta|c|pre|rc|dev)[-.]?(\d+)?$", pre) - if not m: - return - - modifier = m.group(1) - number = m.group(2) - - if number is None: - number = 0 - - if modifier == "a": - modifier = "alpha" - elif modifier == "b": - modifier = "beta" - elif modifier in {"c", "pre"}: - modifier = "rc" - elif modifier == "dev": - modifier = "alpha" - - return "{}.{}".format(modifier, number) - - def _normalize_build(self, build): # type: (str) -> str - if not build: - return - - if build.startswith("post"): - build = build.lstrip("post") - - if not build: - return - - return build - - def _split_parts(self, text): # type: (str) -> List[Union[str, int]] - parts = text.split(".") - - for i, part in enumerate(parts): - try: - parts[i] = int(part) - except (TypeError, ValueError): - continue - - return parts - - def __lt__(self, other): - return self._cmp(other) < 0 - - def __le__(self, other): - return self._cmp(other) <= 0 - - def __gt__(self, other): - return self._cmp(other) > 0 - - def __ge__(self, other): - return self._cmp(other) >= 0 - - def _cmp(self, other): - if not isinstance(other, VersionConstraint): - return NotImplemented - - if not isinstance(other, Version): - return -other._cmp(self) - - if self.major != other.major: - return self._cmp_parts(self.major, other.major) - - if self.minor != other.minor: - return self._cmp_parts(self.minor, other.minor) - - if self.patch != other.patch: - return self._cmp_parts(self.patch, other.patch) - - if self.rest != other.rest: - return self._cmp_parts(self.rest, other.rest) - - # Pre-releases always come before no pre-release string. - if not self.is_prerelease() and other.is_prerelease(): - return 1 - - if not other.is_prerelease() and self.is_prerelease(): - return -1 - - comparison = self._cmp_lists(self.prerelease, other.prerelease) - if comparison != 0: - return comparison - - # Builds always come after no build string. - if not self.build and other.build: - return -1 - - if not other.build and self.build: - return 1 - - return self._cmp_lists(self.build, other.build) - - def _cmp_parts(self, a, b): - if a < b: - return -1 - elif a > b: - return 1 - - return 0 - - def _cmp_lists(self, a, b): # type: (List, List) -> int - for i in range(max(len(a), len(b))): - a_part = None - if i < len(a): - a_part = a[i] - - b_part = None - if i < len(b): - b_part = b[i] - - if a_part == b_part: - continue - - # Missing parts come after present ones. - if a_part is None: - return -1 - - if b_part is None: - return 1 - - if isinstance(a_part, int): - if isinstance(b_part, int): - return self._cmp_parts(a_part, b_part) - - return -1 - else: - if isinstance(b_part, int): - return 1 - - return self._cmp_parts(a_part, b_part) - - return 0 - - def __eq__(self, other): # type: (Version) -> bool - if not isinstance(other, Version): - return NotImplemented - - return ( - self._major == other.major - and self._minor == other.minor - and self._patch == other.patch - and self._rest == other.rest - and self._prerelease == other.prerelease - and self._build == other.build - ) - - def __ne__(self, other): - return not self == other - - def __str__(self): - return self._text - - def __repr__(self): - return "".format(str(self)) - - def __hash__(self): - return hash( - ( - self.major, - self.minor, - self.patch, - ".".join(str(p) for p in self.prerelease), - ".".join(str(p) for p in self.build), - ) - ) diff --git a/poetry/semver/version_constraint.py b/poetry/semver/version_constraint.py deleted file mode 100644 index 46733b68699..00000000000 --- a/poetry/semver/version_constraint.py +++ /dev/null @@ -1,24 +0,0 @@ -class VersionConstraint: - def is_empty(self): # type: () -> bool - raise NotImplementedError() - - def is_any(self): # type: () -> bool - raise NotImplementedError() - - def allows(self, version): # type: ("Version") -> bool - raise NotImplementedError() - - def allows_all(self, other): # type: (VersionConstraint) -> bool - raise NotImplementedError() - - def allows_any(self, other): # type: (VersionConstraint) -> bool - raise NotImplementedError() - - def intersect(self, other): # type: (VersionConstraint) -> VersionConstraint - raise NotImplementedError() - - def union(self, other): # type: (VersionConstraint) -> VersionConstraint - raise NotImplementedError() - - def difference(self, other): # type: (VersionConstraint) -> VersionConstraint - raise NotImplementedError() diff --git a/poetry/semver/version_range.py b/poetry/semver/version_range.py deleted file mode 100644 index cb9739ab6dd..00000000000 --- a/poetry/semver/version_range.py +++ /dev/null @@ -1,450 +0,0 @@ -from typing import List - -from .empty_constraint import EmptyConstraint -from .version_constraint import VersionConstraint -from .version_union import VersionUnion - - -class VersionRange(VersionConstraint): - def __init__( - self, - min=None, - max=None, - include_min=False, - include_max=False, - always_include_max_prerelease=False, - ): - full_max = max - if ( - always_include_max_prerelease - and not include_max - and not full_max.is_prerelease() - and not full_max.build - and ( - min is None - or not min.is_prerelease() - or not min.equals_without_prerelease(full_max) - ) - ): - full_max = full_max.first_prerelease - - self._min = min - self._max = max - self._full_max = full_max - self._include_min = include_min - self._include_max = include_max - - @property - def min(self): - return self._min - - @property - def max(self): - return self._max - - @property - def full_max(self): - return self._full_max - - @property - def include_min(self): - return self._include_min - - @property - def include_max(self): - return self._include_max - - def is_empty(self): - return False - - def is_any(self): - return self._min is None and self._max is None - - def allows(self, other): # type: ("Version") -> bool - if self._min is not None: - if other < self._min: - return False - - if not self._include_min and other == self._min: - return False - - if self._max is not None: - if other > self._max: - return False - - if not self._include_max and other == self._max: - return False - - return True - - def allows_all(self, other): # type: (VersionConstraint) -> bool - from .version import Version - - if other.is_empty(): - return True - - if isinstance(other, Version): - return self.allows(other) - - if isinstance(other, VersionUnion): - return all([self.allows_all(constraint) for constraint in other.ranges]) - - if isinstance(other, VersionRange): - return not other.allows_lower(self) and not other.allows_higher(self) - - raise ValueError("Unknown VersionConstraint type {}.".format(other)) - - def allows_any(self, other): # type: (VersionConstraint) -> bool - from .version import Version - - if other.is_empty(): - return False - - if isinstance(other, Version): - return self.allows(other) - - if isinstance(other, VersionUnion): - return any([self.allows_any(constraint) for constraint in other.ranges]) - - if isinstance(other, VersionRange): - return not other.is_strictly_lower(self) and not other.is_strictly_higher( - self - ) - - raise ValueError("Unknown VersionConstraint type {}.".format(other)) - - def intersect(self, other): # type: (VersionConstraint) -> VersionConstraint - from .version import Version - - if other.is_empty(): - return other - - if isinstance(other, VersionUnion): - return other.intersect(self) - - # A range and a Version just yields the version if it's in the range. - if isinstance(other, Version): - if self.allows(other): - return other - - return EmptyConstraint() - - if not isinstance(other, VersionRange): - raise ValueError("Unknown VersionConstraint type {}.".format(other)) - - if self.allows_lower(other): - if self.is_strictly_lower(other): - return EmptyConstraint() - - intersect_min = other.min - intersect_include_min = other.include_min - else: - if other.is_strictly_lower(self): - return EmptyConstraint() - - intersect_min = self._min - intersect_include_min = self._include_min - - if self.allows_higher(other): - intersect_max = other.max - intersect_include_max = other.include_max - else: - intersect_max = self._max - intersect_include_max = self._include_max - - if intersect_min is None and intersect_max is None: - return VersionRange() - - # If the range is just a single version. - if intersect_min == intersect_max: - # Because we already verified that the lower range isn't strictly - # lower, there must be some overlap. - assert intersect_include_min and intersect_include_max - - return intersect_min - - # If we got here, there is an actual range. - return VersionRange( - intersect_min, intersect_max, intersect_include_min, intersect_include_max - ) - - def union(self, other): # type: (VersionConstraint) -> VersionConstraint - from .version import Version - - if isinstance(other, Version): - if self.allows(other): - return self - - if other == self.min: - return VersionRange( - self.min, self.max, include_min=True, include_max=self.include_max - ) - - if other == self.max: - return VersionRange( - self.min, self.max, include_min=self.include_min, include_max=True - ) - - return VersionUnion.of(self, other) - - if isinstance(other, VersionRange): - # If the two ranges don't overlap, we won't be able to create a single - # VersionRange for both of them. - edges_touch = ( - self.max == other.min and (self.include_max or other.include_min) - ) or (self.min == other.max and (self.include_min or other.include_max)) - - if not edges_touch and not self.allows_any(other): - return VersionUnion.of(self, other) - - if self.allows_lower(other): - union_min = self.min - union_include_min = self.include_min - else: - union_min = other.min - union_include_min = other.include_min - - if self.allows_higher(other): - union_max = self.max - union_include_max = self.include_max - else: - union_max = other.max - union_include_max = other.include_max - - return VersionRange( - union_min, - union_max, - include_min=union_include_min, - include_max=union_include_max, - ) - - return VersionUnion.of(self, other) - - def difference(self, other): # type: (VersionConstraint) -> VersionConstraint - from .version import Version - - if other.is_empty(): - return self - - if isinstance(other, Version): - if not self.allows(other): - return self - - if other == self.min: - if not self.include_min: - return self - - return VersionRange(self.min, self.max, False, self.include_max) - - if other == self.max: - if not self.include_max: - return self - - return VersionRange(self.min, self.max, self.include_min, False) - - return VersionUnion.of( - VersionRange(self.min, other, self.include_min, False), - VersionRange(other, self.max, False, self.include_max), - ) - elif isinstance(other, VersionRange): - if not self.allows_any(other): - return self - - if not self.allows_lower(other): - before = None - elif self.min == other.min: - before = self.min - else: - before = VersionRange( - self.min, other.min, self.include_min, not other.include_min - ) - - if not self.allows_higher(other): - after = None - elif self.max == other.max: - after = self.max - else: - after = VersionRange( - other.max, self.max, not other.include_max, self.include_max - ) - - if before is None and after is None: - return EmptyConstraint() - - if before is None: - return after - - if after is None: - return before - - return VersionUnion.of(before, after) - elif isinstance(other, VersionUnion): - ranges = [] # type: List[VersionRange] - current = self - - for range in other.ranges: - # Skip any ranges that are strictly lower than [current]. - if range.is_strictly_lower(current): - continue - - # If we reach a range strictly higher than [current], no more ranges - # will be relevant so we can bail early. - if range.is_strictly_higher(current): - break - - difference = current.difference(range) - if difference.is_empty(): - return EmptyConstraint() - elif isinstance(difference, VersionUnion): - # If [range] split [current] in half, we only need to continue - # checking future ranges against the latter half. - ranges.append(difference.ranges[0]) - current = difference.ranges[-1] - else: - current = difference - - if not ranges: - return current - - return VersionUnion.of(*(ranges + [current])) - - raise ValueError("Unknown VersionConstraint type {}.".format(other)) - - def allows_lower(self, other): # type: (VersionRange) -> bool - if self.min is None: - return other.min is not None - - if other.min is None: - return False - - if self.min < other.min: - return True - - if self.min > other.min: - return False - - return self.include_min and not other.include_min - - def allows_higher(self, other): # type: (VersionRange) -> bool - if self.max is None: - return other.max is not None - - if other.max is None: - return False - - if self.max < other.max: - return False - - if self.max > other.max: - return True - - return self.include_max and not other.include_max - - def is_strictly_lower(self, other): # type: (VersionRange) -> bool - if self.max is None or other.min is None: - return False - - if self.full_max < other.min: - return True - - if self.full_max > other.min: - return False - - return not self.include_max or not other.include_min - - def is_strictly_higher(self, other): # type: (VersionRange) -> bool - return other.is_strictly_lower(self) - - def is_adjacent_to(self, other): # type: (VersionRange) -> bool - if self.max != other.min: - return False - - return ( - self.include_max - and not other.include_min - or not self.include_max - and other.include_min - ) - - def __eq__(self, other): - if not isinstance(other, VersionRange): - return False - - return ( - self._min == other.min - and self._max == other.max - and self._include_min == other.include_min - and self._include_max == other.include_max - ) - - def __lt__(self, other): - return self._cmp(other) < 0 - - def __le__(self, other): - return self._cmp(other) <= 0 - - def __gt__(self, other): - return self._cmp(other) > 0 - - def __ge__(self, other): - return self._cmp(other) >= 0 - - def _cmp(self, other): # type: (VersionRange) -> int - if self.min is None: - if other.min is None: - return self._compare_max(other) - - return -1 - elif other.min is None: - return 1 - - result = self.min._cmp(other.min) - if result != 0: - return result - - if self.include_min != other.include_min: - return -1 if self.include_min else 1 - - return self._compare_max(other) - - def _compare_max(self, other): # type: (VersionRange) -> int - if self.max is None: - if other.max is None: - return 0 - - return 1 - elif other.max is None: - return -1 - - result = self.max._cmp(other.max) - if result != 0: - return result - - if self.include_max != other.include_max: - return 1 if self.include_max else -1 - - return 0 - - def __str__(self): - text = "" - - if self.min is not None: - text += ">=" if self.include_min else ">" - text += self.min.text - - if self.max is not None: - if self.min is not None: - text += "," - - text += "{}{}".format("<=" if self.include_max else "<", self.max.text) - - if self.min is None and self.max is None: - return "*" - - return text - - def __repr__(self): - return "".format(str(self)) - - def __hash__(self): - return hash((self.min, self.max, self.include_min, self.include_max)) diff --git a/poetry/semver/version_union.py b/poetry/semver/version_union.py deleted file mode 100644 index 95294c9e218..00000000000 --- a/poetry/semver/version_union.py +++ /dev/null @@ -1,254 +0,0 @@ -from typing import List - -from .empty_constraint import EmptyConstraint -from .version_constraint import VersionConstraint - - -class VersionUnion(VersionConstraint): - """ - A version constraint representing a union of multiple disjoint version - ranges. - - An instance of this will only be created if the version can't be represented - as a non-compound value. - """ - - def __init__(self, *ranges): - self._ranges = list(ranges) - - @property - def ranges(self): - return self._ranges - - @classmethod - def of(cls, *ranges): - from .version_range import VersionRange - - flattened = [] - for constraint in ranges: - if constraint.is_empty(): - continue - - if isinstance(constraint, VersionUnion): - flattened += constraint.ranges - continue - - flattened.append(constraint) - - if not flattened: - return EmptyConstraint() - - if any([constraint.is_any() for constraint in flattened]): - return VersionRange() - - # Only allow Versions and VersionRanges here so we can more easily reason - # about everything in flattened. _EmptyVersions and VersionUnions are - # filtered out above. - for constraint in flattened: - if isinstance(constraint, VersionRange): - continue - - raise ValueError("Unknown VersionConstraint type {}.".format(constraint)) - - flattened.sort() - - merged = [] - for constraint in flattened: - # Merge this constraint with the previous one, but only if they touch. - if not merged or ( - not merged[-1].allows_any(constraint) - and not merged[-1].is_adjacent_to(constraint) - ): - merged.append(constraint) - else: - merged[-1] = merged[-1].union(constraint) - - if len(merged) == 1: - return merged[0] - - return VersionUnion(*merged) - - def is_empty(self): - return False - - def is_any(self): - return False - - def allows(self, version): # type: ("Version") -> bool - return any([constraint.allows(version) for constraint in self._ranges]) - - def allows_all(self, other): # type: (VersionConstraint) -> bool - our_ranges = iter(self._ranges) - their_ranges = iter(self._ranges_for(other)) - - our_current_range = next(our_ranges, None) - their_current_range = next(their_ranges, None) - - while our_current_range and their_current_range: - if our_current_range.allows_all(their_current_range): - their_current_range = next(their_ranges, None) - else: - our_current_range = next(our_ranges, None) - - return their_current_range is None - - def allows_any(self, other): # type: (VersionConstraint) -> bool - our_ranges = iter(self._ranges) - their_ranges = iter(self._ranges_for(other)) - - our_current_range = next(our_ranges, None) - their_current_range = next(their_ranges, None) - - while our_current_range and their_current_range: - if our_current_range.allows_any(their_current_range): - return True - - if their_current_range.allows_higher(our_current_range): - our_current_range = next(our_ranges, None) - else: - their_current_range = next(their_ranges, None) - - return False - - def intersect(self, other): # type: (VersionConstraint) -> VersionConstraint - our_ranges = iter(self._ranges) - their_ranges = iter(self._ranges_for(other)) - new_ranges = [] - - our_current_range = next(our_ranges, None) - their_current_range = next(their_ranges, None) - - while our_current_range and their_current_range: - intersection = our_current_range.intersect(their_current_range) - - if not intersection.is_empty(): - new_ranges.append(intersection) - - if their_current_range.allows_higher(our_current_range): - our_current_range = next(our_ranges, None) - else: - their_current_range = next(their_ranges, None) - - return VersionUnion.of(*new_ranges) - - def union(self, other): # type: (VersionConstraint) -> VersionConstraint - return VersionUnion.of(self, other) - - def difference(self, other): # type: (VersionConstraint) -> VersionConstraint - our_ranges = iter(self._ranges) - their_ranges = iter(self._ranges_for(other)) - new_ranges = [] - - state = { - "current": next(our_ranges, None), - "their_range": next(their_ranges, None), - } - - def their_next_range(): - state["their_range"] = next(their_ranges, None) - if state["their_range"]: - return True - - new_ranges.append(state["current"]) - our_current = next(our_ranges, None) - while our_current: - new_ranges.append(our_current) - our_current = next(our_ranges, None) - - return False - - def our_next_range(include_current=True): - if include_current: - new_ranges.append(state["current"]) - - our_current = next(our_ranges, None) - if not our_current: - return False - - state["current"] = our_current - - return True - - while True: - if state["their_range"] is None: - break - - if state["their_range"].is_strictly_lower(state["current"]): - if not their_next_range(): - break - - continue - - if state["their_range"].is_strictly_higher(state["current"]): - if not our_next_range(): - break - - continue - - difference = state["current"].difference(state["their_range"]) - if isinstance(difference, VersionUnion): - assert len(difference.ranges) == 2 - new_ranges.append(difference.ranges[0]) - state["current"] = difference.ranges[-1] - - if not their_next_range(): - break - elif difference.is_empty(): - if not our_next_range(False): - break - else: - state["current"] = difference - - if state["current"].allows_higher(state["their_range"]): - if not their_next_range(): - break - else: - if not our_next_range(): - break - - if not new_ranges: - return EmptyConstraint() - - if len(new_ranges) == 1: - return new_ranges[0] - - return VersionUnion.of(*new_ranges) - - def _ranges_for( - self, constraint - ): # type: (VersionConstraint) -> List["VersionRange"] - from .version_range import VersionRange - - if constraint.is_empty(): - return [] - - if isinstance(constraint, VersionUnion): - return constraint.ranges - - if isinstance(constraint, VersionRange): - return [constraint] - - raise ValueError("Unknown VersionConstraint type {}".format(constraint)) - - def excludes_single_version(self): # type: () -> bool - from .version import Version - from .version_range import VersionRange - - return isinstance(VersionRange().difference(self), Version) - - def __eq__(self, other): - if not isinstance(other, VersionUnion): - return False - - return self._ranges == other.ranges - - def __str__(self): - from .version_range import VersionRange - - if self.excludes_single_version(): - return "!={}".format(VersionRange().difference(self)) - - return " || ".join([str(r) for r in self._ranges]) - - def __repr__(self): - return "".format(str(self)) diff --git a/poetry/spdx/__init__.py b/poetry/spdx/__init__.py deleted file mode 100644 index 80a2a67d736..00000000000 --- a/poetry/spdx/__init__.py +++ /dev/null @@ -1,53 +0,0 @@ -import json -import os - -from io import open - -from .license import License -from .updater import Updater - - -_licenses = None - - -def license_by_id(identifier): - if _licenses is None: - load_licenses() - - id = identifier.lower() - - if id not in _licenses: - raise ValueError("Invalid license id: {}".format(identifier)) - - return _licenses[id] - - -def load_licenses(): - global _licenses - - _licenses = {} - - licenses_file = os.path.join(os.path.dirname(__file__), "data", "licenses.json") - - with open(licenses_file, encoding="utf-8") as f: - data = json.loads(f.read()) - - for name, license_info in data.items(): - license = License(name, license_info[0], license_info[1], license_info[2]) - _licenses[name.lower()] = license - - full_name = license_info[0].lower() - if full_name in _licenses: - existing_license = _licenses[full_name] - if not existing_license.is_deprecated: - continue - - _licenses[full_name] = license - - # Add a Proprietary license for non-standard licenses - _licenses["proprietary"] = License("Proprietary", "Proprietary", False, False) - - -if __name__ == "__main__": - updater = Updater() - updater.dump() diff --git a/poetry/spdx/data/licenses.json b/poetry/spdx/data/licenses.json deleted file mode 100644 index b598305bb49..00000000000 --- a/poetry/spdx/data/licenses.json +++ /dev/null @@ -1,1847 +0,0 @@ -{ - "0BSD": [ - "BSD Zero Clause License", - false, - false - ], - "AAL": [ - "Attribution Assurance License", - true, - false - ], - "ADSL": [ - "Amazon Digital Services License", - false, - false - ], - "AFL-1.1": [ - "Academic Free License v1.1", - true, - false - ], - "AFL-1.2": [ - "Academic Free License v1.2", - true, - false - ], - "AFL-2.0": [ - "Academic Free License v2.0", - true, - false - ], - "AFL-2.1": [ - "Academic Free License v2.1", - true, - false - ], - "AFL-3.0": [ - "Academic Free License v3.0", - true, - false - ], - "AGPL-1.0": [ - "Affero General Public License v1.0", - false, - false - ], - "AGPL-3.0": [ - "GNU Affero General Public License v3.0", - true, - true - ], - "AGPL-3.0-only": [ - "GNU Affero General Public License v3.0 only", - true, - false - ], - "AGPL-3.0-or-later": [ - "GNU Affero General Public License v3.0 or later", - true, - false - ], - "AMDPLPA": [ - "AMD's plpa_map.c License", - false, - false - ], - "AML": [ - "Apple MIT License", - false, - false - ], - "AMPAS": [ - "Academy of Motion Picture Arts and Sciences BSD", - false, - false - ], - "ANTLR-PD": [ - "ANTLR Software Rights Notice", - false, - false - ], - "APAFML": [ - "Adobe Postscript AFM License", - false, - false - ], - "APL-1.0": [ - "Adaptive Public License 1.0", - true, - false - ], - "APSL-1.0": [ - "Apple Public Source License 1.0", - true, - false - ], - "APSL-1.1": [ - "Apple Public Source License 1.1", - true, - false - ], - "APSL-1.2": [ - "Apple Public Source License 1.2", - true, - false - ], - "APSL-2.0": [ - "Apple Public Source License 2.0", - true, - false - ], - "Abstyles": [ - "Abstyles License", - false, - false - ], - "Adobe-2006": [ - "Adobe Systems Incorporated Source Code License Agreement", - false, - false - ], - "Adobe-Glyph": [ - "Adobe Glyph List License", - false, - false - ], - "Afmparse": [ - "Afmparse License", - false, - false - ], - "Aladdin": [ - "Aladdin Free Public License", - false, - false - ], - "Apache-1.0": [ - "Apache License 1.0", - false, - false - ], - "Apache-1.1": [ - "Apache License 1.1", - true, - false - ], - "Apache-2.0": [ - "Apache License 2.0", - true, - false - ], - "Artistic-1.0": [ - "Artistic License 1.0", - true, - false - ], - "Artistic-1.0-Perl": [ - "Artistic License 1.0 (Perl)", - true, - false - ], - "Artistic-1.0-cl8": [ - "Artistic License 1.0 w/clause 8", - true, - false - ], - "Artistic-2.0": [ - "Artistic License 2.0", - true, - false - ], - "BSD-1-Clause": [ - "BSD 1-Clause License", - false, - false - ], - "BSD-2-Clause": [ - "BSD 2-Clause \"Simplified\" License", - true, - false - ], - "BSD-2-Clause-FreeBSD": [ - "BSD 2-Clause FreeBSD License", - false, - false - ], - "BSD-2-Clause-NetBSD": [ - "BSD 2-Clause NetBSD License", - false, - false - ], - "BSD-2-Clause-Patent": [ - "BSD-2-Clause Plus Patent License", - true, - false - ], - "BSD-3-Clause": [ - "BSD 3-Clause \"New\" or \"Revised\" License", - true, - false - ], - "BSD-3-Clause-Attribution": [ - "BSD with attribution", - false, - false - ], - "BSD-3-Clause-Clear": [ - "BSD 3-Clause Clear License", - false, - false - ], - "BSD-3-Clause-LBNL": [ - "Lawrence Berkeley National Labs BSD variant license", - false, - false - ], - "BSD-3-Clause-No-Nuclear-License": [ - "BSD 3-Clause No Nuclear License", - false, - false - ], - "BSD-3-Clause-No-Nuclear-License-2014": [ - "BSD 3-Clause No Nuclear License 2014", - false, - false - ], - "BSD-3-Clause-No-Nuclear-Warranty": [ - "BSD 3-Clause No Nuclear Warranty", - false, - false - ], - "BSD-4-Clause": [ - "BSD 4-Clause \"Original\" or \"Old\" License", - false, - false - ], - "BSD-4-Clause-UC": [ - "BSD-4-Clause (University of California-Specific)", - false, - false - ], - "BSD-Protection": [ - "BSD Protection License", - false, - false - ], - "BSD-Source-Code": [ - "BSD Source Code Attribution", - false, - false - ], - "BSL-1.0": [ - "Boost Software License 1.0", - true, - false - ], - "Bahyph": [ - "Bahyph License", - false, - false - ], - "Barr": [ - "Barr License", - false, - false - ], - "Beerware": [ - "Beerware License", - false, - false - ], - "BitTorrent-1.0": [ - "BitTorrent Open Source License v1.0", - false, - false - ], - "BitTorrent-1.1": [ - "BitTorrent Open Source License v1.1", - false, - false - ], - "Borceux": [ - "Borceux license", - false, - false - ], - "CATOSL-1.1": [ - "Computer Associates Trusted Open Source License 1.1", - true, - false - ], - "CC-BY-1.0": [ - "Creative Commons Attribution 1.0", - false, - false - ], - "CC-BY-2.0": [ - "Creative Commons Attribution 2.0", - false, - false - ], - "CC-BY-2.5": [ - "Creative Commons Attribution 2.5", - false, - false - ], - "CC-BY-3.0": [ - "Creative Commons Attribution 3.0", - false, - false - ], - "CC-BY-4.0": [ - "Creative Commons Attribution 4.0", - false, - false - ], - "CC-BY-NC-1.0": [ - "Creative Commons Attribution Non Commercial 1.0", - false, - false - ], - "CC-BY-NC-2.0": [ - "Creative Commons Attribution Non Commercial 2.0", - false, - false - ], - "CC-BY-NC-2.5": [ - "Creative Commons Attribution Non Commercial 2.5", - false, - false - ], - "CC-BY-NC-3.0": [ - "Creative Commons Attribution Non Commercial 3.0", - false, - false - ], - "CC-BY-NC-4.0": [ - "Creative Commons Attribution Non Commercial 4.0", - false, - false - ], - "CC-BY-NC-ND-1.0": [ - "Creative Commons Attribution Non Commercial No Derivatives 1.0", - false, - false - ], - "CC-BY-NC-ND-2.0": [ - "Creative Commons Attribution Non Commercial No Derivatives 2.0", - false, - false - ], - "CC-BY-NC-ND-2.5": [ - "Creative Commons Attribution Non Commercial No Derivatives 2.5", - false, - false - ], - "CC-BY-NC-ND-3.0": [ - "Creative Commons Attribution Non Commercial No Derivatives 3.0", - false, - false - ], - "CC-BY-NC-ND-4.0": [ - "Creative Commons Attribution Non Commercial No Derivatives 4.0", - false, - false - ], - "CC-BY-NC-SA-1.0": [ - "Creative Commons Attribution Non Commercial Share Alike 1.0", - false, - false - ], - "CC-BY-NC-SA-2.0": [ - "Creative Commons Attribution Non Commercial Share Alike 2.0", - false, - false - ], - "CC-BY-NC-SA-2.5": [ - "Creative Commons Attribution Non Commercial Share Alike 2.5", - false, - false - ], - "CC-BY-NC-SA-3.0": [ - "Creative Commons Attribution Non Commercial Share Alike 3.0", - false, - false - ], - "CC-BY-NC-SA-4.0": [ - "Creative Commons Attribution Non Commercial Share Alike 4.0", - false, - false - ], - "CC-BY-ND-1.0": [ - "Creative Commons Attribution No Derivatives 1.0", - false, - false - ], - "CC-BY-ND-2.0": [ - "Creative Commons Attribution No Derivatives 2.0", - false, - false - ], - "CC-BY-ND-2.5": [ - "Creative Commons Attribution No Derivatives 2.5", - false, - false - ], - "CC-BY-ND-3.0": [ - "Creative Commons Attribution No Derivatives 3.0", - false, - false - ], - "CC-BY-ND-4.0": [ - "Creative Commons Attribution No Derivatives 4.0", - false, - false - ], - "CC-BY-SA-1.0": [ - "Creative Commons Attribution Share Alike 1.0", - false, - false - ], - "CC-BY-SA-2.0": [ - "Creative Commons Attribution Share Alike 2.0", - false, - false - ], - "CC-BY-SA-2.5": [ - "Creative Commons Attribution Share Alike 2.5", - false, - false - ], - "CC-BY-SA-3.0": [ - "Creative Commons Attribution Share Alike 3.0", - false, - false - ], - "CC-BY-SA-4.0": [ - "Creative Commons Attribution Share Alike 4.0", - false, - false - ], - "CC0-1.0": [ - "Creative Commons Zero v1.0 Universal", - false, - false - ], - "CDDL-1.0": [ - "Common Development and Distribution License 1.0", - true, - false - ], - "CDDL-1.1": [ - "Common Development and Distribution License 1.1", - false, - false - ], - "CDLA-Permissive-1.0": [ - "Community Data License Agreement Permissive 1.0", - false, - false - ], - "CDLA-Sharing-1.0": [ - "Community Data License Agreement Sharing 1.0", - false, - false - ], - "CECILL-1.0": [ - "CeCILL Free Software License Agreement v1.0", - false, - false - ], - "CECILL-1.1": [ - "CeCILL Free Software License Agreement v1.1", - false, - false - ], - "CECILL-2.0": [ - "CeCILL Free Software License Agreement v2.0", - false, - false - ], - "CECILL-2.1": [ - "CeCILL Free Software License Agreement v2.1", - true, - false - ], - "CECILL-B": [ - "CeCILL-B Free Software License Agreement", - false, - false - ], - "CECILL-C": [ - "CeCILL-C Free Software License Agreement", - false, - false - ], - "CNRI-Jython": [ - "CNRI Jython License", - false, - false - ], - "CNRI-Python": [ - "CNRI Python License", - true, - false - ], - "CNRI-Python-GPL-Compatible": [ - "CNRI Python Open Source GPL Compatible License Agreement", - false, - false - ], - "CPAL-1.0": [ - "Common Public Attribution License 1.0", - true, - false - ], - "CPL-1.0": [ - "Common Public License 1.0", - true, - false - ], - "CPOL-1.02": [ - "Code Project Open License 1.02", - false, - false - ], - "CUA-OPL-1.0": [ - "CUA Office Public License v1.0", - true, - false - ], - "Caldera": [ - "Caldera License", - false, - false - ], - "ClArtistic": [ - "Clarified Artistic License", - false, - false - ], - "Condor-1.1": [ - "Condor Public License v1.1", - false, - false - ], - "Crossword": [ - "Crossword License", - false, - false - ], - "CrystalStacker": [ - "CrystalStacker License", - false, - false - ], - "Cube": [ - "Cube License", - false, - false - ], - "D-FSL-1.0": [ - "Deutsche Freie Software Lizenz", - false, - false - ], - "DOC": [ - "DOC License", - false, - false - ], - "DSDP": [ - "DSDP License", - false, - false - ], - "Dotseqn": [ - "Dotseqn License", - false, - false - ], - "ECL-1.0": [ - "Educational Community License v1.0", - true, - false - ], - "ECL-2.0": [ - "Educational Community License v2.0", - true, - false - ], - "EFL-1.0": [ - "Eiffel Forum License v1.0", - true, - false - ], - "EFL-2.0": [ - "Eiffel Forum License v2.0", - true, - false - ], - "EPL-1.0": [ - "Eclipse Public License 1.0", - true, - false - ], - "EPL-2.0": [ - "Eclipse Public License 2.0", - true, - false - ], - "EUDatagrid": [ - "EU DataGrid Software License", - true, - false - ], - "EUPL-1.0": [ - "European Union Public License 1.0", - false, - false - ], - "EUPL-1.1": [ - "European Union Public License 1.1", - true, - false - ], - "EUPL-1.2": [ - "European Union Public License 1.2", - true, - false - ], - "Entessa": [ - "Entessa Public License v1.0", - true, - false - ], - "ErlPL-1.1": [ - "Erlang Public License v1.1", - false, - false - ], - "Eurosym": [ - "Eurosym License", - false, - false - ], - "FSFAP": [ - "FSF All Permissive License", - false, - false - ], - "FSFUL": [ - "FSF Unlimited License", - false, - false - ], - "FSFULLR": [ - "FSF Unlimited License (with License Retention)", - false, - false - ], - "FTL": [ - "Freetype Project License", - false, - false - ], - "Fair": [ - "Fair License", - true, - false - ], - "Frameworx-1.0": [ - "Frameworx Open License 1.0", - true, - false - ], - "FreeImage": [ - "FreeImage Public License v1.0", - false, - false - ], - "GFDL-1.1": [ - "GNU Free Documentation License v1.1", - false, - true - ], - "GFDL-1.1-only": [ - "GNU Free Documentation License v1.1 only", - false, - false - ], - "GFDL-1.1-or-later": [ - "GNU Free Documentation License v1.1 or later", - false, - false - ], - "GFDL-1.2": [ - "GNU Free Documentation License v1.2", - false, - true - ], - "GFDL-1.2-only": [ - "GNU Free Documentation License v1.2 only", - false, - false - ], - "GFDL-1.2-or-later": [ - "GNU Free Documentation License v1.2 or later", - false, - false - ], - "GFDL-1.3": [ - "GNU Free Documentation License v1.3", - false, - true - ], - "GFDL-1.3-only": [ - "GNU Free Documentation License v1.3 only", - false, - false - ], - "GFDL-1.3-or-later": [ - "GNU Free Documentation License v1.3 or later", - false, - false - ], - "GL2PS": [ - "GL2PS License", - false, - false - ], - "GPL-1.0": [ - "GNU General Public License v1.0 only", - false, - true - ], - "GPL-1.0+": [ - "GNU General Public License v1.0 or later", - false, - true - ], - "GPL-1.0-only": [ - "GNU General Public License v1.0 only", - false, - false - ], - "GPL-1.0-or-later": [ - "GNU General Public License v1.0 or later", - false, - false - ], - "GPL-2.0": [ - "GNU General Public License v2.0 only", - true, - true - ], - "GPL-2.0+": [ - "GNU General Public License v2.0 or later", - true, - true - ], - "GPL-2.0-only": [ - "GNU General Public License v2.0 only", - true, - false - ], - "GPL-2.0-or-later": [ - "GNU General Public License v2.0 or later", - true, - false - ], - "GPL-2.0-with-GCC-exception": [ - "GNU General Public License v2.0 w/GCC Runtime Library exception", - false, - true - ], - "GPL-2.0-with-autoconf-exception": [ - "GNU General Public License v2.0 w/Autoconf exception", - false, - true - ], - "GPL-2.0-with-bison-exception": [ - "GNU General Public License v2.0 w/Bison exception", - false, - true - ], - "GPL-2.0-with-classpath-exception": [ - "GNU General Public License v2.0 w/Classpath exception", - false, - true - ], - "GPL-2.0-with-font-exception": [ - "GNU General Public License v2.0 w/Font exception", - false, - true - ], - "GPL-3.0": [ - "GNU General Public License v3.0 only", - true, - true - ], - "GPL-3.0+": [ - "GNU General Public License v3.0 or later", - true, - true - ], - "GPL-3.0-only": [ - "GNU General Public License v3.0 only", - true, - false - ], - "GPL-3.0-or-later": [ - "GNU General Public License v3.0 or later", - true, - false - ], - "GPL-3.0-with-GCC-exception": [ - "GNU General Public License v3.0 w/GCC Runtime Library exception", - true, - true - ], - "GPL-3.0-with-autoconf-exception": [ - "GNU General Public License v3.0 w/Autoconf exception", - false, - true - ], - "Giftware": [ - "Giftware License", - false, - false - ], - "Glide": [ - "3dfx Glide License", - false, - false - ], - "Glulxe": [ - "Glulxe License", - false, - false - ], - "HPND": [ - "Historical Permission Notice and Disclaimer", - true, - false - ], - "HaskellReport": [ - "Haskell Language Report License", - false, - false - ], - "IBM-pibs": [ - "IBM PowerPC Initialization and Boot Software", - false, - false - ], - "ICU": [ - "ICU License", - false, - false - ], - "IJG": [ - "Independent JPEG Group License", - false, - false - ], - "IPA": [ - "IPA Font License", - true, - false - ], - "IPL-1.0": [ - "IBM Public License v1.0", - true, - false - ], - "ISC": [ - "ISC License", - true, - false - ], - "ImageMagick": [ - "ImageMagick License", - false, - false - ], - "Imlib2": [ - "Imlib2 License", - false, - false - ], - "Info-ZIP": [ - "Info-ZIP License", - false, - false - ], - "Intel": [ - "Intel Open Source License", - true, - false - ], - "Intel-ACPI": [ - "Intel ACPI Software License Agreement", - false, - false - ], - "Interbase-1.0": [ - "Interbase Public License v1.0", - false, - false - ], - "JSON": [ - "JSON License", - false, - false - ], - "JasPer-2.0": [ - "JasPer License", - false, - false - ], - "LAL-1.2": [ - "Licence Art Libre 1.2", - false, - false - ], - "LAL-1.3": [ - "Licence Art Libre 1.3", - false, - false - ], - "LGPL-2.0": [ - "GNU Library General Public License v2 only", - true, - true - ], - "LGPL-2.0+": [ - "GNU Library General Public License v2 or later", - true, - true - ], - "LGPL-2.0-only": [ - "GNU Library General Public License v2 only", - true, - false - ], - "LGPL-2.0-or-later": [ - "GNU Library General Public License v2 or later", - true, - false - ], - "LGPL-2.1": [ - "GNU Lesser General Public License v2.1 only", - true, - true - ], - "LGPL-2.1+": [ - "GNU Library General Public License v2 or later", - true, - true - ], - "LGPL-2.1-only": [ - "GNU Lesser General Public License v2.1 only", - true, - false - ], - "LGPL-2.1-or-later": [ - "GNU Lesser General Public License v2.1 or later", - true, - false - ], - "LGPL-3.0": [ - "GNU Lesser General Public License v3.0 only", - true, - true - ], - "LGPL-3.0+": [ - "GNU Lesser General Public License v3.0 or later", - true, - true - ], - "LGPL-3.0-only": [ - "GNU Lesser General Public License v3.0 only", - true, - false - ], - "LGPL-3.0-or-later": [ - "GNU Lesser General Public License v3.0 or later", - true, - false - ], - "LGPLLR": [ - "Lesser General Public License For Linguistic Resources", - false, - false - ], - "LPL-1.0": [ - "Lucent Public License Version 1.0", - true, - false - ], - "LPL-1.02": [ - "Lucent Public License v1.02", - true, - false - ], - "LPPL-1.0": [ - "LaTeX Project Public License v1.0", - false, - false - ], - "LPPL-1.1": [ - "LaTeX Project Public License v1.1", - false, - false - ], - "LPPL-1.2": [ - "LaTeX Project Public License v1.2", - false, - false - ], - "LPPL-1.3a": [ - "LaTeX Project Public License v1.3a", - false, - false - ], - "LPPL-1.3c": [ - "LaTeX Project Public License v1.3c", - true, - false - ], - "Latex2e": [ - "Latex2e License", - false, - false - ], - "Leptonica": [ - "Leptonica License", - false, - false - ], - "LiLiQ-P-1.1": [ - "Licence Libre du Qu\u00e9bec \u2013 Permissive version 1.1", - true, - false - ], - "LiLiQ-R-1.1": [ - "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 version 1.1", - true, - false - ], - "LiLiQ-Rplus-1.1": [ - "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 forte version 1.1", - true, - false - ], - "Libpng": [ - "libpng License", - false, - false - ], - "MIT": [ - "MIT License", - true, - false - ], - "MIT-CMU": [ - "CMU License", - false, - false - ], - "MIT-advertising": [ - "Enlightenment License (e16)", - false, - false - ], - "MIT-enna": [ - "enna License", - false, - false - ], - "MIT-feh": [ - "feh License", - false, - false - ], - "MITNFA": [ - "MIT +no-false-attribs license", - false, - false - ], - "MPL-1.0": [ - "Mozilla Public License 1.0", - true, - false - ], - "MPL-1.1": [ - "Mozilla Public License 1.1", - true, - false - ], - "MPL-2.0": [ - "Mozilla Public License 2.0", - true, - false - ], - "MPL-2.0-no-copyleft-exception": [ - "Mozilla Public License 2.0 (no copyleft exception)", - true, - false - ], - "MS-PL": [ - "Microsoft Public License", - true, - false - ], - "MS-RL": [ - "Microsoft Reciprocal License", - true, - false - ], - "MTLL": [ - "Matrix Template Library License", - false, - false - ], - "MakeIndex": [ - "MakeIndex License", - false, - false - ], - "MirOS": [ - "MirOS License", - true, - false - ], - "Motosoto": [ - "Motosoto License", - true, - false - ], - "Multics": [ - "Multics License", - true, - false - ], - "Mup": [ - "Mup License", - false, - false - ], - "NASA-1.3": [ - "NASA Open Source Agreement 1.3", - true, - false - ], - "NBPL-1.0": [ - "Net Boolean Public License v1", - false, - false - ], - "NCSA": [ - "University of Illinois/NCSA Open Source License", - true, - false - ], - "NGPL": [ - "Nethack General Public License", - true, - false - ], - "NLOD-1.0": [ - "Norwegian Licence for Open Government Data", - false, - false - ], - "NLPL": [ - "No Limit Public License", - false, - false - ], - "NOSL": [ - "Netizen Open Source License", - false, - false - ], - "NPL-1.0": [ - "Netscape Public License v1.0", - false, - false - ], - "NPL-1.1": [ - "Netscape Public License v1.1", - false, - false - ], - "NPOSL-3.0": [ - "Non-Profit Open Software License 3.0", - true, - false - ], - "NRL": [ - "NRL License", - false, - false - ], - "NTP": [ - "NTP License", - true, - false - ], - "Naumen": [ - "Naumen Public License", - true, - false - ], - "Net-SNMP": [ - "Net-SNMP License", - false, - false - ], - "NetCDF": [ - "NetCDF license", - false, - false - ], - "Newsletr": [ - "Newsletr License", - false, - false - ], - "Nokia": [ - "Nokia Open Source License", - true, - false - ], - "Noweb": [ - "Noweb License", - false, - false - ], - "Nunit": [ - "Nunit License", - false, - true - ], - "OCCT-PL": [ - "Open CASCADE Technology Public License", - false, - false - ], - "OCLC-2.0": [ - "OCLC Research Public License 2.0", - true, - false - ], - "ODbL-1.0": [ - "ODC Open Database License v1.0", - false, - false - ], - "OFL-1.0": [ - "SIL Open Font License 1.0", - false, - false - ], - "OFL-1.1": [ - "SIL Open Font License 1.1", - true, - false - ], - "OGTSL": [ - "Open Group Test Suite License", - true, - false - ], - "OLDAP-1.1": [ - "Open LDAP Public License v1.1", - false, - false - ], - "OLDAP-1.2": [ - "Open LDAP Public License v1.2", - false, - false - ], - "OLDAP-1.3": [ - "Open LDAP Public License v1.3", - false, - false - ], - "OLDAP-1.4": [ - "Open LDAP Public License v1.4", - false, - false - ], - "OLDAP-2.0": [ - "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)", - false, - false - ], - "OLDAP-2.0.1": [ - "Open LDAP Public License v2.0.1", - false, - false - ], - "OLDAP-2.1": [ - "Open LDAP Public License v2.1", - false, - false - ], - "OLDAP-2.2": [ - "Open LDAP Public License v2.2", - false, - false - ], - "OLDAP-2.2.1": [ - "Open LDAP Public License v2.2.1", - false, - false - ], - "OLDAP-2.2.2": [ - "Open LDAP Public License 2.2.2", - false, - false - ], - "OLDAP-2.3": [ - "Open LDAP Public License v2.3", - false, - false - ], - "OLDAP-2.4": [ - "Open LDAP Public License v2.4", - false, - false - ], - "OLDAP-2.5": [ - "Open LDAP Public License v2.5", - false, - false - ], - "OLDAP-2.6": [ - "Open LDAP Public License v2.6", - false, - false - ], - "OLDAP-2.7": [ - "Open LDAP Public License v2.7", - false, - false - ], - "OLDAP-2.8": [ - "Open LDAP Public License v2.8", - false, - false - ], - "OML": [ - "Open Market License", - false, - false - ], - "OPL-1.0": [ - "Open Public License v1.0", - false, - false - ], - "OSET-PL-2.1": [ - "OSET Public License version 2.1", - true, - false - ], - "OSL-1.0": [ - "Open Software License 1.0", - true, - false - ], - "OSL-1.1": [ - "Open Software License 1.1", - false, - false - ], - "OSL-2.0": [ - "Open Software License 2.0", - true, - false - ], - "OSL-2.1": [ - "Open Software License 2.1", - true, - false - ], - "OSL-3.0": [ - "Open Software License 3.0", - true, - false - ], - "OpenSSL": [ - "OpenSSL License", - false, - false - ], - "PDDL-1.0": [ - "ODC Public Domain Dedication & License 1.0", - false, - false - ], - "PHP-3.0": [ - "PHP License v3.0", - true, - false - ], - "PHP-3.01": [ - "PHP License v3.01", - false, - false - ], - "Plexus": [ - "Plexus Classworlds License", - false, - false - ], - "PostgreSQL": [ - "PostgreSQL License", - true, - false - ], - "Python-2.0": [ - "Python License 2.0", - true, - false - ], - "QPL-1.0": [ - "Q Public License 1.0", - true, - false - ], - "Qhull": [ - "Qhull License", - false, - false - ], - "RHeCos-1.1": [ - "Red Hat eCos Public License v1.1", - false, - false - ], - "RPL-1.1": [ - "Reciprocal Public License 1.1", - true, - false - ], - "RPL-1.5": [ - "Reciprocal Public License 1.5", - true, - false - ], - "RPSL-1.0": [ - "RealNetworks Public Source License v1.0", - true, - false - ], - "RSA-MD": [ - "RSA Message-Digest License ", - false, - false - ], - "RSCPL": [ - "Ricoh Source Code Public License", - true, - false - ], - "Rdisc": [ - "Rdisc License", - false, - false - ], - "Ruby": [ - "Ruby License", - false, - false - ], - "SAX-PD": [ - "Sax Public Domain Notice", - false, - false - ], - "SCEA": [ - "SCEA Shared Source License", - false, - false - ], - "SGI-B-1.0": [ - "SGI Free Software License B v1.0", - false, - false - ], - "SGI-B-1.1": [ - "SGI Free Software License B v1.1", - false, - false - ], - "SGI-B-2.0": [ - "SGI Free Software License B v2.0", - false, - false - ], - "SISSL": [ - "Sun Industry Standards Source License v1.1", - true, - false - ], - "SISSL-1.2": [ - "Sun Industry Standards Source License v1.2", - false, - false - ], - "SMLNJ": [ - "Standard ML of New Jersey License", - false, - false - ], - "SMPPL": [ - "Secure Messaging Protocol Public License", - false, - false - ], - "SNIA": [ - "SNIA Public License 1.1", - false, - false - ], - "SPL-1.0": [ - "Sun Public License v1.0", - true, - false - ], - "SWL": [ - "Scheme Widget Library (SWL) Software License Agreement", - false, - false - ], - "Saxpath": [ - "Saxpath License", - false, - false - ], - "Sendmail": [ - "Sendmail License", - false, - false - ], - "SimPL-2.0": [ - "Simple Public License 2.0", - true, - false - ], - "Sleepycat": [ - "Sleepycat License", - true, - false - ], - "Spencer-86": [ - "Spencer License 86", - false, - false - ], - "Spencer-94": [ - "Spencer License 94", - false, - false - ], - "Spencer-99": [ - "Spencer License 99", - false, - false - ], - "StandardML-NJ": [ - "Standard ML of New Jersey License", - false, - true - ], - "SugarCRM-1.1.3": [ - "SugarCRM Public License v1.1.3", - false, - false - ], - "TCL": [ - "TCL/TK License", - false, - false - ], - "TCP-wrappers": [ - "TCP Wrappers License", - false, - false - ], - "TMate": [ - "TMate Open Source License", - false, - false - ], - "TORQUE-1.1": [ - "TORQUE v2.5+ Software License v1.1", - false, - false - ], - "TOSL": [ - "Trusster Open Source License", - false, - false - ], - "UPL-1.0": [ - "Universal Permissive License v1.0", - true, - false - ], - "Unicode-DFS-2015": [ - "Unicode License Agreement - Data Files and Software (2015)", - false, - false - ], - "Unicode-DFS-2016": [ - "Unicode License Agreement - Data Files and Software (2016)", - false, - false - ], - "Unicode-TOU": [ - "Unicode Terms of Use", - false, - false - ], - "Unlicense": [ - "The Unlicense", - false, - false - ], - "VOSTROM": [ - "VOSTROM Public License for Open Source", - false, - false - ], - "VSL-1.0": [ - "Vovida Software License v1.0", - true, - false - ], - "Vim": [ - "Vim License", - false, - false - ], - "W3C": [ - "W3C Software Notice and License (2002-12-31)", - true, - false - ], - "W3C-19980720": [ - "W3C Software Notice and License (1998-07-20)", - false, - false - ], - "W3C-20150513": [ - "W3C Software Notice and Document License (2015-05-13)", - false, - false - ], - "WTFPL": [ - "Do What The F*ck You Want To Public License", - false, - false - ], - "Watcom-1.0": [ - "Sybase Open Watcom Public License 1.0", - true, - false - ], - "Wsuipa": [ - "Wsuipa License", - false, - false - ], - "X11": [ - "X11 License", - false, - false - ], - "XFree86-1.1": [ - "XFree86 License 1.1", - false, - false - ], - "XSkat": [ - "XSkat License", - false, - false - ], - "Xerox": [ - "Xerox License", - false, - false - ], - "Xnet": [ - "X.Net License", - true, - false - ], - "YPL-1.0": [ - "Yahoo! Public License v1.0", - false, - false - ], - "YPL-1.1": [ - "Yahoo! Public License v1.1", - false, - false - ], - "ZPL-1.1": [ - "Zope Public License 1.1", - false, - false - ], - "ZPL-2.0": [ - "Zope Public License 2.0", - true, - false - ], - "ZPL-2.1": [ - "Zope Public License 2.1", - false, - false - ], - "Zed": [ - "Zed License", - false, - false - ], - "Zend-2.0": [ - "Zend License v2.0", - false, - false - ], - "Zimbra-1.3": [ - "Zimbra Public License v1.3", - false, - false - ], - "Zimbra-1.4": [ - "Zimbra Public License v1.4", - false, - false - ], - "Zlib": [ - "zlib License", - true, - false - ], - "bzip2-1.0.5": [ - "bzip2 and libbzip2 License v1.0.5", - false, - false - ], - "bzip2-1.0.6": [ - "bzip2 and libbzip2 License v1.0.6", - false, - false - ], - "curl": [ - "curl License", - false, - false - ], - "diffmark": [ - "diffmark license", - false, - false - ], - "dvipdfm": [ - "dvipdfm License", - false, - false - ], - "eCos-2.0": [ - "eCos license version 2.0", - false, - true - ], - "eGenix": [ - "eGenix.com Public License 1.1.0", - false, - false - ], - "gSOAP-1.3b": [ - "gSOAP Public License v1.3b", - false, - false - ], - "gnuplot": [ - "gnuplot License", - false, - false - ], - "iMatix": [ - "iMatix Standard Function Library Agreement", - false, - false - ], - "libtiff": [ - "libtiff License", - false, - false - ], - "mpich2": [ - "mpich2 License", - false, - false - ], - "psfrag": [ - "psfrag License", - false, - false - ], - "psutils": [ - "psutils License", - false, - false - ], - "wxWindows": [ - "wxWindows Library License", - false, - true - ], - "xinetd": [ - "xinetd License", - false, - false - ], - "xpp": [ - "XPP License", - false, - false - ], - "zlib-acknowledgement": [ - "zlib/libpng License with Acknowledgement", - false, - false - ] -} diff --git a/poetry/spdx/license.py b/poetry/spdx/license.py deleted file mode 100644 index 11bd2942a5e..00000000000 --- a/poetry/spdx/license.py +++ /dev/null @@ -1,156 +0,0 @@ -from collections import namedtuple - - -class License(namedtuple("License", "id name is_osi_approved is_deprecated")): - - CLASSIFIER_SUPPORTED = { - # Not OSI Approved - "Aladdin", - "CC0-1.0", - "CECILL-B", - "CECILL-C", - "NPL-1.0", - "NPL-1.1", - # OSI Approved - "AFPL", - "AFL-1.1", - "AFL-1.2", - "AFL-2.0", - "AFL-2.1", - "AFL-3.0", - "Apache-1.1", - "Apache-2.0", - "APSL-1.1", - "APSL-1.2", - "APSL-2.0", - "Artistic-1.0", - "Artistic-2.0", - "AAL", - "AGPL-3.0", - "AGPL-3.0-only", - "AGPL-3.0-or-later", - "BSL-1.0", - "BSD-2-Clause", - "BSD-3-Clause", - "CDDL-1.0", - "CECILL-2.1", - "CPL-1.0", - "EFL-1.0", - "EFL-2.0", - "EPL-1.0", - "EPL-2.0", - "EUPL-1.1", - "EUPL-1.2", - "GPL-2.0", - "GPL-2.0+", - "GPL-2.0-only", - "GPL-2.0-or-later", - "GPL-3.0", - "GPL-3.0+", - "GPL-3.0-only", - "GPL-3.0-or-later", - "LGPL-2.0", - "LGPL-2.0+", - "LGPL-2.0-only", - "LGPL-2.0-or-later", - "LGPL-3.0", - "LGPL-3.0+", - "LGPL-3.0-only", - "LGPL-3.0-or-later", - "MIT", - "MPL-1.0", - "MPL-1.1", - "MPL-1.2", - "Nokia", - "W3C", - "ZPL-1.0", - "ZPL-2.0", - "ZPL-2.1", - } - - CLASSIFIER_NAMES = { - # Not OSI Approved - "AFPL": "Aladdin Free Public License (AFPL)", - "CC0-1.0": "CC0 1.0 Universal (CC0 1.0) Public Domain Dedication", - "CECILL-B": "CeCILL-B Free Software License Agreement (CECILL-B)", - "CECILL-C": "CeCILL-C Free Software License Agreement (CECILL-C)", - "NPL-1.0": "Netscape Public License (NPL)", - "NPL-1.1": "Netscape Public License (NPL)", - # OSI Approved - "AFL-1.1": "Academic Free License (AFL)", - "AFL-1.2": "Academic Free License (AFL)", - "AFL-2.0": "Academic Free License (AFL)", - "AFL-2.1": "Academic Free License (AFL)", - "AFL-3.0": "Academic Free License (AFL)", - "Apache-1.1": "Apache Software License", - "Apache-2.0": "Apache Software License", - "APSL-1.1": "Apple Public Source License", - "APSL-1.2": "Apple Public Source License", - "APSL-2.0": "Apple Public Source License", - "Artistic-1.0": "Artistic License", - "Artistic-2.0": "Artistic License", - "AAL": "Attribution Assurance License", - "AGPL-3.0": "GNU Affero General Public License v3", - "AGPL-3.0-only": "GNU Affero General Public License v3", - "AGPL-3.0-or-later": "GNU Affero General Public License v3 or later (AGPLv3+)", - "BSL-1.0": "Boost Software License 1.0 (BSL-1.0)", - "BSD-2-Clause": "BSD License", - "BSD-3-Clause": "BSD License", - "CDDL-1.0": "Common Development and Distribution License 1.0 (CDDL-1.0)", - "CECILL-2.1": "CEA CNRS Inria Logiciel Libre License, version 2.1 (CeCILL-2.1)", - "CPL-1.0": "Common Public License", - "EPL-1.0": "Eclipse Public License 1.0 (EPL-1.0)", - "EFL-1.0": "Eiffel Forum License", - "EFL-2.0": "Eiffel Forum License", - "EUPL-1.1": "European Union Public Licence 1.1 (EUPL 1.1)", - "EUPL-1.2": "European Union Public Licence 1.2 (EUPL 1.2)", - "GPL-2.0": "GNU General Public License v2 (GPLv2)", - "GPL-2.0-only": "GNU General Public License v2 (GPLv2)", - "GPL-2.0+": "GNU General Public License v2 or later (GPLv2+)", - "GPL-2.0-or-later": "GNU General Public License v2 or later (GPLv2+)", - "GPL-3.0": "GNU General Public License v3 (GPLv3)", - "GPL-3.0-only": "GNU General Public License v3 (GPLv3)", - "GPL-3.0+": "GNU General Public License v3 or later (GPLv3+)", - "GPL-3.0-or-later": "GNU General Public License v3 or later (GPLv3+)", - "LGPL-2.0": "GNU Lesser General Public License v2 (LGPLv2)", - "LGPL-2.0-only": "GNU Lesser General Public License v2 (LGPLv2)", - "LGPL-2.0+": "GNU Lesser General Public License v2 or later (LGPLv2+)", - "LGPL-2.0-or-later": "GNU Lesser General Public License v2 or later (LGPLv2+)", - "LGPL-3.0": "GNU Lesser General Public License v3 (LGPLv3)", - "LGPL-3.0-only": "GNU Lesser General Public License v3 (LGPLv3)", - "LGPL-3.0+": "GNU Lesser General Public License v3 or later (LGPLv3+)", - "LGPL-3.0-or-later": "GNU Lesser General Public License v3 or later (LGPLv3+)", - "MPL-1.0": "Mozilla Public License 1.0 (MPL)", - "MPL-1.1": "Mozilla Public License 1.1 (MPL 1.1)", - "MPL-2.0": "Mozilla Public License 2.0 (MPL 2.0)", - "W3C": "W3C License", - "ZPL-1.1": "Zope Public License", - "ZPL-2.0": "Zope Public License", - "ZPL-2.1": "Zope Public License", - } - - @property - def classifier(self): - parts = ["License"] - - if self.is_osi_approved: - parts.append("OSI Approved") - - name = self.classifier_name - if name is not None: - parts.append(name) - - return " :: ".join(parts) - - @property - def classifier_name(self): - if self.id not in self.CLASSIFIER_SUPPORTED: - if self.is_osi_approved: - return None - - return "Other/Proprietary License" - - if self.id in self.CLASSIFIER_NAMES: - return self.CLASSIFIER_NAMES[self.id] - - return self.name diff --git a/poetry/spdx/updater.py b/poetry/spdx/updater.py deleted file mode 100644 index dca4d722399..00000000000 --- a/poetry/spdx/updater.py +++ /dev/null @@ -1,43 +0,0 @@ -import json -import os - -from io import open - - -try: - from urllib.request import urlopen -except ImportError: - from urllib2 import urlopen - - -class Updater: - - BASE_URL = "https://raw.githubusercontent.com/spdx/license-list-data/master/json/" - - def __init__(self, base_url=BASE_URL): - self._base_url = base_url - - def dump(self, file=None): - if file is None: - file = os.path.join(os.path.dirname(__file__), "data", "licenses.json") - - licenses_url = self._base_url + "licenses.json" - - with open(file, "w", encoding="utf-8") as f: - f.write( - json.dumps(self.get_licenses(licenses_url), indent=2, sort_keys=True) - ) - - def get_licenses(self, url): - licenses = {} - with urlopen(url) as r: - data = json.loads(r.read().decode()) - - for info in data["licenses"]: - licenses[info["licenseId"]] = [ - info["name"], - info["isOsiApproved"], - info["isDeprecatedLicenseId"], - ] - - return licenses diff --git a/poetry/utils/env.py b/poetry/utils/env.py index dcdec0363bf..2cfe507de6e 100644 --- a/poetry/utils/env.py +++ b/poetry/utils/env.py @@ -20,10 +20,11 @@ from clikit.api.io import IO +from poetry.core.semver import parse_constraint +from poetry.core.semver.version import Version +from poetry.core.version.markers import BaseMarker from poetry.locations import CACHE_DIR from poetry.poetry import Poetry -from poetry.semver import parse_constraint -from poetry.semver.version import Version from poetry.utils._compat import CalledProcessError from poetry.utils._compat import Path from poetry.utils._compat import decode @@ -31,7 +32,6 @@ from poetry.utils._compat import list_to_shell_command from poetry.utils._compat import subprocess from poetry.utils.toml_file import TomlFile -from poetry.version.markers import BaseMarker GET_ENVIRONMENT_INFO = """\ @@ -108,14 +108,19 @@ from venv import EnvBuilder builder = EnvBuilder(with_pip=True) - build = builder.create + builder.create(path) except ImportError: - # We fallback on virtualenv for Python 2.7 - from virtualenv import create_environment + try: + # We fallback on virtualenv for Python 2.7 + from virtualenv import create_environment - build = create_environment + create_environment(path) + except ImportError: + # since virtualenv>20 we have to use cli_run + from virtualenv import cli_run -build(path)""" + cli_run([path]) +""" class EnvError(Exception): @@ -367,11 +372,20 @@ def list(self, name=None): # type: (Optional[str]) -> List[VirtualEnv] else: venv_path = Path(venv_path) - return [ + env_list = [ VirtualEnv(Path(p)) for p in sorted(venv_path.glob("{}-py*".format(venv_name))) ] + venv = self._poetry.file.parent / ".venv" + if ( + self._poetry.config.get("virtualenvs.in-project") + and venv.exists() + and venv.is_dir() + ): + env_list.insert(0, VirtualEnv(venv)) + return env_list + def remove(self, python): # type: (str) -> Env venv_path = self._poetry.config.get("virtualenvs.path") if venv_path is None: @@ -668,14 +682,18 @@ def build_venv(cls, path, executable=None): use_symlinks = True builder = EnvBuilder(with_pip=True, symlinks=use_symlinks) - build = builder.create + builder.create(path) except ImportError: - # We fallback on virtualenv for Python 2.7 - from virtualenv import create_environment + try: + # We fallback on virtualenv for Python 2.7 + from virtualenv import create_environment - build = create_environment + create_environment(path) + except ImportError: + # since virtualenv>20 we have to use cli_run + from virtualenv import cli_run - build(path) + cli_run([path]) def remove_venv(self, path): # type: (str) -> None shutil.rmtree(path) diff --git a/poetry/utils/exporter.py b/poetry/utils/exporter.py index 9341962d4fb..116e20c8804 100644 --- a/poetry/utils/exporter.py +++ b/poetry/utils/exporter.py @@ -2,10 +2,10 @@ from clikit.api.io import IO -from poetry.packages.directory_dependency import DirectoryDependency -from poetry.packages.file_dependency import FileDependency -from poetry.packages.url_dependency import URLDependency -from poetry.packages.vcs_dependency import VCSDependency +from poetry.core.packages.directory_dependency import DirectoryDependency +from poetry.core.packages.file_dependency import FileDependency +from poetry.core.packages.url_dependency import URLDependency +from poetry.core.packages.vcs_dependency import VCSDependency from poetry.poetry import Poetry from poetry.utils._compat import Path from poetry.utils._compat import decode @@ -17,7 +17,9 @@ class Exporter(object): Exporter class to export a lock file to alternative formats. """ - ACCEPTED_FORMATS = ("requirements.txt",) + FORMAT_REQUIREMENTS_TXT = "requirements.txt" + #: The names of the supported export formats. + ACCEPTED_FORMATS = (FORMAT_REQUIREMENTS_TXT,) ALLOWED_HASH_ALGORITHMS = ("sha256", "sha384", "sha512") def __init__(self, poetry): # type: (Poetry) -> None diff --git a/poetry/utils/extras.py b/poetry/utils/extras.py index 2181f03966b..32b02ee9b00 100644 --- a/poetry/utils/extras.py +++ b/poetry/utils/extras.py @@ -3,7 +3,7 @@ from typing import Mapping from typing import Sequence -from poetry.packages import Package +from poetry.core.packages import Package from poetry.utils.helpers import canonicalize_name diff --git a/poetry/utils/helpers.py b/poetry/utils/helpers.py index 3ecef0c391e..ca0f43f8c78 100644 --- a/poetry/utils/helpers.py +++ b/poetry/utils/helpers.py @@ -5,12 +5,13 @@ import tempfile from contextlib import contextmanager -from typing import List from typing import Optional +import requests + from poetry.config.config import Config +from poetry.core.version import Version from poetry.utils._compat import Path -from poetry.version import Version try: @@ -49,47 +50,6 @@ def temporary_directory(*args, **kwargs): shutil.rmtree(name) -def parse_requires(requires): # type: (str) -> List[str] - lines = requires.split("\n") - - requires_dist = [] - in_section = False - current_marker = None - for line in lines: - line = line.strip() - if not line: - if in_section: - in_section = False - - continue - - if line.startswith("["): - # extras or conditional dependencies - marker = line.lstrip("[").rstrip("]") - if ":" not in marker: - extra, marker = marker, None - else: - extra, marker = marker.split(":") - - if extra: - if marker: - marker = '{} and extra == "{}"'.format(marker, extra) - else: - marker = 'extra == "{}"'.format(extra) - - if marker: - current_marker = marker - - continue - - if current_marker: - line = "{}; {}".format(line, current_marker) - - requires_dist.append(line) - - return requires_dist - - def get_cert(config, repository_name): # type: (Config, str) -> Optional[Path] cert = config.get("certificates.{}.cert".format(repository_name)) if cert: @@ -127,3 +87,17 @@ def merge_dicts(d1, d2): merge_dicts(d1[k], d2[k]) else: d1[k] = d2[k] + + +def download_file( + url, dest, session=None, chunk_size=1024 +): # type: (str, str, Optional[requests.Session], int) -> None + get = requests.get if not session else session.get + + with get(url, stream=True) as response: + response.raise_for_status() + + with open(dest, "wb") as f: + for chunk in response.iter_content(chunk_size=chunk_size): + if chunk: + f.write(chunk) diff --git a/poetry/utils/inspector.py b/poetry/utils/inspector.py deleted file mode 100644 index f1675273b47..00000000000 --- a/poetry/utils/inspector.py +++ /dev/null @@ -1,230 +0,0 @@ -import logging -import os -import tarfile -import zipfile - -from typing import Dict -from typing import List -from typing import Union - -import pkginfo - -from requests import get - -from ._compat import Path -from .helpers import parse_requires -from .setup_reader import SetupReader -from .toml_file import TomlFile - - -logger = logging.getLogger(__name__) - - -class Inspector: - """ - A class to download and inspect remote packages. - """ - - @classmethod - def download(cls, url, dest): # type: (str, Path) -> None - r = get(url, stream=True) - r.raise_for_status() - - with open(str(dest), "wb") as f: - for chunk in r.iter_content(chunk_size=1024): - if chunk: - f.write(chunk) - - def inspect(self, file_path): # type: (Path) -> Dict[str, Union[str, List[str]]] - if file_path.suffix == ".whl": - return self.inspect_wheel(file_path) - - return self.inspect_sdist(file_path) - - def inspect_wheel( - self, file_path - ): # type: (Path) -> Dict[str, Union[str, List[str]]] - info = { - "name": "", - "version": "", - "summary": "", - "requires_python": None, - "requires_dist": [], - } - - try: - meta = pkginfo.Wheel(str(file_path)) - except ValueError: - # Unable to determine dependencies - # Assume none - return info - - if meta.name: - info["name"] = meta.name - - if meta.version: - info["version"] = meta.version - - if meta.summary: - info["summary"] = meta.summary or "" - - info["requires_python"] = meta.requires_python - - if meta.requires_dist: - info["requires_dist"] = meta.requires_dist - - return info - - def inspect_sdist( - self, file_path - ): # type: (Path) -> Dict[str, Union[str, List[str]]] - info = { - "name": "", - "version": "", - "summary": "", - "requires_python": None, - "requires_dist": None, - } - - try: - meta = pkginfo.SDist(str(file_path)) - if meta.name: - info["name"] = meta.name - - if meta.version: - info["version"] = meta.version - - if meta.summary: - info["summary"] = meta.summary - - if meta.requires_python: - info["requires_python"] = meta.requires_python - - if meta.requires_dist: - info["requires_dist"] = list(meta.requires_dist) - - return info - except ValueError: - # Unable to determine dependencies - # We pass and go deeper - pass - - # Still not dependencies found - # So, we unpack and introspect - suffix = file_path.suffix - if suffix == ".zip": - tar = zipfile.ZipFile(str(file_path)) - else: - if suffix == ".bz2": - suffixes = file_path.suffixes - if len(suffixes) > 1 and suffixes[-2] == ".tar": - suffix = ".tar.bz2" - else: - suffix = ".tar.gz" - - tar = tarfile.open(str(file_path)) - - try: - tar.extractall(os.path.join(str(file_path.parent), "unpacked")) - finally: - tar.close() - - unpacked = file_path.parent / "unpacked" - elements = list(unpacked.glob("*")) - if len(elements) == 1 and elements[0].is_dir(): - sdist_dir = elements[0] - else: - sdist_dir = unpacked / file_path.name.rstrip(suffix) - - pyproject = TomlFile(sdist_dir / "pyproject.toml") - if pyproject.exists(): - from poetry.factory import Factory - - pyproject_content = pyproject.read() - if "tool" in pyproject_content and "poetry" in pyproject_content["tool"]: - package = Factory().create_poetry(sdist_dir).package - return { - "name": package.name, - "version": package.version.text, - "summary": package.description, - "requires_dist": [dep.to_pep_508() for dep in package.requires], - "requires_python": package.python_versions, - } - - # Checking for .egg-info at root - eggs = list(sdist_dir.glob("*.egg-info")) - if eggs: - egg_info = eggs[0] - - requires = egg_info / "requires.txt" - if requires.exists(): - with requires.open(encoding="utf-8") as f: - info["requires_dist"] = parse_requires(f.read()) - - return info - - # Searching for .egg-info in sub directories - eggs = list(sdist_dir.glob("**/*.egg-info")) - if eggs: - egg_info = eggs[0] - - requires = egg_info / "requires.txt" - if requires.exists(): - with requires.open(encoding="utf-8") as f: - info["requires_dist"] = parse_requires(f.read()) - - return info - - # Still nothing, try reading (without executing it) - # the setup.py file. - try: - setup_info = self._inspect_sdist_with_setup(sdist_dir) - - for key, value in info.items(): - if value: - continue - - info[key] = setup_info[key] - - return info - except Exception as e: - logger.warning( - "An error occurred when reading setup.py or setup.cfg: {}".format( - str(e) - ) - ) - return info - - def _inspect_sdist_with_setup( - self, sdist_dir - ): # type: (Path) -> Dict[str, Union[str, List[str]]] - info = { - "name": None, - "version": None, - "summary": "", - "requires_python": None, - "requires_dist": None, - } - - result = SetupReader.read_from_directory(sdist_dir) - requires = "" - for dep in result["install_requires"]: - requires += dep + "\n" - - if result["extras_require"]: - requires += "\n" - - for extra_name, deps in result["extras_require"].items(): - requires += "[{}]\n".format(extra_name) - - for dep in deps: - requires += dep + "\n" - - requires += "\n" - - info["name"] = result["name"] - info["version"] = result["version"] - info["requires_dist"] = parse_requires(requires) - info["requires_python"] = result["python_requires"] - - return info diff --git a/poetry/utils/setup_reader.py b/poetry/utils/setup_reader.py index 7056fe47c9b..6af89bc7981 100644 --- a/poetry/utils/setup_reader.py +++ b/poetry/utils/setup_reader.py @@ -183,6 +183,7 @@ def _find_setup_call( func = value.func if not (isinstance(func, ast.Name) and func.id == "setup") and not ( isinstance(func, ast.Attribute) + and hasattr(func.value, "id") and func.value.id == "setuptools" and func.attr == "setup" ): diff --git a/poetry/vcs/__init__.py b/poetry/vcs/__init__.py deleted file mode 100644 index d242ca6c285..00000000000 --- a/poetry/vcs/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -import subprocess -import warnings - -from poetry.utils._compat import Path - -from .git import Git - - -def get_vcs(directory): # type: (Path) -> Git - directory = directory.resolve() - - for p in [directory] + list(directory.parents): - if (p / ".git").is_dir(): - try: - return Git(p) - except (subprocess.CalledProcessError, OSError): - # Either git could not be found or does not exist - warnings.warn( - "git executable could not be found", category=RuntimeWarning - ) - - return diff --git a/poetry/vcs/git.py b/poetry/vcs/git.py deleted file mode 100644 index 791e68dd1af..00000000000 --- a/poetry/vcs/git.py +++ /dev/null @@ -1,283 +0,0 @@ -# -*- coding: utf-8 -*- -import re -import subprocess - -from collections import namedtuple - -from poetry.utils._compat import decode - - -pattern_formats = { - "protocol": r"\w+", - "user": r"[a-zA-Z0-9_.-]+", - "resource": r"[a-zA-Z0-9_.-]+", - "port": r"\d+", - "path": r"[\w~.\-/\\]+", - "name": r"[\w~.\-]+", - "rev": r"[^@#]+", -} - -PATTERNS = [ - re.compile( - r"^(git\+)?" - r"(?Phttps?|git|ssh|rsync|file)://" - r"(?:(?P{user})@)?" - r"(?P{resource})?" - r"(:(?P{port}))?" - r"(?P[:/\\]({path}[/\\])?" - r"((?P{name}?)(\.git|[/\\])?)?)" - r"([@#](?P{rev}))?" - r"$".format( - user=pattern_formats["user"], - resource=pattern_formats["resource"], - port=pattern_formats["port"], - path=pattern_formats["path"], - name=pattern_formats["name"], - rev=pattern_formats["rev"], - ) - ), - re.compile( - r"(git\+)?" - r"((?P{protocol})://)" - r"(?:(?P{user})@)?" - r"(?P{resource}:?)" - r"(:(?P{port}))?" - r"(?P({path})" - r"(?P{name})(\.git|/)?)" - r"([@#](?P{rev}))?" - r"$".format( - protocol=pattern_formats["protocol"], - user=pattern_formats["user"], - resource=pattern_formats["resource"], - port=pattern_formats["port"], - path=pattern_formats["path"], - name=pattern_formats["name"], - rev=pattern_formats["rev"], - ) - ), - re.compile( - r"^(?:(?P{user})@)?" - r"(?P{resource})" - r"(:(?P{port}))?" - r"(?P([:/]{path}/)" - r"(?P{name})(\.git|/)?)" - r"([@#](?P{rev}))?" - r"$".format( - user=pattern_formats["user"], - resource=pattern_formats["resource"], - port=pattern_formats["port"], - path=pattern_formats["path"], - name=pattern_formats["name"], - rev=pattern_formats["rev"], - ) - ), - re.compile( - r"((?P{user})@)?" - r"(?P{resource})" - r"[:/]{{1,2}}" - r"(?P({path})" - r"(?P{name})(\.git|/)?)" - r"([@#](?P{rev}))?" - r"$".format( - user=pattern_formats["user"], - resource=pattern_formats["resource"], - path=pattern_formats["path"], - name=pattern_formats["name"], - rev=pattern_formats["rev"], - ) - ), -] - - -class ParsedUrl: - def __init__(self, protocol, resource, pathname, user, port, name, rev): - self.protocol = protocol - self.resource = resource - self.pathname = pathname - self.user = user - self.port = port - self.name = name - self.rev = rev - - @classmethod - def parse(cls, url): # type: () -> ParsedUrl - for pattern in PATTERNS: - m = pattern.match(url) - if m: - groups = m.groupdict() - return ParsedUrl( - groups.get("protocol"), - groups.get("resource"), - groups.get("pathname"), - groups.get("user"), - groups.get("port"), - groups.get("name"), - groups.get("rev"), - ) - - raise ValueError('Invalid git url "{}"'.format(url)) - - @property - def url(self): # type: () -> str - return "{}{}{}{}{}".format( - "{}://".format(self.protocol) if self.protocol else "", - "{}@".format(self.user) if self.user else "", - self.resource, - ":{}".format(self.port) if self.port else "", - "/" + self.pathname.lstrip(":/"), - ) - - def format(self): - return "{}".format(self.url, "#{}".format(self.rev) if self.rev else "",) - - def __str__(self): # type: () -> str - return self.format() - - -GitUrl = namedtuple("GitUrl", ["url", "revision"]) - - -class GitConfig: - def __init__(self, requires_git_presence=False): - self._config = {} - - try: - config_list = decode( - subprocess.check_output( - ["git", "config", "-l"], stderr=subprocess.STDOUT - ) - ) - - m = re.findall("(?ms)^([^=]+)=(.*?)$", config_list) - if m: - for group in m: - self._config[group[0]] = group[1] - except (subprocess.CalledProcessError, OSError): - if requires_git_presence: - raise - - def get(self, key, default=None): - return self._config.get(key, default) - - def __getitem__(self, item): - return self._config[item] - - -class Git: - def __init__(self, work_dir=None): - self._config = GitConfig(requires_git_presence=True) - self._work_dir = work_dir - - @classmethod - def normalize_url(cls, url): # type: (str) -> GitUrl - parsed = ParsedUrl.parse(url) - - formatted = re.sub(r"^git\+", "", url) - if parsed.rev: - formatted = re.sub(r"[#@]{}$".format(parsed.rev), "", formatted) - - altered = parsed.format() != formatted - - if altered: - if re.match(r"^git\+https?", url) and re.match( - r"^/?:[^0-9]", parsed.pathname - ): - normalized = re.sub(r"git\+(.*:[^:]+):(.*)", "\\1/\\2", url) - elif re.match(r"^git\+file", url): - normalized = re.sub(r"git\+", "", url) - else: - normalized = re.sub(r"^(?:git\+)?ssh://", "", url) - else: - normalized = parsed.format() - - return GitUrl(re.sub(r"#[^#]*$", "", normalized), parsed.rev) - - @property - def config(self): # type: () -> GitConfig - return self._config - - def clone(self, repository, dest): # type: (...) -> str - return self.run("clone", repository, str(dest)) - - def checkout(self, rev, folder=None): # type: (...) -> str - args = [] - if folder is None and self._work_dir: - folder = self._work_dir - - if folder: - args += [ - "--git-dir", - (folder / ".git").as_posix(), - "--work-tree", - folder.as_posix(), - ] - - args += ["checkout", rev] - - return self.run(*args) - - def rev_parse(self, rev, folder=None): # type: (...) -> str - args = [] - if folder is None and self._work_dir: - folder = self._work_dir - - if folder: - args += [ - "--git-dir", - (folder / ".git").as_posix(), - "--work-tree", - folder.as_posix(), - ] - - args += ["rev-parse", rev] - - return self.run(*args) - - def get_ignored_files(self, folder=None): # type: (...) -> list - args = [] - if folder is None and self._work_dir: - folder = self._work_dir - - if folder: - args += [ - "--git-dir", - (folder / ".git").as_posix(), - "--work-tree", - folder.as_posix(), - ] - - args += ["ls-files", "--others", "-i", "--exclude-standard"] - output = self.run(*args) - - return output.strip().split("\n") - - def remote_urls(self, folder=None): # type: (...) -> dict - output = self.run( - "config", "--get-regexp", r"remote\..*\.url", folder=folder - ).strip() - - urls = {} - for url in output.splitlines(): - name, url = url.split(" ", 1) - urls[name.strip()] = url.strip() - - return urls - - def remote_url(self, folder=None): # type: (...) -> str - urls = self.remote_urls(folder=folder) - - return urls.get("remote.origin.url", urls[list(urls.keys())[0]]) - - def run(self, *args, **kwargs): # type: (...) -> str - folder = kwargs.pop("folder", None) - if folder: - args = ( - "--git-dir", - (folder / ".git").as_posix(), - "--work-tree", - folder.as_posix(), - ) + args - - return decode( - subprocess.check_output(["git"] + list(args), stderr=subprocess.STDOUT) - ).strip() diff --git a/poetry/version/__init__.py b/poetry/version/__init__.py index 62d0349fe3a..e69de29bb2d 100644 --- a/poetry/version/__init__.py +++ b/poetry/version/__init__.py @@ -1,45 +0,0 @@ -import operator - -from typing import Union - -from .exceptions import InvalidVersion -from .legacy_version import LegacyVersion -from .version import Version - - -OP_EQ = operator.eq -OP_LT = operator.lt -OP_LE = operator.le -OP_GT = operator.gt -OP_GE = operator.ge -OP_NE = operator.ne - -_trans_op = { - "=": OP_EQ, - "==": OP_EQ, - "<": OP_LT, - "<=": OP_LE, - ">": OP_GT, - ">=": OP_GE, - "!=": OP_NE, -} - - -def parse( - version, # type: str - strict=False, # type: bool -): # type:(...) -> Union[Version, LegacyVersion] - """ - Parse the given version string and return either a :class:`Version` object - or a LegacyVersion object depending on if the given version is - a valid PEP 440 version or a legacy version. - - If strict=True only PEP 440 versions will be accepted. - """ - try: - return Version(version) - except InvalidVersion: - if strict: - raise - - return LegacyVersion(version) diff --git a/poetry/version/base.py b/poetry/version/base.py deleted file mode 100644 index b2281c90b71..00000000000 --- a/poetry/version/base.py +++ /dev/null @@ -1,27 +0,0 @@ -class BaseVersion: - def __hash__(self): - return hash(self._key) - - def __lt__(self, other): - return self._compare(other, lambda s, o: s < o) - - def __le__(self, other): - return self._compare(other, lambda s, o: s <= o) - - def __eq__(self, other): - return self._compare(other, lambda s, o: s == o) - - def __ge__(self, other): - return self._compare(other, lambda s, o: s >= o) - - def __gt__(self, other): - return self._compare(other, lambda s, o: s > o) - - def __ne__(self, other): - return self._compare(other, lambda s, o: s != o) - - def _compare(self, other, method): - if not isinstance(other, BaseVersion): - return NotImplemented - - return method(self._key, other._key) diff --git a/poetry/version/exceptions.py b/poetry/version/exceptions.py deleted file mode 100644 index 741b13ca1fd..00000000000 --- a/poetry/version/exceptions.py +++ /dev/null @@ -1,3 +0,0 @@ -class InvalidVersion(ValueError): - - pass diff --git a/poetry/version/helpers.py b/poetry/version/helpers.py deleted file mode 100644 index 1939f8e0571..00000000000 --- a/poetry/version/helpers.py +++ /dev/null @@ -1,57 +0,0 @@ -from poetry.semver import Version -from poetry.semver import VersionUnion -from poetry.semver import parse_constraint - - -PYTHON_VERSION = [ - "2.7.*", - "3.0.*", - "3.1.*", - "3.2.*", - "3.3.*", - "3.4.*", - "3.5.*", - "3.6.*", - "3.7.*", - "3.8.*", -] - - -def format_python_constraint(constraint): - """ - This helper will help in transforming - disjunctive constraint into proper constraint. - """ - if isinstance(constraint, Version): - if constraint.precision >= 3: - return "=={}".format(str(constraint)) - - # Transform 3.6 or 3 - if constraint.precision == 2: - # 3.6 - constraint = parse_constraint( - "~{}.{}".format(constraint.major, constraint.minor) - ) - else: - constraint = parse_constraint("^{}.0".format(constraint.major)) - - if not isinstance(constraint, VersionUnion): - return str(constraint) - - formatted = [] - accepted = [] - - for version in PYTHON_VERSION: - version_constraint = parse_constraint(version) - matches = constraint.allows_any(version_constraint) - if not matches: - formatted.append("!=" + version) - else: - accepted.append(version) - - # Checking lower bound - low = accepted[0] - - formatted.insert(0, ">=" + ".".join(low.split(".")[:2])) - - return ", ".join(formatted) diff --git a/poetry/version/legacy_version.py b/poetry/version/legacy_version.py deleted file mode 100644 index db6a11b6274..00000000000 --- a/poetry/version/legacy_version.py +++ /dev/null @@ -1,90 +0,0 @@ -import re - -from .base import BaseVersion - - -class LegacyVersion(BaseVersion): - def __init__(self, version): - self._version = str(version) - self._key = _legacy_cmpkey(self._version) - - def __str__(self): - return self._version - - def __repr__(self): - return "".format(repr(str(self))) - - @property - def public(self): - return self._version - - @property - def base_version(self): - return self._version - - @property - def local(self): - return None - - @property - def is_prerelease(self): - return False - - @property - def is_postrelease(self): - return False - - -_legacy_version_component_re = re.compile(r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE) - -_legacy_version_replacement_map = { - "pre": "c", - "preview": "c", - "-": "final-", - "rc": "c", - "dev": "@", -} - - -def _parse_version_parts(s): - for part in _legacy_version_component_re.split(s): - part = _legacy_version_replacement_map.get(part, part) - - if not part or part == ".": - continue - - if part[:1] in "0123456789": - # pad for numeric comparison - yield part.zfill(8) - else: - yield "*" + part - - # ensure that alpha/beta/candidate are before final - yield "*final" - - -def _legacy_cmpkey(version): - # We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch - # greater than or equal to 0. This will effectively put the LegacyVersion, - # which uses the defacto standard originally implemented by setuptools, - # as before all PEP 440 versions. - epoch = -1 - - # This scheme is taken from pkg_resources.parse_version setuptools prior to - # it's adoption of the packaging library. - parts = [] - for part in _parse_version_parts(version.lower()): - if part.startswith("*"): - # remove "-" before a prerelease tag - if part < "*final": - while parts and parts[-1] == "*final-": - parts.pop() - - # remove trailing zeros from each series of numeric parts - while parts and parts[-1] == "00000000": - parts.pop() - - parts.append(part) - parts = tuple(parts) - - return epoch, parts diff --git a/poetry/version/markers.py b/poetry/version/markers.py deleted file mode 100644 index bc4219a33d6..00000000000 --- a/poetry/version/markers.py +++ /dev/null @@ -1,763 +0,0 @@ -import re - -from typing import Any -from typing import Dict -from typing import Iterator -from typing import List - -from pyparsing import Forward -from pyparsing import Group -from pyparsing import Literal as L # noqa -from pyparsing import ParseResults -from pyparsing import QuotedString -from pyparsing import ZeroOrMore -from pyparsing import stringEnd -from pyparsing import stringStart - - -class InvalidMarker(ValueError): - """ - An invalid marker was found, users should refer to PEP 508. - """ - - -class UndefinedComparison(ValueError): - """ - An invalid operation was attempted on a value that doesn't support it. - """ - - -class UndefinedEnvironmentName(ValueError): - """ - A name was attempted to be used that does not exist inside of the - environment. - """ - - -class Node(object): - def __init__(self, value): - self.value = value - - def __str__(self): - return str(self.value) - - def __repr__(self): - return "<{0}({1!r})>".format(self.__class__.__name__, str(self)) - - def serialize(self): - raise NotImplementedError - - -class Variable(Node): - def serialize(self): - return str(self) - - -class Value(Node): - def serialize(self): - return '"{0}"'.format(self) - - -class Op(Node): - def serialize(self): - return str(self) - - -VARIABLE = ( - L("implementation_version") - | L("platform_python_implementation") - | L("implementation_name") - | L("python_full_version") - | L("platform_release") - | L("platform_version") - | L("platform_machine") - | L("platform_system") - | L("python_version") - | L("sys_platform") - | L("os_name") - | L("os.name") - | L("sys.platform") # PEP-345 - | L("platform.version") # PEP-345 - | L("platform.machine") # PEP-345 - | L("platform.python_implementation") # PEP-345 - | L("python_implementation") # PEP-345 - | L("extra") # undocumented setuptools legacy -) -ALIASES = { - "os.name": "os_name", - "sys.platform": "sys_platform", - "platform.version": "platform_version", - "platform.machine": "platform_machine", - "platform.python_implementation": "platform_python_implementation", - "python_implementation": "platform_python_implementation", -} -VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0]))) - -VERSION_CMP = ( - L("===") | L("==") | L(">=") | L("<=") | L("!=") | L("~=") | L(">") | L("<") -) - -MARKER_OP = VERSION_CMP | L("not in") | L("in") -MARKER_OP.setParseAction(lambda s, l, t: Op(t[0])) - -MARKER_VALUE = QuotedString("'") | QuotedString('"') -MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0])) - -BOOLOP = L("and") | L("or") - -MARKER_VAR = VARIABLE | MARKER_VALUE - -MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR) -MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0])) - -LPAREN = L("(").suppress() -RPAREN = L(")").suppress() - -MARKER_EXPR = Forward() -MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN) -MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR) - -MARKER = stringStart + MARKER_EXPR + stringEnd - - -_undefined = object() - - -def _coerce_parse_result(results): - if isinstance(results, ParseResults): - return [_coerce_parse_result(i) for i in results] - else: - return results - - -def _format_marker(marker, first=True): - assert isinstance(marker, (list, tuple, str)) - - # Sometimes we have a structure like [[...]] which is a single item list - # where the single item is itself it's own list. In that case we want skip - # the rest of this function so that we don't get extraneous () on the - # outside. - if ( - isinstance(marker, list) - and len(marker) == 1 - and isinstance(marker[0], (list, tuple)) - ): - return _format_marker(marker[0]) - - if isinstance(marker, list): - inner = (_format_marker(m, first=False) for m in marker) - if first: - return " ".join(inner) - else: - return "(" + " ".join(inner) + ")" - elif isinstance(marker, tuple): - return " ".join([m.serialize() for m in marker]) - else: - return marker - - -class BaseMarker(object): - def intersect(self, other): # type: (BaseMarker) -> BaseMarker - raise NotImplementedError() - - def union(self, other): # type: (BaseMarker) -> BaseMarker - raise NotImplementedError() - - def is_any(self): # type: () -> bool - return False - - def is_empty(self): # type: () -> bool - return False - - def validate(self, environment): # type: (Dict[str, Any]) -> bool - raise NotImplementedError() - - def without_extras(self): # type: () -> BaseMarker - raise NotImplementedError() - - def exclude(self, marker_name): # type: (str) -> BaseMarker - raise NotImplementedError() - - def only(self, marker_name): # type: (str) -> BaseMarker - raise NotImplementedError() - - def __repr__(self): - return "<{} {}>".format(self.__class__.__name__, str(self)) - - -class AnyMarker(BaseMarker): - def intersect(self, other): - return other - - def union(self, other): - return self - - def is_any(self): - return True - - def is_empty(self): # type: () -> bool - return False - - def validate(self, environment): - return True - - def without_extras(self): - return self - - def exclude(self, marker_name): # type: (str) -> AnyMarker - return self - - def only(self, marker_name): # type: (str) -> AnyMarker - return self - - def __str__(self): - return "" - - def __repr__(self): - return "" - - def __hash__(self): - return hash(("", "")) - - def __eq__(self, other): - if not isinstance(other, BaseMarker): - return NotImplemented - - return isinstance(other, AnyMarker) - - -class EmptyMarker(BaseMarker): - def intersect(self, other): - return self - - def union(self, other): - return other - - def is_any(self): - return False - - def is_empty(self): # type: () -> bool - return True - - def validate(self, environment): - return False - - def without_extras(self): - return self - - def exclude(self, marker_name): # type: (str) -> EmptyMarker - return self - - def only(self, marker_name): # type: (str) -> EmptyMarker - return self - - def __str__(self): - return "" - - def __repr__(self): - return "" - - def __hash__(self): - return hash(("", "")) - - def __eq__(self, other): - if not isinstance(other, BaseMarker): - return NotImplemented - - return isinstance(other, EmptyMarker) - - -class SingleMarker(BaseMarker): - - _CONSTRAINT_RE = re.compile(r"(?i)^(~=|!=|>=?|<=?|==?|in|not in)?\s*(.+)$") - _VERSION_LIKE_MARKER_NAME = {"python_version", "platform_release"} - - def __init__(self, name, constraint): - from poetry.packages.constraints import ( - parse_constraint as parse_generic_constraint, - ) - from poetry.semver import parse_constraint - - self._name = name - self._constraint_string = str(constraint) - - # Extract operator and value - m = self._CONSTRAINT_RE.match(self._constraint_string) - self._operator = m.group(1) - if self._operator is None: - self._operator = "==" - - self._value = m.group(2) - self._parser = parse_generic_constraint - - if name in self._VERSION_LIKE_MARKER_NAME: - self._parser = parse_constraint - - if self._operator in {"in", "not in"}: - versions = [] - for v in re.split("[ ,]+", self._value): - split = v.split(".") - if len(split) in [1, 2]: - split.append("*") - op = "" if self._operator == "in" else "!=" - else: - op = "==" if self._operator == "in" else "!=" - - versions.append(op + ".".join(split)) - - glue = ", " - if self._operator == "in": - glue = " || " - - self._constraint = self._parser(glue.join(versions)) - else: - self._constraint = self._parser(self._constraint_string) - else: - self._constraint = self._parser(self._constraint_string) - - @property - def name(self): - return self._name - - @property - def constraint_string(self): - if self._operator in {"in", "not in"}: - return "{} {}".format(self._operator, self._value) - - return self._constraint_string - - @property - def constraint(self): - return self._constraint - - @property - def operator(self): - return self._operator - - @property - def value(self): - return self._value - - def intersect(self, other): - if isinstance(other, SingleMarker): - if other.name != self.name: - return MultiMarker(self, other) - - if self == other: - return self - - if self._operator in {"in", "not in"} or other.operator in {"in", "not in"}: - return MultiMarker.of(self, other) - - new_constraint = self._constraint.intersect(other.constraint) - if new_constraint.is_empty(): - return EmptyMarker() - - if new_constraint == self._constraint or new_constraint == other.constraint: - return SingleMarker(self._name, new_constraint) - - return MultiMarker.of(self, other) - - return other.intersect(self) - - def union(self, other): - if isinstance(other, SingleMarker): - if self == other: - return self - - return MarkerUnion.of(self, other) - - return other.union(self) - - def validate(self, environment): - if environment is None: - return True - - if self._name not in environment: - return True - - return self._constraint.allows(self._parser(environment[self._name])) - - def without_extras(self): - return self.exclude("extra") - - def exclude(self, marker_name): # type: (str) -> BaseMarker - if self.name == marker_name: - return AnyMarker() - - return self - - def only(self, marker_name): # type: (str) -> BaseMarker - if self.name != marker_name: - return EmptyMarker() - - return self - - def __eq__(self, other): - if not isinstance(other, SingleMarker): - return False - - return self._name == other.name and self._constraint == other.constraint - - def __hash__(self): - return hash((self._name, self._constraint_string)) - - def __str__(self): - return _format_marker( - (Variable(self._name), Op(self._operator), Value(self._value)) - ) - - -def _flatten_markers( - markers, flatten_class -): # type: (Iterator[BaseMarker], Any) -> List[BaseMarker] - flattened = [] - - for marker in markers: - if isinstance(marker, flatten_class): - flattened += _flatten_markers(marker.markers, flatten_class) - else: - flattened.append(marker) - - return flattened - - -class MultiMarker(BaseMarker): - def __init__(self, *markers): - self._markers = [] - - markers = _flatten_markers(markers, MultiMarker) - - for m in markers: - self._markers.append(m) - - @classmethod - def of(cls, *markers): - new_markers = [] - markers = _flatten_markers(markers, MultiMarker) - - for marker in markers: - if marker in new_markers: - continue - - if isinstance(marker, SingleMarker): - intersected = False - for i, mark in enumerate(new_markers): - if ( - not isinstance(mark, SingleMarker) - or isinstance(mark, SingleMarker) - and mark.name != marker.name - ): - continue - - intersection = mark.constraint.intersect(marker.constraint) - if intersection == mark.constraint: - intersected = True - elif intersection == marker.constraint: - new_markers[i] = marker - intersected = True - elif intersection.is_empty(): - return EmptyMarker() - - if intersected: - continue - - new_markers.append(marker) - - if any(m.is_empty() for m in new_markers) or not new_markers: - return EmptyMarker() - - if len(new_markers) == 1 and new_markers[0].is_any(): - return AnyMarker() - - return MultiMarker(*new_markers) - - @property - def markers(self): - return self._markers - - def intersect(self, other): - if other.is_any(): - return self - - if other.is_empty(): - return other - - new_markers = self._markers + [other] - - return MultiMarker.of(*new_markers) - - def union(self, other): - if isinstance(other, (SingleMarker, MultiMarker)): - return MarkerUnion.of(self, other) - - return other.union(self) - - def validate(self, environment): - for m in self._markers: - if not m.validate(environment): - return False - - return True - - def without_extras(self): - return self.exclude("extra") - - def exclude(self, marker_name): # type: (str) -> BaseMarker - new_markers = [] - - for m in self._markers: - if isinstance(m, SingleMarker) and m.name == marker_name: - # The marker is not relevant since it must be excluded - continue - - marker = m.exclude(marker_name) - - if not marker.is_empty(): - new_markers.append(marker) - - return self.of(*new_markers) - - def only(self, marker_name): # type: (str) -> BaseMarker - new_markers = [] - - for m in self._markers: - if isinstance(m, SingleMarker) and m.name != marker_name: - # The marker is not relevant since it's not one we want - continue - - marker = m.only(marker_name) - - if not marker.is_empty(): - new_markers.append(marker) - - return self.of(*new_markers) - - def __eq__(self, other): - if not isinstance(other, MultiMarker): - return False - - return set(self._markers) == set(other.markers) - - def __hash__(self): - h = hash("multi") - for m in self._markers: - h |= hash(m) - - return h - - def __str__(self): - elements = [] - for m in self._markers: - if isinstance(m, SingleMarker): - elements.append(str(m)) - elif isinstance(m, MultiMarker): - elements.append(str(m)) - else: - elements.append("({})".format(str(m))) - - return " and ".join(elements) - - -class MarkerUnion(BaseMarker): - def __init__(self, *markers): - self._markers = list(markers) - - @property - def markers(self): - return self._markers - - @classmethod - def of(cls, *markers): # type: (tuple) -> MarkerUnion - flattened_markers = _flatten_markers(markers, MarkerUnion) - - markers = [] - for marker in flattened_markers: - if marker in markers: - continue - - if isinstance(marker, SingleMarker) and marker.name == "python_version": - intersected = False - for i, mark in enumerate(markers): - if ( - not isinstance(mark, SingleMarker) - or isinstance(mark, SingleMarker) - and mark.name != marker.name - ): - continue - - intersection = mark.constraint.union(marker.constraint) - if intersection == mark.constraint: - intersected = True - break - elif intersection == marker.constraint: - markers[i] = marker - intersected = True - break - - if intersected: - continue - - markers.append(marker) - - if any(m.is_any() for m in markers): - return AnyMarker() - - return MarkerUnion(*markers) - - def append(self, marker): - if marker in self._markers: - return - - self._markers.append(marker) - - def intersect(self, other): - if other.is_any(): - return self - - if other.is_empty(): - return other - - new_markers = [] - if isinstance(other, (SingleMarker, MultiMarker)): - for marker in self._markers: - intersection = marker.intersect(other) - - if not intersection.is_empty(): - new_markers.append(intersection) - elif isinstance(other, MarkerUnion): - for our_marker in self._markers: - for their_marker in other.markers: - intersection = our_marker.intersect(their_marker) - - if not intersection.is_empty(): - new_markers.append(intersection) - - return MarkerUnion.of(*new_markers) - - def union(self, other): - if other.is_any(): - return other - - if other.is_empty(): - return self - - new_markers = self._markers + [other] - - return MarkerUnion.of(*new_markers) - - def validate(self, environment): - for m in self._markers: - if m.validate(environment): - return True - - return False - - def without_extras(self): - return self.exclude("extra") - - def exclude(self, marker_name): # type: (str) -> BaseMarker - new_markers = [] - - for m in self._markers: - if isinstance(m, SingleMarker) and m.name == marker_name: - # The marker is not relevant since it must be excluded - continue - - marker = m.exclude(marker_name) - - if not marker.is_empty(): - new_markers.append(marker) - - return self.of(*new_markers) - - def only(self, marker_name): # type: (str) -> BaseMarker - new_markers = [] - - for m in self._markers: - if isinstance(m, SingleMarker) and m.name != marker_name: - # The marker is not relevant since it's not one we want - continue - - marker = m.only(marker_name) - - if not marker.is_empty(): - new_markers.append(marker) - - return self.of(*new_markers) - - def __eq__(self, other): - if not isinstance(other, MarkerUnion): - return False - - return set(self._markers) == set(other.markers) - - def __hash__(self): - h = hash("union") - for m in self._markers: - h |= hash(m) - - return h - - def __str__(self): - return " or ".join( - str(m) for m in self._markers if not m.is_any() and not m.is_empty() - ) - - def is_any(self): - return any(m.is_any() for m in self._markers) - - def is_empty(self): - return all(m.is_empty() for m in self._markers) - - -def parse_marker(marker): - if marker == "": - return EmptyMarker() - - if not marker or marker == "*": - return AnyMarker() - - markers = _coerce_parse_result(MARKER.parseString(marker)) - - return _compact_markers(markers) - - -def _compact_markers(markers): - groups = [MultiMarker()] - - for marker in markers: - if isinstance(marker, list): - groups[-1] = MultiMarker.of(groups[-1], _compact_markers(marker)) - elif isinstance(marker, tuple): - lhs, op, rhs = marker - - if isinstance(lhs, Variable): - name = lhs.value - value = rhs.value - else: - value = lhs.value - name = rhs.value - - groups[-1] = MultiMarker.of( - groups[-1], SingleMarker(name, "{}{}".format(op, value)) - ) - else: - if marker == "or": - groups.append(MultiMarker()) - - for i, group in enumerate(reversed(groups)): - if group.is_empty(): - del groups[len(groups) - 1 - i] - continue - - if isinstance(group, MultiMarker) and len(group.markers) == 1: - groups[len(groups) - 1 - i] = group.markers[0] - - if not groups: - return EmptyMarker() - - if len(groups) == 1: - return groups[0] - - return MarkerUnion.of(*groups) diff --git a/poetry/version/requirements.py b/poetry/version/requirements.py deleted file mode 100644 index 8364626e084..00000000000 --- a/poetry/version/requirements.py +++ /dev/null @@ -1,255 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import re -import string - -from pyparsing import Combine -from pyparsing import Literal as L # noqa -from pyparsing import Optional -from pyparsing import ParseException -from pyparsing import Regex -from pyparsing import Word -from pyparsing import ZeroOrMore -from pyparsing import originalTextFor -from pyparsing import stringEnd -from pyparsing import stringStart - -from poetry.semver import parse_constraint - -from .markers import MARKER_EXPR -from .markers import parse_marker - - -try: - import urllib.parse as urlparse -except ImportError: - import urlparse - - -LEGACY_REGEX = r""" - (?P(==|!=|<=|>=|<|>)) - \s* - (?P - [^,;\s)]* # Since this is a "legacy" specifier, and the version - # string can be just about anything, we match everything - # except for whitespace, a semi-colon for marker support, - # a closing paren since versions can be enclosed in - # them, and a comma since it's a version separator. - ) - """ - - -REGEX = r""" - (?P(~=|==|!=|<=|>=|<|>|===)) - (?P - (?: - # The identity operators allow for an escape hatch that will - # do an exact string match of the version you wish to install. - # This will not be parsed by PEP 440 and we cannot determine - # any semantic meaning from it. This operator is discouraged - # but included entirely as an escape hatch. - (?<====) # Only match for the identity operator - \s* - [^\s]* # We just match everything, except for whitespace - # since we are only testing for strict identity. - ) - | - (?: - # The (non)equality operators allow for wild card and local - # versions to be specified so we have to define these two - # operators separately to enable that. - (?<===|!=) # Only match for equals and not equals - - \s* - v? - (?:[0-9]+!)? # epoch - [0-9]+(?:\.[0-9]+)* # release - (?: # pre release - [-_\.]? - (a|b|c|rc|alpha|beta|pre|preview) - [-_\.]? - [0-9]* - )? - (?: # post release - (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) - )? - - # You cannot use a wild card and a dev or local version - # together so group them with a | and make them optional. - (?: - (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release - (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local - | - \.\* # Wild card syntax of .* - )? - ) - | - (?: - # The compatible operator requires at least two digits in the - # release segment. - (?<=~=) # Only match for the compatible operator - - \s* - v? - (?:[0-9]+!)? # epoch - [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) - (?: # pre release - [-_\.]? - (a|b|c|rc|alpha|beta|pre|preview) - [-_\.]? - [0-9]* - )? - (?: # post release - (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) - )? - (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release - ) - | - (?: - # All other operators only allow a sub set of what the - # (non)equality operators do. Specifically they do not allow - # local versions to be specified nor do they allow the prefix - # matching wild cards. - (?".format(str(self)) diff --git a/poetry/version/specifiers.py b/poetry/version/specifiers.py deleted file mode 100644 index a81516d4524..00000000000 --- a/poetry/version/specifiers.py +++ /dev/null @@ -1,795 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import abc -import functools -import itertools -import re -import sys - -from .legacy_version import LegacyVersion -from .version import Version - - -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] == 3 - -# flake8: noqa - -if PY3: - string_types = (str,) -else: - string_types = (basestring,) - - -def with_metaclass(meta, *bases): - """ - Create a base class with a metaclass. - """ - # This requires a bit of explanation: the basic idea is to make a dummy - # metaclass for one level of class instantiation that replaces itself with - # the actual metaclass. - class metaclass(meta): - def __new__(cls, name, this_bases, d): - return meta(name, bases, d) - - return type.__new__(metaclass, "temporary_class", (), {}) - - -def parse(version): - """ - Parse the given version string and return either a :class:`Version` object - or a :class:`LegacyVersion` object depending on if the given version is - a valid PEP 440 version or a legacy version. - """ - try: - return Version(version) - except InvalidVersion: - return LegacyVersion(version) - - -class InvalidVersion(ValueError): - """ - An invalid version was found, users should refer to PEP 440. - """ - - -class InvalidSpecifier(ValueError): - """ - An invalid specifier was found, users should refer to PEP 440. - """ - - -class BaseSpecifier(with_metaclass(abc.ABCMeta, object)): - @abc.abstractmethod - def __str__(self): - """ - Returns the str representation of this Specifier like object. This - should be representative of the Specifier itself. - """ - - @abc.abstractmethod - def __hash__(self): - """ - Returns a hash value for this Specifier like object. - """ - - @abc.abstractmethod - def __eq__(self, other): - """ - Returns a boolean representing whether or not the two Specifier like - objects are equal. - """ - - @abc.abstractmethod - def __ne__(self, other): - """ - Returns a boolean representing whether or not the two Specifier like - objects are not equal. - """ - - @abc.abstractproperty - def prereleases(self): - """ - Returns whether or not pre-releases as a whole are allowed by this - specifier. - """ - - @prereleases.setter - def prereleases(self, value): - """ - Sets whether or not pre-releases as a whole are allowed by this - specifier. - """ - - @abc.abstractmethod - def contains(self, item, prereleases=None): - """ - Determines if the given item is contained within this specifier. - """ - - @abc.abstractmethod - def filter(self, iterable, prereleases=None): - """ - Takes an iterable of items and filters them so that only items which - are contained within this specifier are allowed in it. - """ - - -class _IndividualSpecifier(BaseSpecifier): - - _operators = {} - - def __init__(self, spec="", prereleases=None): - match = self._regex.search(spec) - if not match: - raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec)) - - self._spec = (match.group("operator").strip(), match.group("version").strip()) - - # Store whether or not this Specifier should accept prereleases - self._prereleases = prereleases - - def __repr__(self): - pre = ( - ", prereleases={0!r}".format(self.prereleases) - if self._prereleases is not None - else "" - ) - - return "<{0}({1!r}{2})>".format(self.__class__.__name__, str(self), pre) - - def __str__(self): - return "{0}{1}".format(*self._spec) - - def __hash__(self): - return hash(self._spec) - - def __eq__(self, other): - if isinstance(other, string_types): - try: - other = self.__class__(other) - except InvalidSpecifier: - return NotImplemented - elif not isinstance(other, self.__class__): - return NotImplemented - - return self._spec == other._spec - - def __ne__(self, other): - if isinstance(other, string_types): - try: - other = self.__class__(other) - except InvalidSpecifier: - return NotImplemented - elif not isinstance(other, self.__class__): - return NotImplemented - - return self._spec != other._spec - - def _get_operator(self, op): - return getattr(self, "_compare_{0}".format(self._operators[op])) - - def _coerce_version(self, version): - if not isinstance(version, (LegacyVersion, Version)): - version = parse(version) - return version - - @property - def operator(self): - return self._spec[0] - - @property - def version(self): - return self._spec[1] - - @property - def prereleases(self): - return self._prereleases - - @prereleases.setter - def prereleases(self, value): - self._prereleases = value - - def __contains__(self, item): - return self.contains(item) - - def contains(self, item, prereleases=None): - # Determine if prereleases are to be allowed or not. - if prereleases is None: - prereleases = self.prereleases - - # Normalize item to a Version or LegacyVersion, this allows us to have - # a shortcut for ``"2.0" in Specifier(">=2") - item = self._coerce_version(item) - - # Determine if we should be supporting prereleases in this specifier - # or not, if we do not support prereleases than we can short circuit - # logic if this version is a prereleases. - if item.is_prerelease and not prereleases: - return False - - # Actually do the comparison to determine if this item is contained - # within this Specifier or not. - return self._get_operator(self.operator)(item, self.version) - - def filter(self, iterable, prereleases=None): - yielded = False - found_prereleases = [] - - kw = {"prereleases": prereleases if prereleases is not None else True} - - # Attempt to iterate over all the values in the iterable and if any of - # them match, yield them. - for version in iterable: - parsed_version = self._coerce_version(version) - - if self.contains(parsed_version, **kw): - # If our version is a prerelease, and we were not set to allow - # prereleases, then we'll store it for later incase nothing - # else matches this specifier. - if parsed_version.is_prerelease and not ( - prereleases or self.prereleases - ): - found_prereleases.append(version) - # Either this is not a prerelease, or we should have been - # accepting prereleases from the beginning. - else: - yielded = True - yield version - - # Now that we've iterated over everything, determine if we've yielded - # any values, and if we have not and we have any prereleases stored up - # then we will go ahead and yield the prereleases. - if not yielded and found_prereleases: - for version in found_prereleases: - yield version - - -class LegacySpecifier(_IndividualSpecifier): - - _regex_str = r""" - (?P(==|!=|<=|>=|<|>)) - \s* - (?P - [^,;\s)]* # Since this is a "legacy" specifier, and the version - # string can be just about anything, we match everything - # except for whitespace, a semi-colon for marker support, - # a closing paren since versions can be enclosed in - # them, and a comma since it's a version separator. - ) - """ - - _regex = re.compile(r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) - - _operators = { - "==": "equal", - "!=": "not_equal", - "<=": "less_than_equal", - ">=": "greater_than_equal", - "<": "less_than", - ">": "greater_than", - } - - def _coerce_version(self, version): - if not isinstance(version, LegacyVersion): - version = LegacyVersion(str(version)) - return version - - def _compare_equal(self, prospective, spec): - return prospective == self._coerce_version(spec) - - def _compare_not_equal(self, prospective, spec): - return prospective != self._coerce_version(spec) - - def _compare_less_than_equal(self, prospective, spec): - return prospective <= self._coerce_version(spec) - - def _compare_greater_than_equal(self, prospective, spec): - return prospective >= self._coerce_version(spec) - - def _compare_less_than(self, prospective, spec): - return prospective < self._coerce_version(spec) - - def _compare_greater_than(self, prospective, spec): - return prospective > self._coerce_version(spec) - - -def _require_version_compare(fn): - @functools.wraps(fn) - def wrapped(self, prospective, spec): - if not isinstance(prospective, Version): - return False - return fn(self, prospective, spec) - - return wrapped - - -class Specifier(_IndividualSpecifier): - - _regex_str = r""" - (?P(~=|==|!=|<=|>=|<|>|===)) - (?P - (?: - # The identity operators allow for an escape hatch that will - # do an exact string match of the version you wish to install. - # This will not be parsed by PEP 440 and we cannot determine - # any semantic meaning from it. This operator is discouraged - # but included entirely as an escape hatch. - (?<====) # Only match for the identity operator - \s* - [^\s]* # We just match everything, except for whitespace - # since we are only testing for strict identity. - ) - | - (?: - # The (non)equality operators allow for wild card and local - # versions to be specified so we have to define these two - # operators separately to enable that. - (?<===|!=) # Only match for equals and not equals - - \s* - v? - (?:[0-9]+!)? # epoch - [0-9]+(?:\.[0-9]+)* # release - (?: # pre release - [-_\.]? - (a|b|c|rc|alpha|beta|pre|preview) - [-_\.]? - [0-9]* - )? - (?: # post release - (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) - )? - - # You cannot use a wild card and a dev or local version - # together so group them with a | and make them optional. - (?: - (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release - (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local - | - \.\* # Wild card syntax of .* - )? - ) - | - (?: - # The compatible operator requires at least two digits in the - # release segment. - (?<=~=) # Only match for the compatible operator - - \s* - v? - (?:[0-9]+!)? # epoch - [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) - (?: # pre release - [-_\.]? - (a|b|c|rc|alpha|beta|pre|preview) - [-_\.]? - [0-9]* - )? - (?: # post release - (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) - )? - (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release - ) - | - (?: - # All other operators only allow a sub set of what the - # (non)equality operators do. Specifically they do not allow - # local versions to be specified nor do they allow the prefix - # matching wild cards. - (?=": "greater_than_equal", - "<": "less_than", - ">": "greater_than", - "===": "arbitrary", - } - - @_require_version_compare - def _compare_compatible(self, prospective, spec): - # Compatible releases have an equivalent combination of >= and ==. That - # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to - # implement this in terms of the other specifiers instead of - # implementing it ourselves. The only thing we need to do is construct - # the other specifiers. - - # We want everything but the last item in the version, but we want to - # ignore post and dev releases and we want to treat the pre-release as - # it's own separate segment. - prefix = ".".join( - list( - itertools.takewhile( - lambda x: (not x.startswith("post") and not x.startswith("dev")), - _version_split(spec), - ) - )[:-1] - ) - - # Add the prefix notation to the end of our string - prefix += ".*" - - return self._get_operator(">=")(prospective, spec) and self._get_operator("==")( - prospective, prefix - ) - - @_require_version_compare - def _compare_equal(self, prospective, spec): - # We need special logic to handle prefix matching - if spec.endswith(".*"): - # In the case of prefix matching we want to ignore local segment. - prospective = Version(prospective.public) - # Split the spec out by dots, and pretend that there is an implicit - # dot in between a release segment and a pre-release segment. - spec = _version_split(spec[:-2]) # Remove the trailing .* - - # Split the prospective version out by dots, and pretend that there - # is an implicit dot in between a release segment and a pre-release - # segment. - prospective = _version_split(str(prospective)) - - # Shorten the prospective version to be the same length as the spec - # so that we can determine if the specifier is a prefix of the - # prospective version or not. - prospective = prospective[: len(spec)] - - # Pad out our two sides with zeros so that they both equal the same - # length. - spec, prospective = _pad_version(spec, prospective) - else: - # Convert our spec string into a Version - spec = Version(spec) - - # If the specifier does not have a local segment, then we want to - # act as if the prospective version also does not have a local - # segment. - if not spec.local: - prospective = Version(prospective.public) - - return prospective == spec - - @_require_version_compare - def _compare_not_equal(self, prospective, spec): - return not self._compare_equal(prospective, spec) - - @_require_version_compare - def _compare_less_than_equal(self, prospective, spec): - return prospective <= Version(spec) - - @_require_version_compare - def _compare_greater_than_equal(self, prospective, spec): - return prospective >= Version(spec) - - @_require_version_compare - def _compare_less_than(self, prospective, spec): - # Convert our spec to a Version instance, since we'll want to work with - # it as a version. - spec = Version(spec) - - # Check to see if the prospective version is less than the spec - # version. If it's not we can short circuit and just return False now - # instead of doing extra unneeded work. - if not prospective < spec: - return False - - # This special case is here so that, unless the specifier itself - # includes is a pre-release version, that we do not accept pre-release - # versions for the version mentioned in the specifier (e.g. <3.1 should - # not match 3.1.dev0, but should match 3.0.dev0). - if not spec.is_prerelease and prospective.is_prerelease: - if Version(prospective.base_version) == Version(spec.base_version): - return False - - # If we've gotten to here, it means that prospective version is both - # less than the spec version *and* it's not a pre-release of the same - # version in the spec. - return True - - @_require_version_compare - def _compare_greater_than(self, prospective, spec): - # Convert our spec to a Version instance, since we'll want to work with - # it as a version. - spec = Version(spec) - - # Check to see if the prospective version is greater than the spec - # version. If it's not we can short circuit and just return False now - # instead of doing extra unneeded work. - if not prospective > spec: - return False - - # This special case is here so that, unless the specifier itself - # includes is a post-release version, that we do not accept - # post-release versions for the version mentioned in the specifier - # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0). - if not spec.is_postrelease and prospective.is_postrelease: - if Version(prospective.base_version) == Version(spec.base_version): - return False - - # Ensure that we do not allow a local version of the version mentioned - # in the specifier, which is technically greater than, to match. - if prospective.local is not None: - if Version(prospective.base_version) == Version(spec.base_version): - return False - - # If we've gotten to here, it means that prospective version is both - # greater than the spec version *and* it's not a pre-release of the - # same version in the spec. - return True - - def _compare_arbitrary(self, prospective, spec): - return str(prospective).lower() == str(spec).lower() - - @property - def prereleases(self): - # If there is an explicit prereleases set for this, then we'll just - # blindly use that. - if self._prereleases is not None: - return self._prereleases - - # Look at all of our specifiers and determine if they are inclusive - # operators, and if they are if they are including an explicit - # prerelease. - operator, version = self._spec - if operator in ["==", ">=", "<=", "~=", "==="]: - # The == specifier can include a trailing .*, if it does we - # want to remove before parsing. - if operator == "==" and version.endswith(".*"): - version = version[:-2] - - # Parse the version, and if it is a pre-release than this - # specifier allows pre-releases. - if parse(version).is_prerelease: - return True - - return False - - @prereleases.setter - def prereleases(self, value): - self._prereleases = value - - -_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$") - - -def _version_split(version): - result = [] - for item in version.split("."): - match = _prefix_regex.search(item) - if match: - result.extend(match.groups()) - else: - result.append(item) - return result - - -def _pad_version(left, right): - left_split, right_split = [], [] - - # Get the release segment of our versions - left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left))) - right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right))) - - # Get the rest of our versions - left_split.append(left[len(left_split[0]) :]) - right_split.append(right[len(right_split[0]) :]) - - # Insert our padding - left_split.insert(1, ["0"] * max(0, len(right_split[0]) - len(left_split[0]))) - right_split.insert(1, ["0"] * max(0, len(left_split[0]) - len(right_split[0]))) - - return (list(itertools.chain(*left_split)), list(itertools.chain(*right_split))) - - -class SpecifierSet(BaseSpecifier): - def __init__(self, specifiers="", prereleases=None): - # Split on , to break each indidivual specifier into it's own item, and - # strip each item to remove leading/trailing whitespace. - specifiers = [s.strip() for s in specifiers.split(",") if s.strip()] - - # Parsed each individual specifier, attempting first to make it a - # Specifier and falling back to a LegacySpecifier. - parsed = set() - for specifier in specifiers: - try: - parsed.add(Specifier(specifier)) - except InvalidSpecifier: - parsed.add(LegacySpecifier(specifier)) - - # Turn our parsed specifiers into a frozen set and save them for later. - self._specs = frozenset(parsed) - - # Store our prereleases value so we can use it later to determine if - # we accept prereleases or not. - self._prereleases = prereleases - - def __repr__(self): - pre = ( - ", prereleases={0!r}".format(self.prereleases) - if self._prereleases is not None - else "" - ) - - return "".format(str(self), pre) - - def __str__(self): - return ",".join(sorted(str(s) for s in self._specs)) - - def __hash__(self): - return hash(self._specs) - - def __and__(self, other): - if isinstance(other, string_types): - other = SpecifierSet(other) - elif not isinstance(other, SpecifierSet): - return NotImplemented - - specifier = SpecifierSet() - specifier._specs = frozenset(self._specs | other._specs) - - if self._prereleases is None and other._prereleases is not None: - specifier._prereleases = other._prereleases - elif self._prereleases is not None and other._prereleases is None: - specifier._prereleases = self._prereleases - elif self._prereleases == other._prereleases: - specifier._prereleases = self._prereleases - else: - raise ValueError( - "Cannot combine SpecifierSets with True and False prerelease " - "overrides." - ) - - return specifier - - def __eq__(self, other): - if isinstance(other, string_types): - other = SpecifierSet(other) - elif isinstance(other, _IndividualSpecifier): - other = SpecifierSet(str(other)) - elif not isinstance(other, SpecifierSet): - return NotImplemented - - return self._specs == other._specs - - def __ne__(self, other): - if isinstance(other, string_types): - other = SpecifierSet(other) - elif isinstance(other, _IndividualSpecifier): - other = SpecifierSet(str(other)) - elif not isinstance(other, SpecifierSet): - return NotImplemented - - return self._specs != other._specs - - def __len__(self): - return len(self._specs) - - def __iter__(self): - return iter(self._specs) - - @property - def prereleases(self): - # If we have been given an explicit prerelease modifier, then we'll - # pass that through here. - if self._prereleases is not None: - return self._prereleases - - # If we don't have any specifiers, and we don't have a forced value, - # then we'll just return None since we don't know if this should have - # pre-releases or not. - if not self._specs: - return None - - # Otherwise we'll see if any of the given specifiers accept - # prereleases, if any of them do we'll return True, otherwise False. - return any(s.prereleases for s in self._specs) - - @prereleases.setter - def prereleases(self, value): - self._prereleases = value - - def __contains__(self, item): - return self.contains(item) - - def contains(self, item, prereleases=None): - # Ensure that our item is a Version or LegacyVersion instance. - if not isinstance(item, (LegacyVersion, Version)): - item = parse(item) - - # Determine if we're forcing a prerelease or not, if we're not forcing - # one for this particular filter call, then we'll use whatever the - # SpecifierSet thinks for whether or not we should support prereleases. - if prereleases is None: - prereleases = self.prereleases - - # We can determine if we're going to allow pre-releases by looking to - # see if any of the underlying items supports them. If none of them do - # and this item is a pre-release then we do not allow it and we can - # short circuit that here. - # Note: This means that 1.0.dev1 would not be contained in something - # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0 - if not prereleases and item.is_prerelease: - return False - - # We simply dispatch to the underlying specs here to make sure that the - # given version is contained within all of them. - # Note: This use of all() here means that an empty set of specifiers - # will always return True, this is an explicit design decision. - return all(s.contains(item, prereleases=prereleases) for s in self._specs) - - def filter(self, iterable, prereleases=None): - # Determine if we're forcing a prerelease or not, if we're not forcing - # one for this particular filter call, then we'll use whatever the - # SpecifierSet thinks for whether or not we should support prereleases. - if prereleases is None: - prereleases = self.prereleases - - # If we have any specifiers, then we want to wrap our iterable in the - # filter method for each one, this will act as a logical AND amongst - # each specifier. - if self._specs: - for spec in self._specs: - iterable = spec.filter(iterable, prereleases=bool(prereleases)) - return iterable - # If we do not have any specifiers, then we need to have a rough filter - # which will filter out any pre-releases, unless there are no final - # releases, and which will filter out LegacyVersion in general. - else: - filtered = [] - found_prereleases = [] - - for item in iterable: - # Ensure that we some kind of Version class for this item. - if not isinstance(item, (LegacyVersion, Version)): - parsed_version = parse(item) - else: - parsed_version = item - - # Filter out any item which is parsed as a LegacyVersion - if isinstance(parsed_version, LegacyVersion): - continue - - # Store any item which is a pre-release for later unless we've - # already found a final version or we are accepting prereleases - if parsed_version.is_prerelease and not prereleases: - if not filtered: - found_prereleases.append(item) - else: - filtered.append(item) - - # If we've found no items except for pre-releases, then we'll go - # ahead and use the pre-releases - if not filtered and found_prereleases and prereleases is None: - return found_prereleases - - return filtered diff --git a/poetry/version/utils.py b/poetry/version/utils.py deleted file mode 100644 index 4e3d50feb7f..00000000000 --- a/poetry/version/utils.py +++ /dev/null @@ -1,62 +0,0 @@ -class Infinity(object): - def __repr__(self): - return "Infinity" - - def __hash__(self): - return hash(repr(self)) - - def __lt__(self, other): - return False - - def __le__(self, other): - return False - - def __eq__(self, other): - return isinstance(other, self.__class__) - - def __ne__(self, other): - return not isinstance(other, self.__class__) - - def __gt__(self, other): - return True - - def __ge__(self, other): - return True - - def __neg__(self): - return NegativeInfinity - - -Infinity = Infinity() # type: ignore - - -class NegativeInfinity(object): - def __repr__(self): - return "-Infinity" - - def __hash__(self): - return hash(repr(self)) - - def __lt__(self, other): - return True - - def __le__(self, other): - return True - - def __eq__(self, other): - return isinstance(other, self.__class__) - - def __ne__(self, other): - return not isinstance(other, self.__class__) - - def __gt__(self, other): - return False - - def __ge__(self, other): - return False - - def __neg__(self): - return Infinity - - -NegativeInfinity = NegativeInfinity() # type: ignore diff --git a/poetry/version/version.py b/poetry/version/version.py deleted file mode 100644 index b85c6c5c79a..00000000000 --- a/poetry/version/version.py +++ /dev/null @@ -1,229 +0,0 @@ -import re - -from collections import namedtuple -from itertools import dropwhile - -from .base import BaseVersion -from .exceptions import InvalidVersion -from .utils import Infinity - - -_Version = namedtuple("_Version", ["epoch", "release", "dev", "pre", "post", "local"]) - - -VERSION_PATTERN = re.compile( - r""" - ^ - v? - (?: - (?:(?P[0-9]+)!)? # epoch - (?P[0-9]+(?:\.[0-9]+)*) # release segment - (?P
                                          # pre-release
-            [-_.]?
-            (?P(a|b|c|rc|alpha|beta|pre|preview))
-            [-_.]?
-            (?P[0-9]+)?
-        )?
-        (?P                                         # post release
-            (?:-(?P[0-9]+))
-            |
-            (?:
-                [-_.]?
-                (?Ppost|rev|r)
-                [-_.]?
-                (?P[0-9]+)?
-            )
-        )?
-        (?P                                          # dev release
-            [-_.]?
-            (?Pdev)
-            [-_.]?
-            (?P[0-9]+)?
-        )?
-    )
-    (?:\+(?P[a-z0-9]+(?:[-_.][a-z0-9]+)*))?       # local version
-    $
-""",
-    re.IGNORECASE | re.VERBOSE,
-)
-
-
-class Version(BaseVersion):
-    def __init__(self, version):
-        # Validate the version and parse it into pieces
-        match = VERSION_PATTERN.match(version)
-        if not match:
-            raise InvalidVersion("Invalid version: '{0}'".format(version))
-
-        # Store the parsed out pieces of the version
-        self._version = _Version(
-            epoch=int(match.group("epoch")) if match.group("epoch") else 0,
-            release=tuple(int(i) for i in match.group("release").split(".")),
-            pre=_parse_letter_version(match.group("pre_l"), match.group("pre_n")),
-            post=_parse_letter_version(
-                match.group("post_l"), match.group("post_n1") or match.group("post_n2")
-            ),
-            dev=_parse_letter_version(match.group("dev_l"), match.group("dev_n")),
-            local=_parse_local_version(match.group("local")),
-        )
-
-        # Generate a key which will be used for sorting
-        self._key = _cmpkey(
-            self._version.epoch,
-            self._version.release,
-            self._version.pre,
-            self._version.post,
-            self._version.dev,
-            self._version.local,
-        )
-
-    def __repr__(self):
-        return "".format(repr(str(self)))
-
-    def __str__(self):
-        parts = []
-
-        # Epoch
-        if self._version.epoch != 0:
-            parts.append("{0}!".format(self._version.epoch))
-
-        # Release segment
-        parts.append(".".join(str(x) for x in self._version.release))
-
-        # Pre-release
-        if self._version.pre is not None:
-            parts.append("".join(str(x) for x in self._version.pre))
-
-        # Post-release
-        if self._version.post is not None:
-            parts.append(".post{0}".format(self._version.post[1]))
-
-        # Development release
-        if self._version.dev is not None:
-            parts.append(".dev{0}".format(self._version.dev[1]))
-
-        # Local version segment
-        if self._version.local is not None:
-            parts.append("+{0}".format(".".join(str(x) for x in self._version.local)))
-
-        return "".join(parts)
-
-    @property
-    def public(self):
-        return str(self).split("+", 1)[0]
-
-    @property
-    def base_version(self):
-        parts = []
-
-        # Epoch
-        if self._version.epoch != 0:
-            parts.append("{0}!".format(self._version.epoch))
-
-        # Release segment
-        parts.append(".".join(str(x) for x in self._version.release))
-
-        return "".join(parts)
-
-    @property
-    def local(self):
-        version_string = str(self)
-        if "+" in version_string:
-            return version_string.split("+", 1)[1]
-
-    @property
-    def is_prerelease(self):
-        return bool(self._version.dev or self._version.pre)
-
-    @property
-    def is_postrelease(self):
-        return bool(self._version.post)
-
-
-def _parse_letter_version(letter, number):
-    if letter:
-        # We consider there to be an implicit 0 in a pre-release if there is
-        # not a numeral associated with it.
-        if number is None:
-            number = 0
-
-        # We normalize any letters to their lower case form
-        letter = letter.lower()
-
-        # We consider some words to be alternate spellings of other words and
-        # in those cases we want to normalize the spellings to our preferred
-        # spelling.
-        if letter == "alpha":
-            letter = "a"
-        elif letter == "beta":
-            letter = "b"
-        elif letter in ["c", "pre", "preview"]:
-            letter = "rc"
-        elif letter in ["rev", "r"]:
-            letter = "post"
-
-        return letter, int(number)
-    if not letter and number:
-        # We assume if we are given a number, but we are not given a letter
-        # then this is using the implicit post release syntax (e.g. 1.0-1)
-        letter = "post"
-
-        return letter, int(number)
-
-
-_local_version_seperators = re.compile(r"[._-]")
-
-
-def _parse_local_version(local):
-    """
-    Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
-    """
-    if local is not None:
-        return tuple(
-            part.lower() if not part.isdigit() else int(part)
-            for part in _local_version_seperators.split(local)
-        )
-
-
-def _cmpkey(epoch, release, pre, post, dev, local):
-    # When we compare a release version, we want to compare it with all of the
-    # trailing zeros removed. So we'll use a reverse the list, drop all the now
-    # leading zeros until we come to something non zero, then take the rest
-    # re-reverse it back into the correct order and make it a tuple and use
-    # that for our sorting key.
-    release = tuple(reversed(list(dropwhile(lambda x: x == 0, reversed(release)))))
-
-    # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
-    # We'll do this by abusing the pre segment, but we _only_ want to do this
-    # if there is not a pre or a post segment. If we have one of those then
-    # the normal sorting rules will handle this case correctly.
-    if pre is None and post is None and dev is not None:
-        pre = -Infinity
-
-    # Versions without a pre-release (except as noted above) should sort after
-    # those with one.
-    elif pre is None:
-        pre = Infinity
-
-    # Versions without a post segment should sort before those with one.
-    if post is None:
-        post = -Infinity
-
-    # Versions without a development segment should sort after those with one.
-    if dev is None:
-        dev = Infinity
-
-    if local is None:
-        # Versions without a local segment should sort before those with one.
-        local = -Infinity
-    else:
-        # Versions with a local segment need that segment parsed to implement
-        # the sorting rules in PEP440.
-        # - Alpha numeric segments sort before numeric segments
-        # - Alpha numeric segments sort lexicographically
-        # - Numeric segments sort numerically
-        # - Shorter versions sort before longer versions when the prefixes
-        #   match exactly
-        local = tuple((i, "") if isinstance(i, int) else (-Infinity, i) for i in local)
-
-    return epoch, release, pre, post, dev, local
diff --git a/poetry/version/version_selector.py b/poetry/version/version_selector.py
index 2077e322699..8cf02c7cbed 100644
--- a/poetry/version/version_selector.py
+++ b/poetry/version/version_selector.py
@@ -1,9 +1,9 @@
 from typing import Union
 
-from poetry.packages import Dependency
-from poetry.packages import Package
-from poetry.semver import Version
-from poetry.semver import parse_constraint
+from poetry.core.packages import Dependency
+from poetry.core.packages import Package
+from poetry.core.semver import Version
+from poetry.core.semver import parse_constraint
 
 
 class VersionSelector(object):
diff --git a/pyproject.toml b/pyproject.toml
index 13e8199331b..71cf98801fe 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "poetry"
-version = "1.0.3"
+version = "1.1.0a1"
 description = "Python dependency management and packaging made easy."
 authors = [
     "Sébastien Eustace "
@@ -22,40 +22,40 @@ classifiers = [
 
 # Requirements
 [tool.poetry.dependencies]
-python = "~2.7 || ^3.4"
-cleo = "^0.7.6"
-clikit = "^0.4.1"
+python = "~2.7 || ^3.5"
+
+poetry-core = "^1.0.0a6"
+cleo = "^0.8.0"
+clikit = "^0.5.1"
 requests = "^2.18"
 cachy = "^0.3.0"
 requests-toolbelt = "^0.8.0"
-jsonschema = "^3.1"
-pyrsistent = "^0.14.2"
-pyparsing = "^2.2"
 cachecontrol = { version = "^0.12.4", extras = ["filecache"] }
 pkginfo = "^1.4"
 html5lib = "^1.0"
 shellingham = "^1.1"
-tomlkit = "^0.5.8"
+tomlkit = "^0.5.11"
 pexpect = "^4.7.0"
 
-# The typing module is not in the stdlib in Python 2.7 and 3.4
-typing = { version = "^3.6", python = "~2.7 || ~3.4" }
+# The typing module is not in the stdlib in Python 2.7
+typing = { version = "^3.6", python = "~2.7" }
 
-# Use pathlib2 for Python 2.7 and 3.4
-pathlib2 = { version = "^2.3", python = "~2.7 || ~3.4" }
+# Use pathlib2 for Python 2.7
+pathlib2 = { version = "^2.3", python = "~2.7" }
 # Use glob2 for Python 2.7 and 3.4
-glob2 = { version = "^0.6", python = "~2.7 || ~3.4" }
+glob2 = { version = "^0.6", python = "~2.7" }
 # Use virtualenv for Python 2.7 since venv does not exist
-virtualenv = { version = "^16.7.9", python = "~2.7" }
+virtualenv = { version = "^20.0.18", python = "~2.7" }
 # functools32 is needed for Python 2.7
 functools32 = { version = "^3.2.3", python = "~2.7" }
 keyring = [
-    { version = "^18.0.1", python = "~2.7 || ~3.4" },
-    { version = "^20.0.1", python = "^3.5" }
+    { version = "^18.0.1", python = "~2.7" },
+    { version = "^20.0.1", python = "~3.5" },
+    { version = "^21.2.0", python = "^3.6" }
 ]
-# Use subprocess32 for Python 2.7 and 3.4
-subprocess32 = { version = "^3.5", python = "~2.7 || ~3.4" }
-importlib-metadata = {version = "~1.1.3", python = "<3.8"}
+# Use subprocess32 for Python 2.7
+subprocess32 = { version = "^3.5", python = "~2.7" }
+importlib-metadata = {version = "^1.6.0", python = "<3.8"}
 
 [tool.poetry.dev-dependencies]
 pytest = "^4.1"
@@ -77,11 +77,8 @@ poetry = "poetry.console:main"
 
 
 [build-system]
-requires = ["intreehooks"]
-build-backend = "intreehooks:loader"
-
-[tool.intreehooks]
-build-backend = "poetry.masonry.api"
+requires = ["poetry-core>=1.0.0a3"]
+build-backend = "poetry.core.masonry.api"
 
 
 [tool.isort]
@@ -109,6 +106,7 @@ known_third_party = [
     "keyring",
     "pexpect",
     "pkginfo",
+    "poetry_core",
     "pyparsing",
     "pytest",
     "requests",
diff --git a/sonnet b/sonnet
index dc4b541275d..4c5e558c545 100755
--- a/sonnet
+++ b/sonnet
@@ -10,6 +10,7 @@ from gzip import GzipFile
 
 from cleo import Application
 from cleo import Command
+from clikit.api.formatter import Style
 
 
 WINDOWS = sys.platform.startswith("win") or (sys.platform == "cli" and os.name == "nt")
@@ -25,7 +26,6 @@ class MakeReleaseCommand(Command):
 
     PYTHON = {
         "2.7": "python2.7",
-        "3.4": "python3.4",
         "3.5": "python3.5",
         "3.6": "python3.6",
         "3.7": "python3.7",
@@ -47,7 +47,8 @@ class MakeReleaseCommand(Command):
 
         self.check_system(pythons)
 
-        from poetry import __version__
+        from poetry.__version__ import __version__
+        from poetry.core.vcs import get_vcs
         from poetry.factory import Factory
         from poetry.puzzle import Solver
         from poetry.repositories.pool import Pool
@@ -59,7 +60,6 @@ class MakeReleaseCommand(Command):
         from poetry.utils.env import GET_BASE_PREFIX
         from poetry.utils.env import VirtualEnv
         from poetry.utils.helpers import temporary_directory
-        from poetry.vcs import get_vcs
 
         project = Factory().create_poetry(Path.cwd())
         package = project.package
@@ -273,6 +273,7 @@ class MakeCommand(Command):
 
 
 app = Application("sonnet")
+app.config.add_style(Style("debug").fg("default").dark())
 
 app.add(MakeCommand())
 
diff --git a/tests/conftest.py b/tests/conftest.py
index d5ff7f488c9..6c1eca07613 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -71,7 +71,9 @@ def config(config_source, auth_config_source, mocker):
 @pytest.fixture(autouse=True)
 def download_mock(mocker):
     # Patch download to not download anything but to just copy from fixtures
-    mocker.patch("poetry.utils.inspector.Inspector.download", new=mock_download)
+    mocker.patch("poetry.utils.helpers.download_file", new=mock_download)
+    mocker.patch("poetry.puzzle.provider.download_file", new=mock_download)
+    mocker.patch("poetry.repositories.pypi_repository.download_file", new=mock_download)
 
 
 @pytest.fixture
@@ -87,9 +89,9 @@ def environ():
 @pytest.fixture(autouse=True)
 def git_mock(mocker):
     # Patch git module to not actually clone projects
-    mocker.patch("poetry.vcs.git.Git.clone", new=mock_clone)
-    mocker.patch("poetry.vcs.git.Git.checkout", new=lambda *_: None)
-    p = mocker.patch("poetry.vcs.git.Git.rev_parse")
+    mocker.patch("poetry.core.vcs.git.Git.clone", new=mock_clone)
+    mocker.patch("poetry.core.vcs.git.Git.checkout", new=lambda *_: None)
+    p = mocker.patch("poetry.core.vcs.git.Git.rev_parse")
     p.return_value = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24"
 
 
@@ -117,3 +119,18 @@ def tmp_dir():
     yield dir_
 
     shutil.rmtree(dir_)
+
+
+@pytest.fixture
+def mocked_open_files(mocker):
+    files = []
+    original = Path.open
+
+    def mocked_open(self, *args, **kwargs):
+        if self.name in {"pyproject.toml"}:
+            return mocker.MagicMock()
+        return original(self, *args, **kwargs)
+
+    mocker.patch("poetry.utils._compat.Path.open", mocked_open)
+
+    yield files
diff --git a/tests/console/commands/env/test_list.py b/tests/console/commands/env/test_list.py
index e9112449307..e2946373b6a 100644
--- a/tests/console/commands/env/test_list.py
+++ b/tests/console/commands/env/test_list.py
@@ -1,3 +1,5 @@
+import os
+
 import tomlkit
 
 from cleo.testers import CommandTester
@@ -58,3 +60,19 @@ def test_activated(app, tmp_dir):
     )
 
     assert expected == tester.io.fetch_output()
+
+
+def test_in_project_venv(app, tmpdir):
+    os.environ.pop("VIRTUAL_ENV", None)
+    app.poetry.config.merge({"virtualenvs": {"in-project": True}})
+
+    (app.poetry.file.parent / ".venv").mkdir(exist_ok=True)
+
+    command = app.find("env list")
+    tester = CommandTester(command)
+    tester.execute()
+
+    expected = ".venv (Activated)\n"
+
+    assert expected == tester.io.fetch_output()
+    (app.poetry.file.parent / ".venv").rmdir()
diff --git a/tests/console/commands/env/test_use.py b/tests/console/commands/env/test_use.py
index 2b1967bf3b1..ac042c93b05 100644
--- a/tests/console/commands/env/test_use.py
+++ b/tests/console/commands/env/test_use.py
@@ -6,7 +6,7 @@
 
 from cleo.testers import CommandTester
 
-from poetry.semver import Version
+from poetry.core.semver import Version
 from poetry.utils._compat import Path
 from poetry.utils.env import EnvManager
 from poetry.utils.env import MockEnv
diff --git a/tests/console/commands/test_add.py b/tests/console/commands/test_add.py
index 8e7f4a870c8..9a1e5036500 100644
--- a/tests/console/commands/test_add.py
+++ b/tests/console/commands/test_add.py
@@ -4,8 +4,8 @@
 
 from cleo.testers import CommandTester
 
+from poetry.core.semver import Version
 from poetry.repositories.legacy_repository import LegacyRepository
-from poetry.semver import Version
 from poetry.utils._compat import Path
 from tests.helpers import get_dependency
 from tests.helpers import get_package
@@ -870,3 +870,23 @@ def test_add_preferes_stable_releases(app, repo, installer):
 """
 
     assert expected in tester.io.fetch_output()
+
+
+def test_add_with_lock(app, repo, installer):
+    command = app.find("add")
+    tester = CommandTester(command)
+
+    repo.add_package(get_package("cachy", "0.2.0"))
+
+    tester.execute("cachy --lock")
+
+    expected = """\
+Using version ^0.2.0 for cachy
+
+Updating dependencies
+Resolving dependencies...
+
+Writing lock file
+"""
+
+    assert expected == tester.io.fetch_output()
diff --git a/tests/console/commands/test_check.py b/tests/console/commands/test_check.py
index 78f928de1fc..8f8b94a5c9b 100644
--- a/tests/console/commands/test_check.py
+++ b/tests/console/commands/test_check.py
@@ -34,14 +34,12 @@ def test_check_invalid(app, mocker):
     if PY2:
         expected = """\
 Error: u'description' is a required property
-Error: INVALID is not a valid license
 Warning: A wildcard Python dependency is ambiguous. Consider specifying a more explicit one.
 Warning: The "pendulum" dependency specifies the "allows-prereleases" property, which is deprecated. Use "allow-prereleases" instead.
 """
     else:
         expected = """\
 Error: 'description' is a required property
-Error: INVALID is not a valid license
 Warning: A wildcard Python dependency is ambiguous. Consider specifying a more explicit one.
 Warning: The "pendulum" dependency specifies the "allows-prereleases" property, which is deprecated. Use "allow-prereleases" instead.
 """
diff --git a/tests/console/commands/test_export.py b/tests/console/commands/test_export.py
index 58049a1bba9..65d4927916d 100644
--- a/tests/console/commands/test_export.py
+++ b/tests/console/commands/test_export.py
@@ -168,6 +168,28 @@ def test_export_prints_to_stdout_by_default(app, repo):
     assert expected == tester.io.fetch_output()
 
 
+def test_export_uses_requirements_txt_format_by_default(app, repo):
+    repo.add_package(get_package("foo", "1.0.0"))
+    repo.add_package(get_package("bar", "1.1.0"))
+
+    command = app.find("lock")
+    tester = CommandTester(command)
+    tester.execute()
+
+    assert app.poetry.locker.lock.exists()
+
+    command = app.find("export")
+    tester = CommandTester(command)
+
+    tester.execute()
+
+    expected = """\
+foo==1.0.0
+"""
+
+    assert expected == tester.io.fetch_output()
+
+
 def test_export_includes_extras_by_flag(app, repo):
     repo.add_package(get_package("foo", "1.0.0"))
     repo.add_package(get_package("bar", "1.1.0"))
diff --git a/tests/console/commands/test_init.py b/tests/console/commands/test_init.py
index e98b781783d..354c75e59ab 100644
--- a/tests/console/commands/test_init.py
+++ b/tests/console/commands/test_init.py
@@ -137,14 +137,16 @@ def test_empty_license(app, mocker, poetry):
     assert expected in tester.io.fetch_output()
 
 
-def test_interactive_with_git_dependencies(app, repo, mocker, poetry):
+def test_interactive_with_git_dependencies(
+    app, repo, mocker, poetry, mocked_open_files
+):
     repo.add_package(get_package("pendulum", "2.0.0"))
     repo.add_package(get_package("pytest", "3.6.0"))
 
     command = app.find("init")
     command._pool = poetry.pool
 
-    mocker.patch("poetry.utils._compat.Path.open")
+    mocked_open_files.append("pyproject.toml")
     p = mocker.patch("poetry.utils._compat.Path.cwd")
     p.return_value = Path(__file__).parent
 
@@ -187,14 +189,16 @@ def test_interactive_with_git_dependencies(app, repo, mocker, poetry):
     assert expected in tester.io.fetch_output()
 
 
-def test_interactive_with_git_dependencies_with_reference(app, repo, mocker, poetry):
+def test_interactive_with_git_dependencies_with_reference(
+    app, repo, mocker, poetry, mocked_open_files
+):
     repo.add_package(get_package("pendulum", "2.0.0"))
     repo.add_package(get_package("pytest", "3.6.0"))
 
     command = app.find("init")
     command._pool = poetry.pool
 
-    mocker.patch("poetry.utils._compat.Path.open")
+    mocked_open_files.append("pyproject.toml")
     p = mocker.patch("poetry.utils._compat.Path.cwd")
     p.return_value = Path(__file__).parent
 
@@ -237,14 +241,16 @@ def test_interactive_with_git_dependencies_with_reference(app, repo, mocker, poe
     assert expected in tester.io.fetch_output()
 
 
-def test_interactive_with_git_dependencies_and_other_name(app, repo, mocker, poetry):
+def test_interactive_with_git_dependencies_and_other_name(
+    app, repo, mocker, poetry, mocked_open_files
+):
     repo.add_package(get_package("pendulum", "2.0.0"))
     repo.add_package(get_package("pytest", "3.6.0"))
 
     command = app.find("init")
     command._pool = poetry.pool
 
-    mocker.patch("poetry.utils._compat.Path.open")
+    mocked_open_files.append("pyproject.toml")
     p = mocker.patch("poetry.utils._compat.Path.cwd")
     p.return_value = Path(__file__).parent
 
@@ -287,14 +293,16 @@ def test_interactive_with_git_dependencies_and_other_name(app, repo, mocker, poe
     assert expected in tester.io.fetch_output()
 
 
-def test_interactive_with_directory_dependency(app, repo, mocker, poetry):
+def test_interactive_with_directory_dependency(
+    app, repo, mocker, poetry, mocked_open_files
+):
     repo.add_package(get_package("pendulum", "2.0.0"))
     repo.add_package(get_package("pytest", "3.6.0"))
 
     command = app.find("init")
     command._pool = poetry.pool
 
-    mocker.patch("poetry.utils._compat.Path.open")
+    mocked_open_files.append("pyproject.toml")
     p = mocker.patch("poetry.utils._compat.Path.cwd")
     p.return_value = Path(__file__).parent
 
diff --git a/tests/console/commands/test_publish.py b/tests/console/commands/test_publish.py
index 856878a57a4..dccc43ee87d 100644
--- a/tests/console/commands/test_publish.py
+++ b/tests/console/commands/test_publish.py
@@ -1,6 +1,14 @@
+import pytest
+import requests
+
+from poetry.publishing.uploader import UploadError
+from poetry.utils._compat import PY36
 from poetry.utils._compat import Path
 
 
+@pytest.mark.skipif(
+    not PY36, reason="Improved error rendering is only available on Python >=3.6"
+)
 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"
@@ -14,7 +22,51 @@ def test_publish_returns_non_zero_code_for_upload_errors(app, app_tester, http):
 Publishing simple-project (1.2.3) to PyPI
 
 
-[UploadError]
+  UploadError
+
+  HTTP Error 400: Bad Request
+"""
+
+    assert expected in app_tester.io.fetch_output()
+
+
+def test_publish_returns_non_zero_code_for_connection_errors(app, app_tester, http):
+    def request_callback(*_, **__):
+        raise requests.ConnectionError()
+
+    http.register_uri(
+        http.POST, "https://upload.pypi.org/legacy/", body=request_callback
+    )
+
+    exit_code = app_tester.execute("publish --username foo --password bar")
+
+    assert 1 == exit_code
+
+    expected = str(UploadError(error=requests.ConnectionError()))
+
+    assert expected in app_tester.io.fetch_output()
+
+
+@pytest.mark.skipif(
+    PY36, reason="Improved error rendering is not available on Python <3.6"
+)
+def test_publish_returns_non_zero_code_for_upload_errors_older_python(
+    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
 """
 
@@ -22,19 +74,36 @@ def test_publish_returns_non_zero_code_for_upload_errors(app, app_tester, http):
 
 
 def test_publish_with_cert(app_tester, mocker):
-    publisher_publish = mocker.patch("poetry.masonry.publishing.Publisher.publish")
+    publisher_publish = mocker.patch("poetry.publishing.Publisher.publish")
 
     app_tester.execute("publish --cert path/to/ca.pem")
 
     assert [
-        (None, None, None, Path("path/to/ca.pem"), None)
+        (None, None, None, Path("path/to/ca.pem"), None, False)
     ] == publisher_publish.call_args
 
 
 def test_publish_with_client_cert(app_tester, mocker):
-    publisher_publish = mocker.patch("poetry.masonry.publishing.Publisher.publish")
+    publisher_publish = mocker.patch("poetry.publishing.Publisher.publish")
 
     app_tester.execute("publish --client-cert path/to/client.pem")
     assert [
-        (None, None, None, None, Path("path/to/client.pem"))
+        (None, None, None, None, Path("path/to/client.pem"), False)
     ] == publisher_publish.call_args
+
+
+def test_publish_dry_run(app_tester, http):
+    http.register_uri(
+        http.POST, "https://upload.pypi.org/legacy/", status=403, body="Forbidden"
+    )
+
+    exit_code = app_tester.execute("publish --dry-run --username foo --password bar")
+
+    assert 0 == exit_code
+
+    output = app_tester.io.fetch_output()
+    error = app_tester.io.fetch_error()
+
+    assert "Publishing simple-project (1.2.3) to PyPI" in output
+    assert "- Uploading simple-project-1.2.3.tar.gz" in error
+    assert "- Uploading simple_project-1.2.3-py2.py3-none-any.whl" in error
diff --git a/tests/console/commands/test_version.py b/tests/console/commands/test_version.py
index d08cdc0db83..42c4d297d44 100644
--- a/tests/console/commands/test_version.py
+++ b/tests/console/commands/test_version.py
@@ -45,3 +45,10 @@ def test_version_show(app):
     tester = CommandTester(command)
     tester.execute()
     assert "simple-project 1.2.3\n" == tester.io.fetch_output()
+
+
+def test_short_version_show(app):
+    command = app.find("version")
+    tester = CommandTester(command)
+    tester.execute("--short")
+    assert "1.2.3\n" == tester.io.fetch_output()
diff --git a/tests/console/conftest.py b/tests/console/conftest.py
index 58b8834aa61..05b7c49ce6b 100644
--- a/tests/console/conftest.py
+++ b/tests/console/conftest.py
@@ -16,7 +16,6 @@
 from poetry.utils.env import MockEnv
 from poetry.utils.toml_file import TomlFile
 from tests.helpers import mock_clone
-from tests.helpers import mock_download
 
 
 @pytest.fixture()
@@ -49,14 +48,11 @@ def setup(mocker, installer, installed, config, env):
     p.return_value = installed
 
     # Patch git module to not actually clone projects
-    mocker.patch("poetry.vcs.git.Git.clone", new=mock_clone)
-    mocker.patch("poetry.vcs.git.Git.checkout", new=lambda *_: None)
-    p = mocker.patch("poetry.vcs.git.Git.rev_parse")
+    mocker.patch("poetry.core.vcs.git.Git.clone", new=mock_clone)
+    mocker.patch("poetry.core.vcs.git.Git.checkout", new=lambda *_: None)
+    p = mocker.patch("poetry.core.vcs.git.Git.rev_parse")
     p.return_value = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24"
 
-    # Patch download to not download anything but to just copy from fixtures
-    mocker.patch("poetry.utils.inspector.Inspector.download", new=mock_download)
-
     # Patch the virtual environment creation do actually do nothing
     mocker.patch("poetry.utils.env.EnvManager.create_venv", return_value=env)
 
diff --git a/tests/fixtures/directory/project_with_transitive_file_dependencies/setup.py b/tests/fixtures/directory/project_with_transitive_file_dependencies/setup.py
deleted file mode 100644
index 24a8f05be9f..00000000000
--- a/tests/fixtures/directory/project_with_transitive_file_dependencies/setup.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# -*- coding: utf-8 -*-
-from distutils.core import setup
-
-packages = ["project_with_extras"]
-
-package_data = {"": ["*"]}
-
-extras_require = {"extras_a": ["pendulum>=1.4.4"], "extras_b": ["cachy>=0.2.0"]}
-
-setup_kwargs = {
-    "name": "project-with-extras",
-    "version": "1.2.3",
-    "description": "This is a description",
-    "long_description": None,
-    "author": "Your Name",
-    "author_email": "you@example.com",
-    "url": None,
-    "packages": packages,
-    "package_data": package_data,
-    "extras_require": extras_require,
-}
-
-
-setup(**setup_kwargs)
diff --git a/tests/masonry/builders/fixtures/case_sensitive_exclusions/README.rst b/tests/fixtures/excluded_subpackage/README.rst
similarity index 100%
rename from tests/masonry/builders/fixtures/case_sensitive_exclusions/README.rst
rename to tests/fixtures/excluded_subpackage/README.rst
diff --git a/tests/fixtures/excluded_subpackage/example/__init__.py b/tests/fixtures/excluded_subpackage/example/__init__.py
new file mode 100644
index 00000000000..3dc1f76bc69
--- /dev/null
+++ b/tests/fixtures/excluded_subpackage/example/__init__.py
@@ -0,0 +1 @@
+__version__ = "0.1.0"
diff --git a/poetry/packages/utils/__init__.py b/tests/fixtures/excluded_subpackage/example/test/__init__.py
similarity index 100%
rename from poetry/packages/utils/__init__.py
rename to tests/fixtures/excluded_subpackage/example/test/__init__.py
diff --git a/tests/fixtures/excluded_subpackage/example/test/excluded.py b/tests/fixtures/excluded_subpackage/example/test/excluded.py
new file mode 100644
index 00000000000..bf6e1f8962f
--- /dev/null
+++ b/tests/fixtures/excluded_subpackage/example/test/excluded.py
@@ -0,0 +1,5 @@
+from .. import __version__
+
+
+def test_version():
+    assert __version__ == "0.1.0"
diff --git a/tests/fixtures/excluded_subpackage/pyproject.toml b/tests/fixtures/excluded_subpackage/pyproject.toml
new file mode 100644
index 00000000000..3852bb831fa
--- /dev/null
+++ b/tests/fixtures/excluded_subpackage/pyproject.toml
@@ -0,0 +1,18 @@
+[tool.poetry]
+name = "example"
+version = "0.1.0"
+description = ""
+authors = ["Sébastien Eustace "]
+exclude = [
+    "**/test/**/*",
+]
+
+[tool.poetry.dependencies]
+python = "^3.6"
+
+[tool.poetry.dev-dependencies]
+pytest = "^3.0"
+
+[build-system]
+requires = ["poetry>=0.12"]
+build-backend = "poetry.masonry.api"
diff --git a/tests/masonry/builders/fixtures/case_sensitive_exclusions/LICENSE b/tests/fixtures/with-include/LICENSE
similarity index 100%
rename from tests/masonry/builders/fixtures/case_sensitive_exclusions/LICENSE
rename to tests/fixtures/with-include/LICENSE
diff --git a/tests/masonry/builders/fixtures/complete/README.rst b/tests/fixtures/with-include/README.rst
similarity index 100%
rename from tests/masonry/builders/fixtures/complete/README.rst
rename to tests/fixtures/with-include/README.rst
diff --git a/tests/masonry/builders/fixtures/with-include/extra_dir/README.md b/tests/fixtures/with-include/extra_dir/README.md
similarity index 100%
rename from tests/masonry/builders/fixtures/with-include/extra_dir/README.md
rename to tests/fixtures/with-include/extra_dir/README.md
diff --git a/tests/json/__init__.py b/tests/fixtures/with-include/extra_dir/__init__.py
similarity index 100%
rename from tests/json/__init__.py
rename to tests/fixtures/with-include/extra_dir/__init__.py
diff --git a/tests/masonry/__init__.py b/tests/fixtures/with-include/extra_dir/sub_pkg/__init__.py
similarity index 100%
rename from tests/masonry/__init__.py
rename to tests/fixtures/with-include/extra_dir/sub_pkg/__init__.py
diff --git a/tests/masonry/builders/fixtures/with-include/extra_dir/sub_pkg/vcs_excluded.txt b/tests/fixtures/with-include/extra_dir/sub_pkg/vcs_excluded.txt
similarity index 100%
rename from tests/masonry/builders/fixtures/with-include/extra_dir/sub_pkg/vcs_excluded.txt
rename to tests/fixtures/with-include/extra_dir/sub_pkg/vcs_excluded.txt
diff --git a/tests/masonry/builders/fixtures/with-include/extra_dir/vcs_excluded.txt b/tests/fixtures/with-include/extra_dir/vcs_excluded.txt
similarity index 100%
rename from tests/masonry/builders/fixtures/with-include/extra_dir/vcs_excluded.txt
rename to tests/fixtures/with-include/extra_dir/vcs_excluded.txt
diff --git a/tests/masonry/builders/__init__.py b/tests/fixtures/with-include/for_wheel_only/__init__.py
similarity index 100%
rename from tests/masonry/builders/__init__.py
rename to tests/fixtures/with-include/for_wheel_only/__init__.py
diff --git a/tests/masonry/builders/fixtures/with-include/my_module.py b/tests/fixtures/with-include/my_module.py
similarity index 100%
rename from tests/masonry/builders/fixtures/with-include/my_module.py
rename to tests/fixtures/with-include/my_module.py
diff --git a/tests/masonry/builders/fixtures/with-include/notes.txt b/tests/fixtures/with-include/notes.txt
similarity index 100%
rename from tests/masonry/builders/fixtures/with-include/notes.txt
rename to tests/fixtures/with-include/notes.txt
diff --git a/tests/masonry/builders/fixtures/case_sensitive_exclusions/my_package/__init__.py b/tests/fixtures/with-include/package_with_include/__init__.py
similarity index 100%
rename from tests/masonry/builders/fixtures/case_sensitive_exclusions/my_package/__init__.py
rename to tests/fixtures/with-include/package_with_include/__init__.py
diff --git a/tests/masonry/builders/fixtures/with-include/pyproject.toml b/tests/fixtures/with-include/pyproject.toml
similarity index 100%
rename from tests/masonry/builders/fixtures/with-include/pyproject.toml
rename to tests/fixtures/with-include/pyproject.toml
diff --git a/tests/masonry/builders/fixtures/complete/my_package/sub_pkg1/__init__.py b/tests/fixtures/with-include/src/src_package/__init__.py
similarity index 100%
rename from tests/masonry/builders/fixtures/complete/my_package/sub_pkg1/__init__.py
rename to tests/fixtures/with-include/src/src_package/__init__.py
diff --git a/tests/masonry/builders/fixtures/complete/my_package/sub_pkg2/__init__.py b/tests/fixtures/with-include/tests/__init__.py
similarity index 100%
rename from tests/masonry/builders/fixtures/complete/my_package/sub_pkg2/__init__.py
rename to tests/fixtures/with-include/tests/__init__.py
diff --git a/tests/helpers.py b/tests/helpers.py
index 6f5f73f163b..0dd7ce312e5 100644
--- a/tests/helpers.py
+++ b/tests/helpers.py
@@ -1,13 +1,13 @@
 import os
 import shutil
 
-from poetry.packages import Dependency
-from poetry.packages import Package
+from poetry.core.packages import Dependency
+from poetry.core.packages import Package
+from poetry.core.vcs.git import ParsedUrl
 from poetry.utils._compat import PY2
 from poetry.utils._compat import WINDOWS
 from poetry.utils._compat import Path
 from poetry.utils._compat import urlparse
-from poetry.vcs.git import ParsedUrl
 
 
 FIXTURE_PATH = Path(__file__).parent / "fixtures"
@@ -81,10 +81,10 @@ def mock_clone(_, source, dest):
     copy_or_symlink(folder, dest)
 
 
-def mock_download(self, url, dest):
+def mock_download(url, dest, **__):
     parts = urlparse.urlparse(url)
 
     fixtures = Path(__file__).parent / "fixtures"
     fixture = fixtures / parts.path.lstrip("/")
 
-    copy_or_symlink(fixture, dest)
+    copy_or_symlink(fixture, Path(dest))
diff --git a/tests/installation/fixtures/with-directory-dependency-poetry-transitive.test b/tests/installation/fixtures/with-directory-dependency-poetry-transitive.test
index 06f262f74e6..ffc00b0dd33 100644
--- a/tests/installation/fixtures/with-directory-dependency-poetry-transitive.test
+++ b/tests/installation/fixtures/with-directory-dependency-poetry-transitive.test
@@ -1,6 +1,6 @@
 [[package]]
 category = "main"
-description = ""
+description = "This is a description"
 develop = true
 name = "project-with-extras"
 optional = false
@@ -18,7 +18,7 @@ url = "tests/fixtures/directory/project_with_transitive_directory_dependencies/.
 
 [[package]]
 category = "main"
-description = ""
+description = "This is a description"
 develop = true
 name = "project-with-transitive-directory-dependencies"
 optional = false
diff --git a/tests/installation/fixtures/with-directory-dependency-poetry.test b/tests/installation/fixtures/with-directory-dependency-poetry.test
index df8b282d684..c9bd6b32c4b 100644
--- a/tests/installation/fixtures/with-directory-dependency-poetry.test
+++ b/tests/installation/fixtures/with-directory-dependency-poetry.test
@@ -8,7 +8,7 @@ version = "1.4.4"
 
 [[package]]
 category = "main"
-description = ""
+description = "This is a description"
 develop = true
 name = "project-with-extras"
 optional = false
diff --git a/tests/installation/fixtures/with-file-dependency-transitive.test b/tests/installation/fixtures/with-file-dependency-transitive.test
index db3b632694a..a580109dc32 100644
--- a/tests/installation/fixtures/with-file-dependency-transitive.test
+++ b/tests/installation/fixtures/with-file-dependency-transitive.test
@@ -28,7 +28,7 @@ version = "1.4.4"
 
 [[package]]
 category = "main"
-description = ""
+description = "This is a description"
 develop = true
 name = "project-with-transitive-file-dependencies"
 optional = false
diff --git a/tests/installation/fixtures/with-multiple-updates.test b/tests/installation/fixtures/with-multiple-updates.test
index 961817afea1..cacaf6954af 100644
--- a/tests/installation/fixtures/with-multiple-updates.test
+++ b/tests/installation/fixtures/with-multiple-updates.test
@@ -21,14 +21,6 @@ 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"
diff --git a/tests/installation/fixtures/with-pypi-repository.test b/tests/installation/fixtures/with-pypi-repository.test
index fc16d3d6187..e1898fbd3f1 100644
--- a/tests/installation/fixtures/with-pypi-repository.test
+++ b/tests/installation/fixtures/with-pypi-repository.test
@@ -67,7 +67,6 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 [package.dependencies]
 py = ">=1.5.0"
 six = ">=1.10.0"
-setuptools = "*"
 attrs = ">=17.4.0"
 more-itertools = ">=4.0.0"
 pluggy = ">=0.5,<0.7"
diff --git a/tests/installation/test_installer.py b/tests/installation/test_installer.py
index c236141be44..dadbb6be82b 100644
--- a/tests/installation/test_installer.py
+++ b/tests/installation/test_installer.py
@@ -6,10 +6,10 @@
 
 from clikit.io import NullIO
 
+from poetry.core.packages import ProjectPackage
 from poetry.installation import Installer as BaseInstaller
 from poetry.installation.noop_installer import NoopInstaller
 from poetry.packages import Locker as BaseLocker
-from poetry.packages import ProjectPackage
 from poetry.repositories import Pool
 from poetry.repositories import Repository
 from poetry.repositories.installed_repository import InstalledRepository
diff --git a/tests/installation/test_pip_installer.py b/tests/installation/test_pip_installer.py
index fe40328aa1a..f3cf376ff39 100644
--- a/tests/installation/test_pip_installer.py
+++ b/tests/installation/test_pip_installer.py
@@ -1,8 +1,8 @@
 import pytest
 
+from poetry.core.packages.package import Package
 from poetry.installation.pip_installer import PipInstaller
 from poetry.io.null_io import NullIO
-from poetry.packages.package import Package
 from poetry.repositories.legacy_repository import LegacyRepository
 from poetry.repositories.pool import Pool
 from poetry.utils._compat import Path
diff --git a/tests/json/test_poetry_schema.py b/tests/json/test_poetry_schema.py
deleted file mode 100644
index 3086242cf25..00000000000
--- a/tests/json/test_poetry_schema.py
+++ /dev/null
@@ -1,21 +0,0 @@
-import pytest
-
-from poetry.json import validate_object
-
-
-@pytest.fixture
-def base_object():
-    return {
-        "name": "myapp",
-        "version": "1.0.0",
-        "description": "Some description.",
-        "dependencies": {"python": "^3.6"},
-        "dev-dependencies": {},
-    }
-
-
-def test_path_dependencies(base_object):
-    base_object["dependencies"].update({"foo": {"path": "../foo"}})
-    base_object["dev-dependencies"].update({"foo": {"path": "../foo"}})
-
-    assert len(validate_object(base_object, "poetry-schema")) == 0
diff --git a/tests/masonry/builders/fixtures/case_sensitive_exclusions/my_package/Foo/Bar.py b/tests/masonry/builders/fixtures/case_sensitive_exclusions/my_package/Foo/Bar.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/case_sensitive_exclusions/my_package/Foo/IncludedBar.py b/tests/masonry/builders/fixtures/case_sensitive_exclusions/my_package/Foo/IncludedBar.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/case_sensitive_exclusions/my_package/Foo/SecondBar.py b/tests/masonry/builders/fixtures/case_sensitive_exclusions/my_package/Foo/SecondBar.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/case_sensitive_exclusions/my_package/Foo/lowercasebar.py b/tests/masonry/builders/fixtures/case_sensitive_exclusions/my_package/Foo/lowercasebar.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/case_sensitive_exclusions/my_package/FooBar/Bar.py b/tests/masonry/builders/fixtures/case_sensitive_exclusions/my_package/FooBar/Bar.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/case_sensitive_exclusions/my_package/FooBar/lowercasebar.py b/tests/masonry/builders/fixtures/case_sensitive_exclusions/my_package/FooBar/lowercasebar.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/case_sensitive_exclusions/my_package/bar/CapitalFoo.py b/tests/masonry/builders/fixtures/case_sensitive_exclusions/my_package/bar/CapitalFoo.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/case_sensitive_exclusions/my_package/bar/foo.py b/tests/masonry/builders/fixtures/case_sensitive_exclusions/my_package/bar/foo.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/case_sensitive_exclusions/pyproject.toml b/tests/masonry/builders/fixtures/case_sensitive_exclusions/pyproject.toml
deleted file mode 100644
index 57d25a4314f..00000000000
--- a/tests/masonry/builders/fixtures/case_sensitive_exclusions/pyproject.toml
+++ /dev/null
@@ -1,49 +0,0 @@
-[tool.poetry]
-name = "my-package"
-version = "1.2.3"
-description = "Some description."
-authors = [
-    "Sébastien Eustace "
-]
-license = "MIT"
-
-readme = "README.rst"
-
-homepage = "https://python-poetry.org/"
-repository = "https://github.com/python-poetry/poetry"
-documentation = "https://python-poetry.org/docs"
-
-keywords = ["packaging", "dependency", "poetry"]
-
-classifiers = [
-    "Topic :: Software Development :: Build Tools",
-    "Topic :: Software Development :: Libraries :: Python Modules"
-]
-
-exclude = [
-    "**/SecondBar.py",
-    "my_package/FooBar/*",
-    "my_package/Foo/Bar.py",
-    "my_package/Foo/lowercasebar.py",
-    "my_package/bar/foo.py",
-    "my_package/bar/CapitalFoo.py"
-]
-
-# Requirements
-[tool.poetry.dependencies]
-python = "^3.6"
-cleo = "^0.6"
-cachy = { version = "^0.2.0", extras = ["msgpack"] }
-
-pendulum = { version = "^1.4", optional = true }
-
-[tool.poetry.dev-dependencies]
-pytest = "~3.4"
-
-[tool.poetry.extras]
-time = ["pendulum"]
-
-[tool.poetry.scripts]
-my-script = "my_package:main"
-my-2nd-script = "my_package:main2"
-extra-script = {callable = "my_package.extra:main", extras = ["time"]}
diff --git a/tests/masonry/builders/fixtures/complete/LICENSE b/tests/masonry/builders/fixtures/complete/LICENSE
deleted file mode 100644
index 44cf2b30e68..00000000000
--- a/tests/masonry/builders/fixtures/complete/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) 2018 Sébastien Eustace
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/tests/masonry/builders/fixtures/complete/my_package/__init__.py b/tests/masonry/builders/fixtures/complete/my_package/__init__.py
deleted file mode 100644
index 10aa336ce07..00000000000
--- a/tests/masonry/builders/fixtures/complete/my_package/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-__version__ = "1.2.3"
diff --git a/tests/masonry/builders/fixtures/complete/my_package/data1/test.json b/tests/masonry/builders/fixtures/complete/my_package/data1/test.json
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/complete/my_package/sub_pkg1/extra_file.xml b/tests/masonry/builders/fixtures/complete/my_package/sub_pkg1/extra_file.xml
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/complete/my_package/sub_pkg2/data2/data.json b/tests/masonry/builders/fixtures/complete/my_package/sub_pkg2/data2/data.json
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/complete/my_package/sub_pkg3/foo.py b/tests/masonry/builders/fixtures/complete/my_package/sub_pkg3/foo.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/complete/pyproject.toml b/tests/masonry/builders/fixtures/complete/pyproject.toml
deleted file mode 100644
index 13834964e82..00000000000
--- a/tests/masonry/builders/fixtures/complete/pyproject.toml
+++ /dev/null
@@ -1,53 +0,0 @@
-[tool.poetry]
-name = "my-package"
-version = "1.2.3"
-description = "Some description."
-authors = [
-    "Sébastien Eustace "
-]
-maintainers = [
-    "People Everywhere "
-]
-license = "MIT"
-
-readme = "README.rst"
-
-homepage = "https://python-poetry.org/"
-repository = "https://github.com/python-poetry/poetry"
-documentation = "https://python-poetry.org/docs"
-
-keywords = ["packaging", "dependency", "poetry"]
-
-classifiers = [
-    "Topic :: Software Development :: Build Tools",
-    "Topic :: Software Development :: Libraries :: Python Modules"
-]
-
-exclude = [
-    "**/*.xml"
-]
-
-# Requirements
-[tool.poetry.dependencies]
-python = "^3.6"
-cleo = "^0.6"
-cachy = { version = "^0.2.0", extras = ["msgpack"] }
-
-[tool.poetry.dependencies.pendulum]
-version = "^1.4"
-markers= 'python_version ~= "2.7" and sys_platform == "win32" or python_version in "3.4 3.5"'
-optional = true
-
-[tool.poetry.dev-dependencies]
-pytest = "~3.4"
-
-[tool.poetry.extras]
-time = ["pendulum"]
-
-[tool.poetry.scripts]
-my-script = "my_package:main"
-my-2nd-script = "my_package:main2"
-extra-script = {callable = "my_package.extra:main", extras = ["time"]}
-
-[tool.poetry.urls]
-"Issue Tracker" = "https://github.com/python-poetry/poetry/issues"
diff --git a/tests/masonry/builders/fixtures/default_with_excluded_data/LICENSE b/tests/masonry/builders/fixtures/default_with_excluded_data/LICENSE
deleted file mode 100644
index 44cf2b30e68..00000000000
--- a/tests/masonry/builders/fixtures/default_with_excluded_data/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) 2018 Sébastien Eustace
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/tests/masonry/builders/fixtures/default_with_excluded_data/README.rst b/tests/masonry/builders/fixtures/default_with_excluded_data/README.rst
deleted file mode 100644
index f7fe15470f9..00000000000
--- a/tests/masonry/builders/fixtures/default_with_excluded_data/README.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-My Package
-==========
diff --git a/tests/masonry/builders/fixtures/default_with_excluded_data/my_package/data/data1.txt b/tests/masonry/builders/fixtures/default_with_excluded_data/my_package/data/data1.txt
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/default_with_excluded_data/my_package/data/sub_data/data2.txt b/tests/masonry/builders/fixtures/default_with_excluded_data/my_package/data/sub_data/data2.txt
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/default_with_excluded_data/my_package/data/sub_data/data3.txt b/tests/masonry/builders/fixtures/default_with_excluded_data/my_package/data/sub_data/data3.txt
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/default_with_excluded_data/pyproject.toml b/tests/masonry/builders/fixtures/default_with_excluded_data/pyproject.toml
deleted file mode 100644
index 80e86166ad8..00000000000
--- a/tests/masonry/builders/fixtures/default_with_excluded_data/pyproject.toml
+++ /dev/null
@@ -1,39 +0,0 @@
-[tool.poetry]
-name = "my-package"
-version = "1.2.3"
-description = "Some description."
-authors = [
-    "Sébastien Eustace "
-]
-license = "MIT"
-
-readme = "README.rst"
-
-homepage = "https://python-poetry.org/"
-repository = "https://github.com/python-poetry/poetry"
-documentation = "https://python-poetry.org/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 = "^0.6"
-cachy = { version = "^0.2.0", extras = ["msgpack"] }
-
-pendulum = { version = "^1.4", optional = true }
-
-[tool.poetry.dev-dependencies]
-pytest = "~3.4"
-
-[tool.poetry.extras]
-time = ["pendulum"]
-
-[tool.poetry.scripts]
-my-script = "my_package:main"
-my-2nd-script = "my_package:main2"
diff --git a/tests/masonry/builders/fixtures/default_with_excluded_data_toml/LICENSE b/tests/masonry/builders/fixtures/default_with_excluded_data_toml/LICENSE
deleted file mode 100644
index 44cf2b30e68..00000000000
--- a/tests/masonry/builders/fixtures/default_with_excluded_data_toml/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) 2018 Sébastien Eustace
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/tests/masonry/builders/fixtures/default_with_excluded_data_toml/README.rst b/tests/masonry/builders/fixtures/default_with_excluded_data_toml/README.rst
deleted file mode 100644
index f7fe15470f9..00000000000
--- a/tests/masonry/builders/fixtures/default_with_excluded_data_toml/README.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-My Package
-==========
diff --git a/tests/masonry/builders/fixtures/default_with_excluded_data_toml/my_package/__init__.py b/tests/masonry/builders/fixtures/default_with_excluded_data_toml/my_package/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/default_with_excluded_data_toml/my_package/data/data1.txt b/tests/masonry/builders/fixtures/default_with_excluded_data_toml/my_package/data/data1.txt
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/default_with_excluded_data_toml/my_package/data/sub_data/data2.txt b/tests/masonry/builders/fixtures/default_with_excluded_data_toml/my_package/data/sub_data/data2.txt
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/default_with_excluded_data_toml/my_package/data/sub_data/data3.txt b/tests/masonry/builders/fixtures/default_with_excluded_data_toml/my_package/data/sub_data/data3.txt
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/default_with_excluded_data_toml/pyproject.toml b/tests/masonry/builders/fixtures/default_with_excluded_data_toml/pyproject.toml
deleted file mode 100644
index fcd31fa2007..00000000000
--- a/tests/masonry/builders/fixtures/default_with_excluded_data_toml/pyproject.toml
+++ /dev/null
@@ -1,41 +0,0 @@
-[tool.poetry]
-name = "my-package"
-version = "1.2.3"
-description = "Some description."
-authors = [
-    "Sébastien Eustace "
-]
-license = "MIT"
-
-readme = "README.rst"
-
-exclude = ["my_package/data/data1.txt"]
-
-homepage = "https://python-poetry.org/"
-repository = "https://github.com/python-poetry/poetry"
-documentation = "https://python-poetry.org/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 = "^0.6"
-cachy = { version = "^0.2.0", extras = ["msgpack"] }
-
-pendulum = { version = "^1.4", optional = true }
-
-[tool.poetry.dev-dependencies]
-pytest = "~3.4"
-
-[tool.poetry.extras]
-time = ["pendulum"]
-
-[tool.poetry.scripts]
-my-script = "my_package:main"
-my-2nd-script = "my_package:main2"
diff --git a/tests/masonry/builders/fixtures/exclude_nested_data_toml/LICENSE b/tests/masonry/builders/fixtures/exclude_nested_data_toml/LICENSE
deleted file mode 100644
index 44cf2b30e68..00000000000
--- a/tests/masonry/builders/fixtures/exclude_nested_data_toml/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) 2018 Sébastien Eustace
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/tests/masonry/builders/fixtures/exclude_nested_data_toml/README.rst b/tests/masonry/builders/fixtures/exclude_nested_data_toml/README.rst
deleted file mode 100644
index f7fe15470f9..00000000000
--- a/tests/masonry/builders/fixtures/exclude_nested_data_toml/README.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-My Package
-==========
diff --git a/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/__init__.py b/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/data/data1.txt b/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/data/data1.txt
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/data/data2.txt b/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/data/data2.txt
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/data/sub_data/data2.txt b/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/data/sub_data/data2.txt
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/data/sub_data/data3.txt b/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/data/sub_data/data3.txt
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/puplic/item1/itemdata1.txt b/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/puplic/item1/itemdata1.txt
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/puplic/item1/subitem/subitemdata.txt b/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/puplic/item1/subitem/subitemdata.txt
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/puplic/item2/itemdata2.txt b/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/puplic/item2/itemdata2.txt
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/puplic/publicdata.txt b/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/puplic/publicdata.txt
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/exclude_nested_data_toml/pyproject.toml b/tests/masonry/builders/fixtures/exclude_nested_data_toml/pyproject.toml
deleted file mode 100644
index 28cff3c5414..00000000000
--- a/tests/masonry/builders/fixtures/exclude_nested_data_toml/pyproject.toml
+++ /dev/null
@@ -1,42 +0,0 @@
-[tool.poetry]
-name = "my-package"
-version = "1.2.3"
-description = "Some description."
-authors = [
-    "Sébastien Eustace "
-]
-license = "MIT"
-
-readme = "README.rst"
-
-exclude = ["**/data/", "**/*/item*"]
-include = ["my_package/data/data2.txt"]
-
-homepage = "https://python-poetry.org/"
-repository = "https://github.com/python-poetry/poetry"
-documentation = "https://python-poetry.org/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 = "^0.6"
-cachy = { version = "^0.2.0", extras = ["msgpack"] }
-
-pendulum = { version = "^1.4", optional = true }
-
-[tool.poetry.dev-dependencies]
-pytest = "~3.4"
-
-[tool.poetry.extras]
-time = ["pendulum"]
-
-[tool.poetry.scripts]
-my-script = "my_package:main"
-my-2nd-script = "my_package:main2"
diff --git a/tests/masonry/builders/fixtures/extended/README.rst b/tests/masonry/builders/fixtures/extended/README.rst
deleted file mode 100644
index a7508bd515e..00000000000
--- a/tests/masonry/builders/fixtures/extended/README.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Module 1
-========
diff --git a/tests/masonry/builders/fixtures/extended/build.py b/tests/masonry/builders/fixtures/extended/build.py
deleted file mode 100644
index 5308ec59b05..00000000000
--- a/tests/masonry/builders/fixtures/extended/build.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from distutils.core import Extension
-
-extensions = [Extension("extended.extended", ["extended/extended.c"])]
-
-
-def build(setup_kwargs):
-    setup_kwargs.update({"ext_modules": extensions})
diff --git a/tests/masonry/builders/fixtures/extended/extended/__init__.py b/tests/masonry/builders/fixtures/extended/extended/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/extended/extended/extended.c b/tests/masonry/builders/fixtures/extended/extended/extended.c
deleted file mode 100644
index 25a028eb11e..00000000000
--- a/tests/masonry/builders/fixtures/extended/extended/extended.c
+++ /dev/null
@@ -1,58 +0,0 @@
-#include 
-
-
-static PyObject *hello(PyObject *self) {
-    return PyUnicode_FromString("Hello");
-}
-
-
-static PyMethodDef module_methods[] = {
-    {
-        "hello",
-        (PyCFunction) hello,
-        NULL,
-        PyDoc_STR("Say hello.")
-    },
-    {NULL}
-};
-
-#if PY_MAJOR_VERSION >= 3
-static struct PyModuleDef moduledef = {
-    PyModuleDef_HEAD_INIT,
-    "extended",
-    NULL,
-    -1,
-    module_methods,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-};
-#endif
-
-PyMODINIT_FUNC
-#if PY_MAJOR_VERSION >= 3
-PyInit_extended(void)
-#else
-init_extended(void)
-#endif
-{
-    PyObject *module;
-
-#if PY_MAJOR_VERSION >= 3
-    module = PyModule_Create(&moduledef);
-#else
-    module = Py_InitModule3("extended", module_methods, NULL);
-#endif
-
-    if (module == NULL)
-#if PY_MAJOR_VERSION >= 3
-        return NULL;
-#else
-        return;
-#endif
-
-#if PY_MAJOR_VERSION >= 3
-    return module;
-#endif
-}
diff --git a/tests/masonry/builders/fixtures/extended/pyproject.toml b/tests/masonry/builders/fixtures/extended/pyproject.toml
deleted file mode 100644
index f8e8bd8105f..00000000000
--- a/tests/masonry/builders/fixtures/extended/pyproject.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-[tool.poetry]
-name = "extended"
-version = "0.1"
-description = "Some description."
-authors = [
-    "Sébastien Eustace "
-]
-license = "MIT"
-
-readme = "README.rst"
-
-homepage = "https://python-poetry.org/"
-
-build = "build.py"
diff --git a/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/LICENSE b/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/LICENSE
deleted file mode 100644
index 44cf2b30e68..00000000000
--- a/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) 2018 Sébastien Eustace
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/README.rst b/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/README.rst
deleted file mode 100644
index f7fe15470f9..00000000000
--- a/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/README.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-My Package
-==========
diff --git a/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/my_package/Bar/foo/bar/Foo.py b/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/my_package/Bar/foo/bar/Foo.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/my_package/Foo/Bar.py b/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/my_package/Foo/Bar.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/my_package/Foo/IncludedBar.py b/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/my_package/Foo/IncludedBar.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/my_package/Foo/SecondBar.py b/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/my_package/Foo/SecondBar.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/my_package/Foo/lowercasebar.py b/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/my_package/Foo/lowercasebar.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/my_package/FooBar/Bar.py b/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/my_package/FooBar/Bar.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/my_package/FooBar/lowercasebar.py b/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/my_package/FooBar/lowercasebar.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/my_package/__init__.py b/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/my_package/__init__.py
deleted file mode 100644
index 10aa336ce07..00000000000
--- a/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/my_package/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-__version__ = "1.2.3"
diff --git a/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/pyproject.toml b/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/pyproject.toml
deleted file mode 100644
index 6ef10e5959b..00000000000
--- a/tests/masonry/builders/fixtures/invalid_case_sensitive_exclusions/pyproject.toml
+++ /dev/null
@@ -1,44 +0,0 @@
-[tool.poetry]
-name = "my-package"
-version = "1.2.3"
-description = "Some description."
-authors = [
-    "Sébastien Eustace "
-]
-license = "MIT"
-
-readme = "README.rst"
-
-homepage = "https://python-poetry.org/"
-repository = "https://github.com/python-poetry/poetry"
-documentation = "https://python-poetry.org/docs"
-
-keywords = ["packaging", "dependency", "poetry"]
-
-classifiers = [
-    "Topic :: Software Development :: Build Tools",
-    "Topic :: Software Development :: Libraries :: Python Modules"
-]
-
-exclude = [
-    "my_package/Bar/*/bar/*.py"
-]
-
-# Requirements
-[tool.poetry.dependencies]
-python = "^3.6"
-cleo = "^0.6"
-cachy = { version = "^0.2.0", extras = ["msgpack"] }
-
-pendulum = { version = "^1.4", optional = true }
-
-[tool.poetry.dev-dependencies]
-pytest = "~3.4"
-
-[tool.poetry.extras]
-time = ["pendulum"]
-
-[tool.poetry.scripts]
-my-script = "my_package:main"
-my-2nd-script = "my_package:main2"
-extra-script = {callable = "my_package.extra:main", extras = ["time"]}
diff --git a/tests/masonry/builders/fixtures/localversionlabel/localversionlabel.py b/tests/masonry/builders/fixtures/localversionlabel/localversionlabel.py
deleted file mode 100644
index 0f503ecd7c0..00000000000
--- a/tests/masonry/builders/fixtures/localversionlabel/localversionlabel.py
+++ /dev/null
@@ -1 +0,0 @@
-"""Test fixture for https://github.com/python-poetry/poetry/issues/756"""
diff --git a/tests/masonry/builders/fixtures/localversionlabel/pyproject.toml b/tests/masonry/builders/fixtures/localversionlabel/pyproject.toml
deleted file mode 100644
index 4b5f4dddb18..00000000000
--- a/tests/masonry/builders/fixtures/localversionlabel/pyproject.toml
+++ /dev/null
@@ -1,5 +0,0 @@
-[tool.poetry]
-name = "localversionlabel"
-description = "Local Version Label"
-version = "0.1-beta.1+gitbranch-buildno-1"
-authors = []
diff --git a/tests/masonry/builders/fixtures/module1/README.rst b/tests/masonry/builders/fixtures/module1/README.rst
deleted file mode 100644
index a7508bd515e..00000000000
--- a/tests/masonry/builders/fixtures/module1/README.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Module 1
-========
diff --git a/tests/masonry/builders/fixtures/module1/module1.py b/tests/masonry/builders/fixtures/module1/module1.py
deleted file mode 100644
index 7ef41c5d4ea..00000000000
--- a/tests/masonry/builders/fixtures/module1/module1.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""Example module"""
-
-__version__ = "0.1"
diff --git a/tests/masonry/builders/fixtures/module1/pyproject.toml b/tests/masonry/builders/fixtures/module1/pyproject.toml
deleted file mode 100644
index fd5af3aa164..00000000000
--- a/tests/masonry/builders/fixtures/module1/pyproject.toml
+++ /dev/null
@@ -1,16 +0,0 @@
-[tool.poetry]
-name = "module1"
-version = "0.1"
-description = "Some description."
-authors = [
-    "Sébastien Eustace "
-]
-license = "MIT"
-
-readme = "README.rst"
-
-homepage = "https://python-poetry.org/"
-
-
-[tool.poetry.dependencies]
-python = "*"
diff --git a/tests/masonry/builders/fixtures/prerelease/README.rst b/tests/masonry/builders/fixtures/prerelease/README.rst
deleted file mode 100644
index 77d54395b7d..00000000000
--- a/tests/masonry/builders/fixtures/prerelease/README.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Prerelease
-==========
diff --git a/tests/masonry/builders/fixtures/prerelease/prerelease.py b/tests/masonry/builders/fixtures/prerelease/prerelease.py
deleted file mode 100644
index 7ef41c5d4ea..00000000000
--- a/tests/masonry/builders/fixtures/prerelease/prerelease.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""Example module"""
-
-__version__ = "0.1"
diff --git a/tests/masonry/builders/fixtures/prerelease/pyproject.toml b/tests/masonry/builders/fixtures/prerelease/pyproject.toml
deleted file mode 100644
index 9e920c57ba1..00000000000
--- a/tests/masonry/builders/fixtures/prerelease/pyproject.toml
+++ /dev/null
@@ -1,12 +0,0 @@
-[tool.poetry]
-name = "prerelease"
-version = "0.1-beta.1"
-description = "Some description."
-authors = [
-    "Sébastien Eustace "
-]
-license = "MIT"
-
-readme = "README.rst"
-
-homepage = "https://python-poetry.org/"
diff --git a/tests/masonry/builders/fixtures/simple_version/README.rst b/tests/masonry/builders/fixtures/simple_version/README.rst
deleted file mode 100644
index a7508bd515e..00000000000
--- a/tests/masonry/builders/fixtures/simple_version/README.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Module 1
-========
diff --git a/tests/masonry/builders/fixtures/simple_version/pyproject.toml b/tests/masonry/builders/fixtures/simple_version/pyproject.toml
deleted file mode 100644
index 4a8767b9009..00000000000
--- a/tests/masonry/builders/fixtures/simple_version/pyproject.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-[tool.poetry]
-name = "simple-version"
-version = "0.1"
-description = "Some description."
-authors = [
-    "Sébastien Eustace "
-]
-
-readme = "README.rst"
-
-
-[tool.poetry.dependencies]
-python = "3.6"
diff --git a/tests/masonry/builders/fixtures/simple_version/simple_version.py b/tests/masonry/builders/fixtures/simple_version/simple_version.py
deleted file mode 100644
index 7ef41c5d4ea..00000000000
--- a/tests/masonry/builders/fixtures/simple_version/simple_version.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""Example module"""
-
-__version__ = "0.1"
diff --git a/tests/masonry/builders/fixtures/single_python/README.rst b/tests/masonry/builders/fixtures/single_python/README.rst
deleted file mode 100644
index 265d70d6a73..00000000000
--- a/tests/masonry/builders/fixtures/single_python/README.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Single Python
-=============
diff --git a/tests/masonry/builders/fixtures/single_python/pyproject.toml b/tests/masonry/builders/fixtures/single_python/pyproject.toml
deleted file mode 100644
index 5aca79eb23e..00000000000
--- a/tests/masonry/builders/fixtures/single_python/pyproject.toml
+++ /dev/null
@@ -1,16 +0,0 @@
-[tool.poetry]
-name = "single-python"
-version = "0.1"
-description = "Some description."
-authors = [
-    "Sébastien Eustace "
-]
-license = "MIT"
-
-readme = "README.rst"
-
-homepage = "https://python-poetry.org/"
-
-
-[tool.poetry.dependencies]
-python = "2.7.15"
diff --git a/tests/masonry/builders/fixtures/single_python/single_python.py b/tests/masonry/builders/fixtures/single_python/single_python.py
deleted file mode 100644
index 7ef41c5d4ea..00000000000
--- a/tests/masonry/builders/fixtures/single_python/single_python.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""Example module"""
-
-__version__ = "0.1"
diff --git a/tests/masonry/builders/fixtures/source_file/README.rst b/tests/masonry/builders/fixtures/source_file/README.rst
deleted file mode 100644
index a7508bd515e..00000000000
--- a/tests/masonry/builders/fixtures/source_file/README.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Module 1
-========
diff --git a/tests/masonry/builders/fixtures/source_file/pyproject.toml b/tests/masonry/builders/fixtures/source_file/pyproject.toml
deleted file mode 100644
index 34b77e4ddaf..00000000000
--- a/tests/masonry/builders/fixtures/source_file/pyproject.toml
+++ /dev/null
@@ -1,16 +0,0 @@
-[tool.poetry]
-name = "module-src"
-version = "0.1"
-description = "Some description."
-authors = [
-    "Sébastien Eustace "
-]
-license = "MIT"
-
-readme = "README.rst"
-
-homepage = "https://python-poetry.org/"
-
-
-[tool.poetry.dependencies]
-python = "*"
diff --git a/tests/masonry/builders/fixtures/source_file/src/module_src.py b/tests/masonry/builders/fixtures/source_file/src/module_src.py
deleted file mode 100644
index 7ef41c5d4ea..00000000000
--- a/tests/masonry/builders/fixtures/source_file/src/module_src.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""Example module"""
-
-__version__ = "0.1"
diff --git a/tests/masonry/builders/fixtures/source_package/README.rst b/tests/masonry/builders/fixtures/source_package/README.rst
deleted file mode 100644
index a7508bd515e..00000000000
--- a/tests/masonry/builders/fixtures/source_package/README.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Module 1
-========
diff --git a/tests/masonry/builders/fixtures/source_package/pyproject.toml b/tests/masonry/builders/fixtures/source_package/pyproject.toml
deleted file mode 100644
index 4456fdb6c69..00000000000
--- a/tests/masonry/builders/fixtures/source_package/pyproject.toml
+++ /dev/null
@@ -1,15 +0,0 @@
-[tool.poetry]
-name = "package-src"
-version = "0.1"
-description = "Some description."
-authors = [
-    "Sébastien Eustace "
-]
-license = "MIT"
-
-readme = "README.rst"
-
-homepage = "https://python-poetry.org/"
-
-[tool.poetry.dependencies]
-python = "*"
diff --git a/tests/masonry/builders/fixtures/source_package/src/package_src/__init__.py b/tests/masonry/builders/fixtures/source_package/src/package_src/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/source_package/src/package_src/module.py b/tests/masonry/builders/fixtures/source_package/src/package_src/module.py
deleted file mode 100644
index 7ef41c5d4ea..00000000000
--- a/tests/masonry/builders/fixtures/source_package/src/package_src/module.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""Example module"""
-
-__version__ = "0.1"
diff --git a/tests/masonry/builders/fixtures/src_extended/README.rst b/tests/masonry/builders/fixtures/src_extended/README.rst
deleted file mode 100644
index a7508bd515e..00000000000
--- a/tests/masonry/builders/fixtures/src_extended/README.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Module 1
-========
diff --git a/tests/masonry/builders/fixtures/src_extended/build.py b/tests/masonry/builders/fixtures/src_extended/build.py
deleted file mode 100644
index 707bcaf24d5..00000000000
--- a/tests/masonry/builders/fixtures/src_extended/build.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from distutils.core import Extension
-
-extensions = [Extension("extended.extended", ["src/extended/extended.c"])]
-
-
-def build(setup_kwargs):
-    setup_kwargs.update({"ext_modules": extensions})
diff --git a/tests/masonry/builders/fixtures/src_extended/pyproject.toml b/tests/masonry/builders/fixtures/src_extended/pyproject.toml
deleted file mode 100644
index f8e8bd8105f..00000000000
--- a/tests/masonry/builders/fixtures/src_extended/pyproject.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-[tool.poetry]
-name = "extended"
-version = "0.1"
-description = "Some description."
-authors = [
-    "Sébastien Eustace "
-]
-license = "MIT"
-
-readme = "README.rst"
-
-homepage = "https://python-poetry.org/"
-
-build = "build.py"
diff --git a/tests/masonry/builders/fixtures/src_extended/src/extended/__init__.py b/tests/masonry/builders/fixtures/src_extended/src/extended/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/src_extended/src/extended/extended.c b/tests/masonry/builders/fixtures/src_extended/src/extended/extended.c
deleted file mode 100644
index 25a028eb11e..00000000000
--- a/tests/masonry/builders/fixtures/src_extended/src/extended/extended.c
+++ /dev/null
@@ -1,58 +0,0 @@
-#include 
-
-
-static PyObject *hello(PyObject *self) {
-    return PyUnicode_FromString("Hello");
-}
-
-
-static PyMethodDef module_methods[] = {
-    {
-        "hello",
-        (PyCFunction) hello,
-        NULL,
-        PyDoc_STR("Say hello.")
-    },
-    {NULL}
-};
-
-#if PY_MAJOR_VERSION >= 3
-static struct PyModuleDef moduledef = {
-    PyModuleDef_HEAD_INIT,
-    "extended",
-    NULL,
-    -1,
-    module_methods,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-};
-#endif
-
-PyMODINIT_FUNC
-#if PY_MAJOR_VERSION >= 3
-PyInit_extended(void)
-#else
-init_extended(void)
-#endif
-{
-    PyObject *module;
-
-#if PY_MAJOR_VERSION >= 3
-    module = PyModule_Create(&moduledef);
-#else
-    module = Py_InitModule3("extended", module_methods, NULL);
-#endif
-
-    if (module == NULL)
-#if PY_MAJOR_VERSION >= 3
-        return NULL;
-#else
-        return;
-#endif
-
-#if PY_MAJOR_VERSION >= 3
-    return module;
-#endif
-}
diff --git a/tests/masonry/builders/fixtures/with-include/LICENSE b/tests/masonry/builders/fixtures/with-include/LICENSE
deleted file mode 100644
index 44cf2b30e68..00000000000
--- a/tests/masonry/builders/fixtures/with-include/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) 2018 Sébastien Eustace
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/tests/masonry/builders/fixtures/with-include/README.rst b/tests/masonry/builders/fixtures/with-include/README.rst
deleted file mode 100644
index f7fe15470f9..00000000000
--- a/tests/masonry/builders/fixtures/with-include/README.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-My Package
-==========
diff --git a/tests/masonry/builders/fixtures/with-include/extra_dir/__init__.py b/tests/masonry/builders/fixtures/with-include/extra_dir/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/with-include/extra_dir/sub_pkg/__init__.py b/tests/masonry/builders/fixtures/with-include/extra_dir/sub_pkg/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/with-include/for_wheel_only/__init__.py b/tests/masonry/builders/fixtures/with-include/for_wheel_only/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/with-include/package_with_include/__init__.py b/tests/masonry/builders/fixtures/with-include/package_with_include/__init__.py
deleted file mode 100644
index 10aa336ce07..00000000000
--- a/tests/masonry/builders/fixtures/with-include/package_with_include/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-__version__ = "1.2.3"
diff --git a/tests/masonry/builders/fixtures/with-include/src/src_package/__init__.py b/tests/masonry/builders/fixtures/with-include/src/src_package/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/with-include/tests/__init__.py b/tests/masonry/builders/fixtures/with-include/tests/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/with_url_dependency/pyproject.toml b/tests/masonry/builders/fixtures/with_url_dependency/pyproject.toml
deleted file mode 100644
index c78f7aed61c..00000000000
--- a/tests/masonry/builders/fixtures/with_url_dependency/pyproject.toml
+++ /dev/null
@@ -1,24 +0,0 @@
-[tool.poetry]
-name = "with-url-dependency"
-version = "1.2.3"
-description = "Some description."
-authors = [
-    "Sébastien Eustace "
-]
-license = "MIT"
-
-homepage = "https://python-poetry.org/"
-repository = "https://github.com/python-poetry/poetry"
-documentation = "https://python-poetry.org/docs"
-
-keywords = ["packaging", "dependency", "poetry"]
-
-classifiers = [
-    "Topic :: Software Development :: Build Tools",
-    "Topic :: Software Development :: Libraries :: Python Modules"
-]
-
-# Requirements
-[tool.poetry.dependencies]
-python = "^3.6"
-demo = { url = "https://python-poetry.org/distributions/demo-0.1.0-py2.py3-none-any.whl" }
diff --git a/tests/masonry/builders/fixtures/with_url_dependency/with_url_dependency/__init__.py b/tests/masonry/builders/fixtures/with_url_dependency/with_url_dependency/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/fixtures/with_vcs_dependency/pyproject.toml b/tests/masonry/builders/fixtures/with_vcs_dependency/pyproject.toml
deleted file mode 100644
index 6fb808ffaad..00000000000
--- a/tests/masonry/builders/fixtures/with_vcs_dependency/pyproject.toml
+++ /dev/null
@@ -1,24 +0,0 @@
-[tool.poetry]
-name = "with-vcs-dependency"
-version = "1.2.3"
-description = "Some description."
-authors = [
-    "Sébastien Eustace "
-]
-license = "MIT"
-
-homepage = "https://python-poetry.org/"
-repository = "https://github.com/python-poetry/poetry"
-documentation = "https://python-poetry.org/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" }
diff --git a/tests/masonry/builders/fixtures/with_vcs_dependency/with_vcs_dependency/__init__.py b/tests/masonry/builders/fixtures/with_vcs_dependency/with_vcs_dependency/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/builders/test_builder.py b/tests/masonry/builders/test_builder.py
deleted file mode 100644
index 70817e12851..00000000000
--- a/tests/masonry/builders/test_builder.py
+++ /dev/null
@@ -1,159 +0,0 @@
-# -*- coding: utf-8 -*-
-from email.parser import Parser
-
-from clikit.io import NullIO
-
-from poetry.factory import Factory
-from poetry.masonry.builders.builder import Builder
-from poetry.utils._compat import Path
-from poetry.utils.env import NullEnv
-
-
-def test_builder_find_excluded_files(mocker):
-    p = mocker.patch("poetry.vcs.git.Git.get_ignored_files")
-    p.return_value = []
-
-    builder = Builder(
-        Factory().create_poetry(Path(__file__).parent / "fixtures" / "complete"),
-        NullEnv(),
-        NullIO(),
-    )
-
-    assert builder.find_excluded_files() == {"my_package/sub_pkg1/extra_file.xml"}
-
-
-def test_builder_find_case_sensitive_excluded_files(mocker):
-    p = mocker.patch("poetry.vcs.git.Git.get_ignored_files")
-    p.return_value = []
-
-    builder = Builder(
-        Factory().create_poetry(
-            Path(__file__).parent / "fixtures" / "case_sensitive_exclusions"
-        ),
-        NullEnv(),
-        NullIO(),
-    )
-
-    assert builder.find_excluded_files() == {
-        "my_package/FooBar/Bar.py",
-        "my_package/FooBar/lowercasebar.py",
-        "my_package/Foo/SecondBar.py",
-        "my_package/Foo/Bar.py",
-        "my_package/Foo/lowercasebar.py",
-        "my_package/bar/foo.py",
-        "my_package/bar/CapitalFoo.py",
-    }
-
-
-def test_builder_find_invalid_case_sensitive_excluded_files(mocker):
-    p = mocker.patch("poetry.vcs.git.Git.get_ignored_files")
-    p.return_value = []
-
-    builder = Builder(
-        Factory().create_poetry(
-            Path(__file__).parent / "fixtures" / "invalid_case_sensitive_exclusions"
-        ),
-        NullEnv(),
-        NullIO(),
-    )
-
-    assert {"my_package/Bar/foo/bar/Foo.py"} == builder.find_excluded_files()
-
-
-def test_get_metadata_content():
-    builder = Builder(
-        Factory().create_poetry(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://python-poetry.org/"
-
-    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",
-        "Programming Language :: Python :: 3.8",
-        "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); (python_version ~= "2.7" and sys_platform == "win32" or python_version in "3.4 3.5") and (extra == "time")',
-    ]
-
-    urls = parsed.get_all("Project-URL")
-    assert urls == [
-        "Documentation, https://python-poetry.org/docs",
-        "Issue Tracker, https://github.com/python-poetry/poetry/issues",
-        "Repository, https://github.com/python-poetry/poetry",
-    ]
-
-
-def test_metadata_homepage_default():
-    builder = Builder(
-        Factory().create_poetry(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(
-        Factory().create_poetry(
-            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
-
-
-def test_metadata_with_url_dependencies():
-    builder = Builder(
-        Factory().create_poetry(
-            Path(__file__).parent / "fixtures" / "with_url_dependency"
-        ),
-        NullEnv(),
-        NullIO(),
-    )
-
-    metadata = Parser().parsestr(builder.get_metadata_content())
-
-    requires_dist = metadata["Requires-Dist"]
-
-    assert (
-        "demo @ https://python-poetry.org/distributions/demo-0.1.0-py2.py3-none-any.whl"
-        == requires_dist
-    )
diff --git a/tests/masonry/builders/test_complete.py b/tests/masonry/builders/test_complete.py
deleted file mode 100644
index 2f3b4b2db09..00000000000
--- a/tests/masonry/builders/test_complete.py
+++ /dev/null
@@ -1,481 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-import ast
-import os
-import re
-import shutil
-import sys
-import tarfile
-import tempfile
-import zipfile
-
-import pytest
-
-from clikit.io import NullIO
-
-from poetry import __version__
-from poetry.factory import Factory
-from poetry.masonry.builders import CompleteBuilder
-from poetry.utils._compat import Path
-from poetry.utils._compat import decode
-from poetry.utils.env import NullEnv
-
-
-fixtures_dir = Path(__file__).parent / "fixtures"
-
-
-@pytest.fixture(autouse=True)
-def setup():
-    clear_samples_dist()
-
-    yield
-
-    clear_samples_dist()
-
-
-def clear_samples_dist():
-    for dist in fixtures_dir.glob("**/dist"):
-        if dist.is_dir():
-            shutil.rmtree(str(dist))
-
-
-@pytest.mark.skipif(
-    sys.platform == "win32" and sys.version_info <= (3, 6),
-    reason="Disable test on Windows for Python <=3.6",
-)
-def test_wheel_c_extension():
-    module_path = fixtures_dir / "extended"
-    builder = CompleteBuilder(
-        Factory().create_poetry(module_path), NullEnv(execute=True), NullIO()
-    )
-    builder.build()
-
-    sdist = fixtures_dir / "extended" / "dist" / "extended-0.1.tar.gz"
-
-    assert sdist.exists()
-
-    with tarfile.open(str(sdist), "r") as tar:
-        assert "extended-0.1/build.py" in tar.getnames()
-        assert "extended-0.1/extended/extended.c" in tar.getnames()
-
-    whl = list((module_path / "dist").glob("extended-0.1-cp*-cp*-*.whl"))[0]
-
-    assert whl.exists()
-
-    zip = zipfile.ZipFile(str(whl))
-
-    has_compiled_extension = False
-    for name in zip.namelist():
-        if name.startswith("extended/extended") and name.endswith((".so", ".pyd")):
-            has_compiled_extension = True
-
-    assert has_compiled_extension
-
-    try:
-        wheel_data = decode(zip.read("extended-0.1.dist-info/WHEEL"))
-
-        assert (
-            re.match(
-                """(?m)^\
-Wheel-Version: 1.0
-Generator: poetry {}
-Root-Is-Purelib: false
-Tag: cp[23]\\d-cp[23]\\dm?u?-.+
-$""".format(
-                    __version__
-                ),
-                wheel_data,
-            )
-            is not None
-        )
-
-        records = decode(zip.read("extended-0.1.dist-info/RECORD"))
-
-        assert re.search(r"\s+extended/extended.*\.(so|pyd)", records) is not None
-    finally:
-        zip.close()
-
-
-@pytest.mark.skipif(
-    sys.platform == "win32" and sys.version_info <= (3, 6),
-    reason="Disable test on Windows for Python <=3.6",
-)
-def test_wheel_c_extension_src_layout():
-    module_path = fixtures_dir / "src_extended"
-    builder = CompleteBuilder(
-        Factory().create_poetry(module_path), NullEnv(execute=True), NullIO()
-    )
-    builder.build()
-
-    sdist = fixtures_dir / "src_extended" / "dist" / "extended-0.1.tar.gz"
-
-    assert sdist.exists()
-
-    with tarfile.open(str(sdist), "r") as tar:
-        assert "extended-0.1/build.py" in tar.getnames()
-        assert "extended-0.1/src/extended/extended.c" in tar.getnames()
-
-    whl = list((module_path / "dist").glob("extended-0.1-cp*-cp*-*.whl"))[0]
-
-    assert whl.exists()
-
-    zip = zipfile.ZipFile(str(whl))
-
-    has_compiled_extension = False
-    for name in zip.namelist():
-        if name.startswith("extended/extended") and name.endswith((".so", ".pyd")):
-            has_compiled_extension = True
-
-    assert has_compiled_extension
-
-    try:
-        wheel_data = decode(zip.read("extended-0.1.dist-info/WHEEL"))
-
-        assert (
-            re.match(
-                """(?m)^\
-Wheel-Version: 1.0
-Generator: poetry {}
-Root-Is-Purelib: false
-Tag: cp[23]\\d-cp[23]\\dm?u?-.+
-$""".format(
-                    __version__
-                ),
-                wheel_data,
-            )
-            is not None
-        )
-
-        records = decode(zip.read("extended-0.1.dist-info/RECORD"))
-
-        assert re.search(r"\s+extended/extended.*\.(so|pyd)", records) is not None
-    finally:
-        zip.close()
-
-
-def test_complete():
-    module_path = fixtures_dir / "complete"
-    builder = CompleteBuilder(
-        Factory().create_poetry(module_path), NullEnv(execute=True), NullIO()
-    )
-    builder.build()
-
-    whl = module_path / "dist" / "my_package-1.2.3-py3-none-any.whl"
-
-    assert whl.exists()
-    if sys.platform != "win32":
-        assert (os.stat(str(whl)).st_mode & 0o777) == 0o644
-
-    zip = zipfile.ZipFile(str(whl))
-
-    try:
-        assert "my_package/sub_pgk1/extra_file.xml" not in zip.namelist()
-
-        entry_points = zip.read("my_package-1.2.3.dist-info/entry_points.txt")
-
-        assert (
-            decode(entry_points.decode())
-            == """\
-[console_scripts]
-extra-script=my_package.extra:main[time]
-my-2nd-script=my_package:main2
-my-script=my_package:main
-
-"""
-        )
-        wheel_data = decode(zip.read("my_package-1.2.3.dist-info/WHEEL"))
-
-        assert (
-            wheel_data
-            == """\
-Wheel-Version: 1.0
-Generator: poetry {}
-Root-Is-Purelib: true
-Tag: py3-none-any
-""".format(
-                __version__
-            )
-        )
-        wheel_data = decode(zip.read("my_package-1.2.3.dist-info/METADATA"))
-
-        assert (
-            wheel_data
-            == """\
-Metadata-Version: 2.1
-Name: my-package
-Version: 1.2.3
-Summary: Some description.
-Home-page: https://python-poetry.org/
-License: MIT
-Keywords: packaging,dependency,poetry
-Author: Sébastien Eustace
-Author-email: sebastien@eustace.io
-Maintainer: People Everywhere
-Maintainer-email: people@everywhere.com
-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: Programming Language :: Python :: 3.8
-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); (python_version ~= "2.7" and sys_platform == "win32" or python_version in "3.4 3.5") and (extra == "time")
-Project-URL: Documentation, https://python-poetry.org/docs
-Project-URL: Issue Tracker, https://github.com/python-poetry/poetry/issues
-Project-URL: Repository, https://github.com/python-poetry/poetry
-Description-Content-Type: text/x-rst
-
-My Package
-==========
-
-"""
-        )
-    finally:
-        zip.close()
-
-
-def test_complete_no_vcs():
-    # Copy the complete fixtures dir to a temporary directory
-    module_path = fixtures_dir / "complete"
-    temporary_dir = Path(tempfile.mkdtemp()) / "complete"
-
-    shutil.copytree(module_path.as_posix(), temporary_dir.as_posix())
-
-    builder = CompleteBuilder(
-        Factory().create_poetry(temporary_dir), NullEnv(execute=True), NullIO()
-    )
-    builder.build()
-
-    whl = temporary_dir / "dist" / "my_package-1.2.3-py3-none-any.whl"
-
-    assert whl.exists()
-
-    zip = zipfile.ZipFile(str(whl))
-
-    # Check the zipped file to be sure that included and excluded files are
-    # correctly taken account of without vcs
-    expected_name_list = [
-        "my_package/__init__.py",
-        "my_package/data1/test.json",
-        "my_package/sub_pkg1/__init__.py",
-        "my_package/sub_pkg2/__init__.py",
-        "my_package/sub_pkg2/data2/data.json",
-        "my_package/sub_pkg3/foo.py",
-        "my_package-1.2.3.dist-info/entry_points.txt",
-        "my_package-1.2.3.dist-info/LICENSE",
-        "my_package-1.2.3.dist-info/WHEEL",
-        "my_package-1.2.3.dist-info/METADATA",
-        "my_package-1.2.3.dist-info/RECORD",
-    ]
-
-    assert sorted(zip.namelist()) == sorted(expected_name_list)
-
-    try:
-        entry_points = zip.read("my_package-1.2.3.dist-info/entry_points.txt")
-
-        assert (
-            decode(entry_points.decode())
-            == """\
-[console_scripts]
-extra-script=my_package.extra:main[time]
-my-2nd-script=my_package:main2
-my-script=my_package:main
-
-"""
-        )
-        wheel_data = decode(zip.read("my_package-1.2.3.dist-info/WHEEL"))
-
-        assert (
-            wheel_data
-            == """\
-Wheel-Version: 1.0
-Generator: poetry {}
-Root-Is-Purelib: true
-Tag: py3-none-any
-""".format(
-                __version__
-            )
-        )
-        wheel_data = decode(zip.read("my_package-1.2.3.dist-info/METADATA"))
-
-        assert (
-            wheel_data
-            == """\
-Metadata-Version: 2.1
-Name: my-package
-Version: 1.2.3
-Summary: Some description.
-Home-page: https://python-poetry.org/
-License: MIT
-Keywords: packaging,dependency,poetry
-Author: Sébastien Eustace
-Author-email: sebastien@eustace.io
-Maintainer: People Everywhere
-Maintainer-email: people@everywhere.com
-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: Programming Language :: Python :: 3.8
-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); (python_version ~= "2.7" and sys_platform == "win32" or python_version in "3.4 3.5") and (extra == "time")
-Project-URL: Documentation, https://python-poetry.org/docs
-Project-URL: Issue Tracker, https://github.com/python-poetry/poetry/issues
-Project-URL: Repository, https://github.com/python-poetry/poetry
-Description-Content-Type: text/x-rst
-
-My Package
-==========
-
-"""
-        )
-    finally:
-        zip.close()
-
-
-def test_module_src():
-    module_path = fixtures_dir / "source_file"
-    builder = CompleteBuilder(
-        Factory().create_poetry(module_path), NullEnv(execute=True), NullIO()
-    )
-    builder.build()
-
-    sdist = module_path / "dist" / "module-src-0.1.tar.gz"
-
-    assert sdist.exists()
-
-    with tarfile.open(str(sdist), "r") as tar:
-        assert "module-src-0.1/src/module_src.py" in tar.getnames()
-
-    whl = module_path / "dist" / "module_src-0.1-py2.py3-none-any.whl"
-
-    assert whl.exists()
-
-    zip = zipfile.ZipFile(str(whl))
-
-    try:
-        assert "module_src.py" in zip.namelist()
-    finally:
-        zip.close()
-
-
-def test_package_src():
-    module_path = fixtures_dir / "source_package"
-    builder = CompleteBuilder(
-        Factory().create_poetry(module_path), NullEnv(execute=True), NullIO()
-    )
-    builder.build()
-
-    sdist = module_path / "dist" / "package-src-0.1.tar.gz"
-
-    assert sdist.exists()
-
-    with tarfile.open(str(sdist), "r") as tar:
-        assert "package-src-0.1/src/package_src/module.py" in tar.getnames()
-
-    whl = module_path / "dist" / "package_src-0.1-py2.py3-none-any.whl"
-
-    assert whl.exists()
-
-    zip = zipfile.ZipFile(str(whl))
-
-    try:
-        assert "package_src/__init__.py" in zip.namelist()
-        assert "package_src/module.py" in zip.namelist()
-    finally:
-        zip.close()
-
-
-def test_package_with_include(mocker):
-    module_path = fixtures_dir / "with-include"
-
-    # Patch git module to return specific excluded files
-    p = mocker.patch("poetry.vcs.git.Git.get_ignored_files")
-    p.return_value = [
-        str(
-            Path(__file__).parent
-            / "fixtures"
-            / "with-include"
-            / "extra_dir"
-            / "vcs_excluded.txt"
-        ),
-        str(
-            Path(__file__).parent
-            / "fixtures"
-            / "with-include"
-            / "extra_dir"
-            / "sub_pkg"
-            / "vcs_excluded.txt"
-        ),
-    ]
-    builder = CompleteBuilder(Factory().create_poetry(module_path), NullEnv(), NullIO())
-    builder.build()
-
-    sdist = fixtures_dir / "with-include" / "dist" / "with-include-1.2.3.tar.gz"
-
-    assert sdist.exists()
-
-    with tarfile.open(str(sdist), "r") as tar:
-        names = tar.getnames()
-        assert len(names) == len(set(names))
-        assert "with-include-1.2.3/LICENSE" in names
-        assert "with-include-1.2.3/README.rst" in names
-        assert "with-include-1.2.3/extra_dir/__init__.py" in names
-        assert "with-include-1.2.3/extra_dir/vcs_excluded.txt" in names
-        assert "with-include-1.2.3/extra_dir/sub_pkg/__init__.py" in names
-        assert "with-include-1.2.3/extra_dir/sub_pkg/vcs_excluded.txt" not in names
-        assert "with-include-1.2.3/my_module.py" in names
-        assert "with-include-1.2.3/notes.txt" in names
-        assert "with-include-1.2.3/package_with_include/__init__.py" in names
-        assert "with-include-1.2.3/tests/__init__.py" in names
-        assert "with-include-1.2.3/pyproject.toml" in names
-        assert "with-include-1.2.3/setup.py" in names
-        assert "with-include-1.2.3/PKG-INFO" in names
-        assert "with-include-1.2.3/for_wheel_only/__init__.py" not in names
-        assert "with-include-1.2.3/src/src_package/__init__.py" in names
-
-        setup = tar.extractfile("with-include-1.2.3/setup.py").read()
-        setup_ast = ast.parse(setup)
-
-        setup_ast.body = [n for n in setup_ast.body if isinstance(n, ast.Assign)]
-        ns = {}
-        exec(compile(setup_ast, filename="setup.py", mode="exec"), ns)
-        assert ns["package_dir"] == {"": "src"}
-        assert ns["packages"] == [
-            "extra_dir",
-            "extra_dir.sub_pkg",
-            "package_with_include",
-            "src_package",
-            "tests",
-        ]
-        assert ns["package_data"] == {"": ["*"]}
-        assert ns["modules"] == ["my_module"]
-
-    whl = module_path / "dist" / "with_include-1.2.3-py3-none-any.whl"
-
-    assert whl.exists()
-
-    with zipfile.ZipFile(str(whl)) as z:
-        names = z.namelist()
-        assert len(names) == len(set(names))
-        assert "with_include-1.2.3.dist-info/LICENSE" in names
-        assert "extra_dir/__init__.py" in names
-        assert "extra_dir/vcs_excluded.txt" in names
-        assert "extra_dir/sub_pkg/__init__.py" in names
-        assert "extra_dir/sub_pkg/vcs_excluded.txt" not in names
-        assert "for_wheel_only/__init__.py" in names
-        assert "my_module.py" in names
-        assert "notes.txt" in names
-        assert "package_with_include/__init__.py" in names
-        assert "tests/__init__.py" not in names
-        assert "src_package/__init__.py" in names
diff --git a/tests/masonry/builders/test_editable.py b/tests/masonry/builders/test_editable.py
deleted file mode 100644
index d1121243ca4..00000000000
--- a/tests/masonry/builders/test_editable.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-import sys
-
-from clikit.io import NullIO
-
-from poetry.factory import Factory
-from poetry.masonry.builders import EditableBuilder
-from poetry.utils._compat import Path
-from poetry.utils.env import MockEnv
-
-
-fixtures_dir = Path(__file__).parent / "fixtures"
-
-
-def test_build_should_delegate_to_pip_for_non_pure_python_packages(tmp_dir, mocker):
-    move = mocker.patch("shutil.move")
-    tmp_dir = Path(tmp_dir)
-    env = MockEnv(path=tmp_dir, pip_version="18.1", execute=False, sys_path=[])
-    module_path = fixtures_dir / "extended"
-
-    builder = EditableBuilder(Factory().create_poetry(module_path), env, NullIO())
-    builder.build()
-
-    expected = [[sys.executable, "-m", "pip", "install", "-e", str(module_path)]]
-    assert expected == env.executed
-
-    assert 0 == move.call_count
-
-
-def test_build_should_temporarily_remove_the_pyproject_file(tmp_dir, mocker):
-    move = mocker.patch("shutil.move")
-    tmp_dir = Path(tmp_dir)
-    env = MockEnv(path=tmp_dir, pip_version="19.1", execute=False, sys_path=[])
-    module_path = fixtures_dir / "extended"
-
-    builder = EditableBuilder(Factory().create_poetry(module_path), env, NullIO())
-    builder.build()
-
-    expected = [[sys.executable, "-m", "pip", "install", "-e", str(module_path)]]
-    assert expected == env.executed
-
-    assert 2 == move.call_count
-
-    expected_calls = [
-        mocker.call(
-            str(module_path / "pyproject.toml"), str(module_path / "pyproject.tmp")
-        ),
-        mocker.call(
-            str(module_path / "pyproject.tmp"), str(module_path / "pyproject.toml")
-        ),
-    ]
-
-    assert expected_calls == move.call_args_list
diff --git a/tests/masonry/builders/test_sdist.py b/tests/masonry/builders/test_sdist.py
deleted file mode 100644
index 670289f9fb0..00000000000
--- a/tests/masonry/builders/test_sdist.py
+++ /dev/null
@@ -1,475 +0,0 @@
-# -*- coding: utf-8 -*-
-import ast
-import shutil
-import tarfile
-
-from email.parser import Parser
-
-import pytest
-
-from clikit.io import NullIO
-
-from poetry.factory import Factory
-from poetry.masonry.builders.sdist import SdistBuilder
-from poetry.masonry.utils.package_include import PackageInclude
-from poetry.packages import Package
-from poetry.packages.vcs_dependency import VCSDependency
-from poetry.utils._compat import Path
-from poetry.utils._compat import to_str
-from poetry.utils.env import NullEnv
-from tests.helpers import get_dependency
-
-
-fixtures_dir = Path(__file__).parent / "fixtures"
-
-
-@pytest.fixture(autouse=True)
-def setup():
-    clear_samples_dist()
-
-    yield
-
-    clear_samples_dist()
-
-
-def clear_samples_dist():
-    for dist in fixtures_dir.glob("**/dist"):
-        if dist.is_dir():
-            shutil.rmtree(str(dist))
-
-
-def project(name):
-    return Path(__file__).parent / "fixtures" / name
-
-
-def test_convert_dependencies():
-    package = Package("foo", "1.2.3")
-    result = SdistBuilder.convert_dependencies(
-        package,
-        [
-            get_dependency("A", "^1.0"),
-            get_dependency("B", "~1.0"),
-            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",
-        "D @ git+https://github.com/sdispater/d.git@master",
-    ]
-    extras = {}
-
-    assert result == (main, extras)
-
-    package = Package("foo", "1.2.3")
-    package.extras = {"bar": [get_dependency("A")]}
-
-    result = SdistBuilder.convert_dependencies(
-        package,
-        [
-            get_dependency("A", ">=1.2", optional=True),
-            get_dependency("B", "~1.0"),
-            get_dependency("C", "1.2.3"),
-        ],
-    )
-    main = ["B>=1.0,<1.1", "C==1.2.3"]
-    extras = {"bar": ["A>=1.2"]}
-
-    assert result == (main, extras)
-
-    c = get_dependency("C", "1.2.3")
-    c.python_versions = "~2.7 || ^3.6"
-    d = get_dependency("D", "3.4.5", optional=True)
-    d.python_versions = "~2.7 || ^3.4"
-
-    package.extras = {"baz": [get_dependency("D")]}
-
-    result = SdistBuilder.convert_dependencies(
-        package,
-        [
-            get_dependency("A", ">=1.2", optional=True),
-            get_dependency("B", "~1.0"),
-            c,
-            d,
-        ],
-    )
-    main = ["B>=1.0,<1.1"]
-
-    extra_python = (
-        ':python_version >= "2.7" and python_version < "2.8" '
-        'or python_version >= "3.6" and python_version < "4.0"'
-    )
-    extra_d_dependency = (
-        'baz:python_version >= "2.7" and python_version < "2.8" '
-        'or python_version >= "3.4" and python_version < "4.0"'
-    )
-    extras = {extra_python: ["C==1.2.3"], extra_d_dependency: ["D==3.4.5"]}
-
-    assert result == (main, extras)
-
-
-def test_make_setup():
-    poetry = Factory().create_poetry(project("complete"))
-
-    builder = SdistBuilder(poetry, NullEnv(), NullIO())
-    setup = builder.build_setup()
-    setup_ast = ast.parse(setup)
-
-    setup_ast.body = [n for n in setup_ast.body if isinstance(n, ast.Assign)]
-    ns = {}
-    exec(compile(setup_ast, filename="setup.py", mode="exec"), ns)
-    assert ns["packages"] == [
-        "my_package",
-        "my_package.sub_pkg1",
-        "my_package.sub_pkg2",
-        "my_package.sub_pkg3",
-    ]
-    assert ns["install_requires"] == ["cachy[msgpack]>=0.2.0,<0.3.0", "cleo>=0.6,<0.7"]
-    assert ns["entry_points"] == {
-        "console_scripts": [
-            "extra-script = my_package.extra:main[time]",
-            "my-2nd-script = my_package:main2",
-            "my-script = my_package:main",
-        ]
-    }
-    assert ns["extras_require"] == {
-        'time:python_version ~= "2.7" and sys_platform == "win32" or python_version in "3.4 3.5"': [
-            "pendulum>=1.4,<2.0"
-        ]
-    }
-
-
-def test_make_pkg_info(mocker):
-    get_metadata_content = mocker.patch(
-        "poetry.masonry.builders.builder.Builder.get_metadata_content"
-    )
-    poetry = Factory().create_poetry(project("complete"))
-
-    builder = SdistBuilder(poetry, NullEnv(), NullIO())
-    builder.build_pkg_info()
-
-    assert get_metadata_content.called
-
-
-def test_make_pkg_info_any_python():
-    poetry = Factory().create_poetry(project("module1"))
-
-    builder = SdistBuilder(poetry, NullEnv(), NullIO())
-    pkg_info = builder.build_pkg_info()
-    p = Parser()
-    parsed = p.parsestr(to_str(pkg_info))
-
-    assert "Requires-Python" not in parsed
-
-
-def test_find_files_to_add():
-    poetry = Factory().create_poetry(project("complete"))
-
-    builder = SdistBuilder(poetry, NullEnv(), NullIO())
-    result = builder.find_files_to_add()
-
-    assert sorted(result) == sorted(
-        [
-            Path("LICENSE"),
-            Path("README.rst"),
-            Path("my_package/__init__.py"),
-            Path("my_package/data1/test.json"),
-            Path("my_package/sub_pkg1/__init__.py"),
-            Path("my_package/sub_pkg2/__init__.py"),
-            Path("my_package/sub_pkg2/data2/data.json"),
-            Path("my_package/sub_pkg3/foo.py"),
-            Path("pyproject.toml"),
-        ]
-    )
-
-
-def test_make_pkg_info_multi_constraints_dependency():
-    poetry = Factory().create_poetry(
-        Path(__file__).parent.parent.parent
-        / "fixtures"
-        / "project_with_multi_constraints_dependency"
-    )
-
-    builder = SdistBuilder(poetry, NullEnv(), NullIO())
-    pkg_info = builder.build_pkg_info()
-    p = Parser()
-    parsed = p.parsestr(to_str(pkg_info))
-
-    requires = parsed.get_all("Requires-Dist")
-    assert requires == [
-        'pendulum (>=1.5,<2.0); python_version < "3.4"',
-        'pendulum (>=2.0,<3.0); python_version >= "3.4" and python_version < "4.0"',
-    ]
-
-
-def test_find_packages():
-    poetry = Factory().create_poetry(project("complete"))
-
-    builder = SdistBuilder(poetry, NullEnv(), NullIO())
-
-    base = project("complete")
-    include = PackageInclude(base, "my_package")
-
-    pkg_dir, packages, pkg_data = builder.find_packages(include)
-
-    assert pkg_dir is None
-    assert packages == [
-        "my_package",
-        "my_package.sub_pkg1",
-        "my_package.sub_pkg2",
-        "my_package.sub_pkg3",
-    ]
-    assert pkg_data == {
-        "": ["*"],
-        "my_package": ["data1/*"],
-        "my_package.sub_pkg2": ["data2/*"],
-    }
-
-    poetry = Factory().create_poetry(project("source_package"))
-
-    builder = SdistBuilder(poetry, NullEnv(), NullIO())
-
-    base = project("source_package")
-    include = PackageInclude(base, "package_src", source="src")
-
-    pkg_dir, packages, pkg_data = builder.find_packages(include)
-
-    assert pkg_dir == str(base / "src")
-    assert packages == ["package_src"]
-    assert pkg_data == {"": ["*"]}
-
-
-def test_package():
-    poetry = Factory().create_poetry(project("complete"))
-
-    builder = SdistBuilder(poetry, NullEnv(), NullIO())
-    builder.build()
-
-    sdist = fixtures_dir / "complete" / "dist" / "my-package-1.2.3.tar.gz"
-
-    assert sdist.exists()
-
-    with tarfile.open(str(sdist), "r") as tar:
-        assert "my-package-1.2.3/LICENSE" in tar.getnames()
-
-
-def test_module():
-    poetry = Factory().create_poetry(project("module1"))
-
-    builder = SdistBuilder(poetry, NullEnv(), NullIO())
-    builder.build()
-
-    sdist = fixtures_dir / "module1" / "dist" / "module1-0.1.tar.gz"
-
-    assert sdist.exists()
-
-    with tarfile.open(str(sdist), "r") as tar:
-        assert "module1-0.1/module1.py" in tar.getnames()
-
-
-def test_prelease():
-    poetry = Factory().create_poetry(project("prerelease"))
-
-    builder = SdistBuilder(poetry, NullEnv(), NullIO())
-    builder.build()
-
-    sdist = fixtures_dir / "prerelease" / "dist" / "prerelease-0.1b1.tar.gz"
-
-    assert sdist.exists()
-
-
-def test_with_c_extensions():
-    poetry = Factory().create_poetry(project("extended"))
-
-    builder = SdistBuilder(poetry, NullEnv(), NullIO())
-    builder.build()
-
-    sdist = fixtures_dir / "extended" / "dist" / "extended-0.1.tar.gz"
-
-    assert sdist.exists()
-
-    with tarfile.open(str(sdist), "r") as tar:
-        assert "extended-0.1/build.py" in tar.getnames()
-        assert "extended-0.1/extended/extended.c" in tar.getnames()
-
-
-def test_with_c_extensions_src_layout():
-    poetry = Factory().create_poetry(project("src_extended"))
-
-    builder = SdistBuilder(poetry, NullEnv(), NullIO())
-    builder.build()
-
-    sdist = fixtures_dir / "src_extended" / "dist" / "extended-0.1.tar.gz"
-
-    assert sdist.exists()
-
-    with tarfile.open(str(sdist), "r") as tar:
-        assert "extended-0.1/build.py" in tar.getnames()
-        assert "extended-0.1/src/extended/extended.c" in tar.getnames()
-
-
-def test_with_src_module_file():
-    poetry = Factory().create_poetry(project("source_file"))
-
-    builder = SdistBuilder(poetry, NullEnv(), NullIO())
-
-    # Check setup.py
-    setup = builder.build_setup()
-    setup_ast = ast.parse(setup)
-
-    setup_ast.body = [n for n in setup_ast.body if isinstance(n, ast.Assign)]
-    ns = {}
-    exec(compile(setup_ast, filename="setup.py", mode="exec"), ns)
-    assert ns["package_dir"] == {"": "src"}
-    assert ns["modules"] == ["module_src"]
-
-    builder.build()
-
-    sdist = fixtures_dir / "source_file" / "dist" / "module-src-0.1.tar.gz"
-
-    assert sdist.exists()
-
-    with tarfile.open(str(sdist), "r") as tar:
-        assert "module-src-0.1/src/module_src.py" in tar.getnames()
-
-
-def test_with_src_module_dir():
-    poetry = Factory().create_poetry(project("source_package"))
-
-    builder = SdistBuilder(poetry, NullEnv(), NullIO())
-
-    # Check setup.py
-    setup = builder.build_setup()
-    setup_ast = ast.parse(setup)
-
-    setup_ast.body = [n for n in setup_ast.body if isinstance(n, ast.Assign)]
-    ns = {}
-    exec(compile(setup_ast, filename="setup.py", mode="exec"), ns)
-    assert ns["package_dir"] == {"": "src"}
-    assert ns["packages"] == ["package_src"]
-
-    builder.build()
-
-    sdist = fixtures_dir / "source_package" / "dist" / "package-src-0.1.tar.gz"
-
-    assert sdist.exists()
-
-    with tarfile.open(str(sdist), "r") as tar:
-        assert "package-src-0.1/src/package_src/__init__.py" in tar.getnames()
-        assert "package-src-0.1/src/package_src/module.py" in tar.getnames()
-
-
-def test_default_with_excluded_data(mocker):
-    # Patch git module to return specific excluded files
-    p = mocker.patch("poetry.vcs.git.Git.get_ignored_files")
-    p.return_value = [
-        (
-            (
-                Path(__file__).parent
-                / "fixtures"
-                / "default_with_excluded_data"
-                / "my_package"
-                / "data"
-                / "sub_data"
-                / "data2.txt"
-            )
-            .relative_to(project("default_with_excluded_data"))
-            .as_posix()
-        )
-    ]
-    poetry = Factory().create_poetry(project("default_with_excluded_data"))
-
-    builder = SdistBuilder(poetry, NullEnv(), NullIO())
-
-    # Check setup.py
-    setup = builder.build_setup()
-    setup_ast = ast.parse(setup)
-
-    setup_ast.body = [n for n in setup_ast.body if isinstance(n, ast.Assign)]
-    ns = {}
-    exec(compile(setup_ast, filename="setup.py", mode="exec"), ns)
-    assert "package_dir" not in ns
-    assert ns["packages"] == ["my_package"]
-    assert ns["package_data"] == {
-        "": ["*"],
-        "my_package": ["data/*", "data/sub_data/data3.txt"],
-    }
-
-    builder.build()
-
-    sdist = (
-        fixtures_dir / "default_with_excluded_data" / "dist" / "my-package-1.2.3.tar.gz"
-    )
-
-    assert sdist.exists()
-
-    with tarfile.open(str(sdist), "r") as tar:
-        names = tar.getnames()
-        assert len(names) == len(set(names))
-        assert "my-package-1.2.3/LICENSE" in names
-        assert "my-package-1.2.3/README.rst" in names
-        assert "my-package-1.2.3/my_package/__init__.py" in names
-        assert "my-package-1.2.3/my_package/data/data1.txt" in names
-        assert "my-package-1.2.3/pyproject.toml" in names
-        assert "my-package-1.2.3/setup.py" in names
-        assert "my-package-1.2.3/PKG-INFO" in names
-        # all last modified times should be set to a valid timestamp
-        for tarinfo in tar.getmembers():
-            assert 0 < tarinfo.mtime
-
-
-def test_src_excluded_nested_data():
-    module_path = fixtures_dir / "exclude_nested_data_toml"
-    poetry = Factory().create_poetry(module_path)
-
-    builder = SdistBuilder(poetry, NullEnv(), NullIO())
-    builder.build()
-
-    sdist = module_path / "dist" / "my-package-1.2.3.tar.gz"
-
-    assert sdist.exists()
-
-    with tarfile.open(str(sdist), "r") as tar:
-        names = tar.getnames()
-        assert len(names) == len(set(names))
-        assert "my-package-1.2.3/LICENSE" in names
-        assert "my-package-1.2.3/README.rst" in names
-        assert "my-package-1.2.3/pyproject.toml" in names
-        assert "my-package-1.2.3/setup.py" in names
-        assert "my-package-1.2.3/PKG-INFO" in names
-        assert "my-package-1.2.3/my_package/__init__.py" in names
-        assert "my-package-1.2.3/my_package/data/sub_data/data2.txt" not in names
-        assert "my-package-1.2.3/my_package/data/sub_data/data3.txt" not in names
-        assert "my-package-1.2.3/my_package/data/data1.txt" not in names
-        assert "my-package-1.2.3/my_package/data/data2.txt" in names
-        assert "my-package-1.2.3/my_package/puplic/publicdata.txt" in names
-        assert "my-package-1.2.3/my_package/public/item1/itemdata1.txt" not in names
-        assert (
-            "my-package-1.2.3/my_package/public/item1/subitem/subitemdata.txt"
-            not in names
-        )
-        assert "my-package-1.2.3/my_package/public/item2/itemdata2.txt" not in names
-
-
-def test_proper_python_requires_if_two_digits_precision_version_specified():
-    poetry = Factory().create_poetry(project("simple_version"))
-
-    builder = SdistBuilder(poetry, NullEnv(), NullIO())
-    pkg_info = builder.build_pkg_info()
-    p = Parser()
-    parsed = p.parsestr(to_str(pkg_info))
-
-    assert parsed["Requires-Python"] == ">=3.6,<3.7"
-
-
-def test_proper_python_requires_if_three_digits_precision_version_specified():
-    poetry = Factory().create_poetry(project("single_python"))
-
-    builder = SdistBuilder(poetry, NullEnv(), NullIO())
-    pkg_info = builder.build_pkg_info()
-    p = Parser()
-    parsed = p.parsestr(to_str(pkg_info))
-
-    assert parsed["Requires-Python"] == "==2.7.15"
diff --git a/tests/masonry/builders/test_wheel.py b/tests/masonry/builders/test_wheel.py
deleted file mode 100644
index ec3de8f7a60..00000000000
--- a/tests/masonry/builders/test_wheel.py
+++ /dev/null
@@ -1,164 +0,0 @@
-# -*- coding: utf-8 -*-
-import shutil
-import zipfile
-
-import pytest
-
-from clikit.io import NullIO
-
-from poetry.factory import Factory
-from poetry.masonry.builders.wheel import WheelBuilder
-from poetry.masonry.publishing.uploader import Uploader
-from poetry.utils._compat import Path
-from poetry.utils.env import NullEnv
-
-
-fixtures_dir = Path(__file__).parent / "fixtures"
-
-
-@pytest.fixture(autouse=True)
-def setup():
-    clear_samples_dist()
-
-    yield
-
-    clear_samples_dist()
-
-
-def clear_samples_dist():
-    for dist in fixtures_dir.glob("**/dist"):
-        if dist.is_dir():
-            shutil.rmtree(str(dist))
-
-
-def test_wheel_module():
-    module_path = fixtures_dir / "module1"
-    WheelBuilder.make(Factory().create_poetry(module_path), NullEnv(), NullIO())
-
-    whl = module_path / "dist" / "module1-0.1-py2.py3-none-any.whl"
-
-    assert whl.exists()
-
-    with zipfile.ZipFile(str(whl)) as z:
-        assert "module1.py" in z.namelist()
-
-
-def test_wheel_package():
-    module_path = fixtures_dir / "complete"
-    WheelBuilder.make(Factory().create_poetry(module_path), NullEnv(), NullIO())
-
-    whl = module_path / "dist" / "my_package-1.2.3-py3-none-any.whl"
-
-    assert whl.exists()
-
-    with zipfile.ZipFile(str(whl)) as z:
-        assert "my_package/sub_pkg1/__init__.py" in z.namelist()
-
-
-def test_wheel_prerelease():
-    module_path = fixtures_dir / "prerelease"
-    WheelBuilder.make(Factory().create_poetry(module_path), NullEnv(), NullIO())
-
-    whl = module_path / "dist" / "prerelease-0.1b1-py2.py3-none-any.whl"
-
-    assert whl.exists()
-
-
-def test_wheel_excluded_data():
-    module_path = fixtures_dir / "default_with_excluded_data_toml"
-    WheelBuilder.make(Factory().create_poetry(module_path), NullEnv(), NullIO())
-
-    whl = module_path / "dist" / "my_package-1.2.3-py3-none-any.whl"
-
-    assert whl.exists()
-
-    with zipfile.ZipFile(str(whl)) as z:
-        assert "my_package/__init__.py" in z.namelist()
-        assert "my_package/data/sub_data/data2.txt" in z.namelist()
-        assert "my_package/data/sub_data/data3.txt" in z.namelist()
-        assert "my_package/data/data1.txt" not in z.namelist()
-
-
-def test_wheel_excluded_nested_data():
-    module_path = fixtures_dir / "exclude_nested_data_toml"
-    poetry = Factory().create_poetry(module_path)
-    WheelBuilder.make(poetry, NullEnv(), NullIO())
-
-    whl = module_path / "dist" / "my_package-1.2.3-py3-none-any.whl"
-
-    assert whl.exists()
-
-    with zipfile.ZipFile(str(whl)) as z:
-        assert "my_package/__init__.py" in z.namelist()
-        assert "my_package/data/sub_data/data2.txt" not in z.namelist()
-        assert "my_package/data/sub_data/data3.txt" not in z.namelist()
-        assert "my_package/data/data1.txt" not in z.namelist()
-        assert "my_package/data/data2.txt" in z.namelist()
-        assert "my_package/puplic/publicdata.txt" in z.namelist()
-        assert "my_package/public/item1/itemdata1.txt" not in z.namelist()
-        assert "my_package/public/item1/subitem/subitemdata.txt" not in z.namelist()
-        assert "my_package/public/item2/itemdata2.txt" not in z.namelist()
-
-
-def test_wheel_localversionlabel():
-    module_path = fixtures_dir / "localversionlabel"
-    project = Factory().create_poetry(module_path)
-    WheelBuilder.make(project, NullEnv(), NullIO())
-    local_version_string = "localversionlabel-0.1b1+gitbranch.buildno.1"
-    whl = module_path / "dist" / (local_version_string + "-py2.py3-none-any.whl")
-
-    assert whl.exists()
-
-    with zipfile.ZipFile(str(whl)) as z:
-        assert local_version_string + ".dist-info/METADATA" in z.namelist()
-
-    uploader = Uploader(project, NullIO())
-    assert whl in uploader.files
-
-
-def test_wheel_package_src():
-    module_path = fixtures_dir / "source_package"
-    WheelBuilder.make(Factory().create_poetry(module_path), NullEnv(), NullIO())
-
-    whl = module_path / "dist" / "package_src-0.1-py2.py3-none-any.whl"
-
-    assert whl.exists()
-
-    with zipfile.ZipFile(str(whl)) as z:
-        assert "package_src/__init__.py" in z.namelist()
-        assert "package_src/module.py" in z.namelist()
-
-
-def test_wheel_module_src():
-    module_path = fixtures_dir / "source_file"
-    WheelBuilder.make(Factory().create_poetry(module_path), NullEnv(), NullIO())
-
-    whl = module_path / "dist" / "module_src-0.1-py2.py3-none-any.whl"
-
-    assert whl.exists()
-
-    with zipfile.ZipFile(str(whl)) as z:
-        assert "module_src.py" in z.namelist()
-
-
-def test_dist_info_file_permissions():
-    module_path = fixtures_dir / "complete"
-    WheelBuilder.make(Factory().create_poetry(module_path), NullEnv(), NullIO())
-
-    whl = module_path / "dist" / "my_package-1.2.3-py3-none-any.whl"
-
-    with zipfile.ZipFile(str(whl)) as z:
-        assert (
-            z.getinfo("my_package-1.2.3.dist-info/WHEEL").external_attr == 0o644 << 16
-        )
-        assert (
-            z.getinfo("my_package-1.2.3.dist-info/METADATA").external_attr
-            == 0o644 << 16
-        )
-        assert (
-            z.getinfo("my_package-1.2.3.dist-info/RECORD").external_attr == 0o644 << 16
-        )
-        assert (
-            z.getinfo("my_package-1.2.3.dist-info/entry_points.txt").external_attr
-            == 0o644 << 16
-        )
diff --git a/tests/masonry/publishing/__init__.py b/tests/masonry/publishing/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/test_api.py b/tests/masonry/test_api.py
deleted file mode 100644
index 2019a08212a..00000000000
--- a/tests/masonry/test_api.py
+++ /dev/null
@@ -1,131 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-import os
-import tarfile
-import zipfile
-
-from contextlib import contextmanager
-
-from poetry import __version__
-from poetry.masonry import api
-from poetry.utils._compat import Path
-from poetry.utils._compat import decode
-from poetry.utils.helpers import temporary_directory
-
-
-@contextmanager
-def cwd(directory):
-    prev = os.getcwd()
-    os.chdir(str(directory))
-    try:
-        yield
-    finally:
-        os.chdir(prev)
-
-
-fixtures = os.path.join(os.path.dirname(__file__), "builders", "fixtures")
-
-
-def test_get_requires_for_build_wheel():
-    expected = []
-    with cwd(os.path.join(fixtures, "complete")):
-        assert api.get_requires_for_build_wheel() == expected
-
-
-def test_get_requires_for_build_sdist():
-    expected = []
-    with cwd(os.path.join(fixtures, "complete")):
-        assert api.get_requires_for_build_sdist() == expected
-
-
-def test_build_wheel():
-    with temporary_directory() as tmp_dir, cwd(os.path.join(fixtures, "complete")):
-        filename = api.build_wheel(tmp_dir)
-
-        with zipfile.ZipFile(str(os.path.join(tmp_dir, filename))) as zip:
-            namelist = zip.namelist()
-
-            assert "my_package-1.2.3.dist-info/entry_points.txt" in namelist
-            assert "my_package-1.2.3.dist-info/WHEEL" in namelist
-            assert "my_package-1.2.3.dist-info/METADATA" in namelist
-
-
-def test_build_sdist():
-    with temporary_directory() as tmp_dir, cwd(os.path.join(fixtures, "complete")):
-        filename = api.build_sdist(tmp_dir)
-
-        with tarfile.open(str(os.path.join(tmp_dir, filename))) as tar:
-            namelist = tar.getnames()
-
-            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://python-poetry.org/
-License: MIT
-Keywords: packaging,dependency,poetry
-Author: Sébastien Eustace
-Author-email: sebastien@eustace.io
-Maintainer: People Everywhere
-Maintainer-email: people@everywhere.com
-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: Programming Language :: Python :: 3.8
-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); (python_version ~= "2.7" and sys_platform == "win32" or python_version in "3.4 3.5") and (extra == "time")
-Project-URL: Documentation, https://python-poetry.org/docs
-Project-URL: Issue Tracker, https://github.com/python-poetry/poetry/issues
-Project-URL: Repository, https://github.com/python-poetry/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(encoding="utf-8") as f:
-            assert entry_points == decode(f.read())
-
-        with (dist_info / "WHEEL").open(encoding="utf-8") as f:
-            assert wheel_data == decode(f.read())
-
-        with (dist_info / "METADATA").open(encoding="utf-8") as f:
-            assert metadata == decode(f.read())
diff --git a/tests/masonry/utils/__init__.py b/tests/masonry/utils/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/utils/fixtures/with_includes/__init__.py b/tests/masonry/utils/fixtures/with_includes/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/utils/fixtures/with_includes/bar/baz.py b/tests/masonry/utils/fixtures/with_includes/bar/baz.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/utils/fixtures/with_includes/extra_package/some_dir/foo.py b/tests/masonry/utils/fixtures/with_includes/extra_package/some_dir/foo.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/utils/fixtures/with_includes/extra_package/some_dir/quux.py b/tests/masonry/utils/fixtures/with_includes/extra_package/some_dir/quux.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/utils/fixtures/with_includes/not_a_python_pkg/baz.txt b/tests/masonry/utils/fixtures/with_includes/not_a_python_pkg/baz.txt
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/masonry/utils/test_package_include.py b/tests/masonry/utils/test_package_include.py
deleted file mode 100644
index a79ff96f03c..00000000000
--- a/tests/masonry/utils/test_package_include.py
+++ /dev/null
@@ -1,43 +0,0 @@
-import pytest
-
-from poetry.masonry.utils.package_include import PackageInclude
-from poetry.utils._compat import Path
-
-
-fixtures_dir = Path(__file__).parent / "fixtures"
-with_includes = fixtures_dir / "with_includes"
-
-
-def test_package_include_with_multiple_dirs():
-    pkg_include = PackageInclude(base=fixtures_dir, include="with_includes")
-    assert pkg_include.elements == [
-        with_includes / "__init__.py",
-        with_includes / "bar",
-        with_includes / "bar/baz.py",
-        with_includes / "extra_package",
-        with_includes / "extra_package/some_dir",
-        with_includes / "extra_package/some_dir/foo.py",
-        with_includes / "extra_package/some_dir/quux.py",
-        with_includes / "not_a_python_pkg",
-        with_includes / "not_a_python_pkg/baz.txt",
-    ]
-
-
-def test_package_include_with_simple_dir():
-    pkg_include = PackageInclude(base=with_includes, include="bar")
-    assert pkg_include.elements == [with_includes / "bar/baz.py"]
-
-
-def test_package_include_with_nested_dir():
-    pkg_include = PackageInclude(base=with_includes, include="extra_package/**/*.py")
-    assert pkg_include.elements == [
-        with_includes / "extra_package/some_dir/foo.py",
-        with_includes / "extra_package/some_dir/quux.py",
-    ]
-
-
-def test_package_include_with_no_python_files_in_dir():
-    with pytest.raises(ValueError) as e:
-        PackageInclude(base=with_includes, include="not_a_python_pkg")
-
-    assert str(e.value) == "not_a_python_pkg is not a package."
diff --git a/tests/mixology/helpers.py b/tests/mixology/helpers.py
index 1f9d686617a..05ab493f79a 100644
--- a/tests/mixology/helpers.py
+++ b/tests/mixology/helpers.py
@@ -1,7 +1,7 @@
+from poetry.core.packages import Package
 from poetry.mixology.failure import SolveFailure
 from poetry.mixology.version_solver import VersionSolver
 from poetry.packages import DependencyPackage
-from poetry.packages import Package
 
 
 def add_to_repo(repository, name, version, deps=None, python=None):
diff --git a/tests/mixology/version_solver/conftest.py b/tests/mixology/version_solver/conftest.py
index c27dfb11ff5..0b605d31f6b 100644
--- a/tests/mixology/version_solver/conftest.py
+++ b/tests/mixology/version_solver/conftest.py
@@ -2,7 +2,7 @@
 
 from clikit.io import NullIO
 
-from poetry.packages.project_package import ProjectPackage
+from poetry.core.packages.project_package import ProjectPackage
 from poetry.puzzle.provider import Provider
 from poetry.repositories import Pool
 from poetry.repositories import Repository
diff --git a/tests/packages/constraints/__init__.py b/tests/packages/constraints/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/packages/constraints/test_constraint.py b/tests/packages/constraints/test_constraint.py
deleted file mode 100644
index 1c55b63489e..00000000000
--- a/tests/packages/constraints/test_constraint.py
+++ /dev/null
@@ -1,90 +0,0 @@
-from poetry.packages.constraints.constraint import Constraint
-from poetry.packages.constraints.empty_constraint import EmptyConstraint
-from poetry.packages.constraints.multi_constraint import MultiConstraint
-from poetry.packages.constraints.union_constraint import UnionConstraint
-
-
-def test_allows():
-    c = Constraint("win32")
-
-    assert c.allows(Constraint("win32"))
-    assert not c.allows(Constraint("linux"))
-
-    c = Constraint("win32", "!=")
-
-    assert not c.allows(Constraint("win32"))
-    assert c.allows(Constraint("linux"))
-
-
-def test_allows_any():
-    c = Constraint("win32")
-
-    assert c.allows_any(Constraint("win32"))
-    assert not c.allows_any(Constraint("linux"))
-    assert c.allows_any(UnionConstraint(Constraint("win32"), Constraint("linux")))
-    assert c.allows_any(Constraint("linux", "!="))
-
-    c = Constraint("win32", "!=")
-
-    assert not c.allows_any(Constraint("win32"))
-    assert c.allows_any(Constraint("linux"))
-    assert c.allows_any(UnionConstraint(Constraint("win32"), Constraint("linux")))
-    assert c.allows_any(Constraint("linux", "!="))
-
-
-def test_allows_all():
-    c = Constraint("win32")
-
-    assert c.allows_all(Constraint("win32"))
-    assert not c.allows_all(Constraint("linux"))
-    assert not c.allows_all(Constraint("linux", "!="))
-    assert not c.allows_all(UnionConstraint(Constraint("win32"), Constraint("linux")))
-
-
-def test_intersect():
-    c = Constraint("win32")
-
-    intersection = c.intersect(Constraint("linux"))
-    assert intersection == EmptyConstraint()
-
-    intersection = c.intersect(
-        UnionConstraint(Constraint("win32"), Constraint("linux"))
-    )
-    assert intersection == Constraint("win32")
-
-    intersection = c.intersect(
-        UnionConstraint(Constraint("linux"), Constraint("linux2"))
-    )
-    assert intersection == EmptyConstraint()
-
-    intersection = c.intersect(Constraint("linux", "!="))
-    assert intersection == c
-
-    c = Constraint("win32", "!=")
-
-    intersection = c.intersect(Constraint("linux", "!="))
-    assert intersection == MultiConstraint(
-        Constraint("win32", "!="), Constraint("linux", "!=")
-    )
-
-
-def test_union():
-    c = Constraint("win32")
-
-    union = c.union(Constraint("linux"))
-    assert union == UnionConstraint(Constraint("win32"), Constraint("linux"))
-
-    union = c.union(UnionConstraint(Constraint("win32"), Constraint("linux")))
-    assert union == UnionConstraint(Constraint("win32"), Constraint("linux"))
-
-    union = c.union(UnionConstraint(Constraint("linux"), Constraint("linux2")))
-    assert union == UnionConstraint(
-        Constraint("win32"), Constraint("linux"), Constraint("linux2")
-    )
-
-
-def test_difference():
-    c = Constraint("win32")
-
-    assert c.difference(Constraint("win32")).is_empty()
-    assert c.difference(Constraint("linux")) == c
diff --git a/tests/packages/constraints/test_main.py b/tests/packages/constraints/test_main.py
deleted file mode 100644
index 2b3418289b7..00000000000
--- a/tests/packages/constraints/test_main.py
+++ /dev/null
@@ -1,57 +0,0 @@
-import pytest
-
-from poetry.packages.constraints import parse_constraint
-from poetry.packages.constraints.any_constraint import AnyConstraint
-from poetry.packages.constraints.constraint import Constraint
-from poetry.packages.constraints.multi_constraint import MultiConstraint
-from poetry.packages.constraints.union_constraint import UnionConstraint
-
-
-@pytest.mark.parametrize(
-    "input,constraint",
-    [
-        ("*", AnyConstraint()),
-        ("win32", Constraint("win32", "=")),
-        ("=win32", Constraint("win32", "=")),
-        ("==win32", Constraint("win32", "=")),
-        ("!=win32", Constraint("win32", "!=")),
-        ("!= win32", Constraint("win32", "!=")),
-    ],
-)
-def test_parse_constraint(input, constraint):
-    assert parse_constraint(input) == constraint
-
-
-@pytest.mark.parametrize(
-    "input,constraint",
-    [
-        (
-            "!=win32,!=linux",
-            MultiConstraint(Constraint("win32", "!="), Constraint("linux", "!=")),
-        ),
-        (
-            "!=win32,!=linux,!=linux2",
-            MultiConstraint(
-                Constraint("win32", "!="),
-                Constraint("linux", "!="),
-                Constraint("linux2", "!="),
-            ),
-        ),
-    ],
-)
-def test_parse_constraint_multi(input, constraint):
-    assert parse_constraint(input) == constraint
-
-
-@pytest.mark.parametrize(
-    "input,constraint",
-    [
-        ("win32 || linux", UnionConstraint(Constraint("win32"), Constraint("linux"))),
-        (
-            "win32 || !=linux2",
-            UnionConstraint(Constraint("win32"), Constraint("linux2", "!=")),
-        ),
-    ],
-)
-def test_parse_constraint_union(input, constraint):
-    assert parse_constraint(input) == constraint
diff --git a/tests/packages/constraints/test_multi_constraint.py b/tests/packages/constraints/test_multi_constraint.py
deleted file mode 100644
index 38f57fa902a..00000000000
--- a/tests/packages/constraints/test_multi_constraint.py
+++ /dev/null
@@ -1,41 +0,0 @@
-from poetry.packages.constraints.constraint import Constraint
-from poetry.packages.constraints.multi_constraint import MultiConstraint
-
-
-def test_allows():
-    c = MultiConstraint(Constraint("win32", "!="), Constraint("linux", "!="))
-
-    assert not c.allows(Constraint("win32"))
-    assert not c.allows(Constraint("linux"))
-    assert c.allows(Constraint("darwin"))
-
-
-def test_allows_any():
-    c = MultiConstraint(Constraint("win32", "!="), Constraint("linux", "!="))
-
-    assert c.allows_any(Constraint("darwin"))
-    assert c.allows_any(Constraint("darwin", "!="))
-    assert not c.allows_any(Constraint("win32"))
-    assert c.allows_any(c)
-    assert c.allows_any(
-        MultiConstraint(Constraint("win32", "!="), Constraint("darwin", "!="))
-    )
-
-
-def test_allows_all():
-    c = MultiConstraint(Constraint("win32", "!="), Constraint("linux", "!="))
-
-    assert c.allows_all(Constraint("darwin"))
-    assert c.allows_all(Constraint("darwin", "!="))
-    assert not c.allows_all(Constraint("win32"))
-    assert c.allows_all(c)
-    assert not c.allows_all(
-        MultiConstraint(Constraint("win32", "!="), Constraint("darwin", "!="))
-    )
-
-
-def test_intersect():
-    c = MultiConstraint(Constraint("win32", "!="), Constraint("linux", "!="))
-
-    intersection = c.intersect(Constraint("win32", "!="))
-    assert intersection == Constraint("win32", "!=")
diff --git a/tests/packages/constraints/test_union_constraint.py b/tests/packages/constraints/test_union_constraint.py
deleted file mode 100644
index 2d6ad77185c..00000000000
--- a/tests/packages/constraints/test_union_constraint.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from poetry.packages.constraints.constraint import Constraint
-from poetry.packages.constraints.union_constraint import UnionConstraint
-
-
-def test_allows():
-    c = UnionConstraint(Constraint("win32"), Constraint("linux"))
-
-    assert c.allows(Constraint("win32"))
-    assert c.allows(Constraint("linux"))
-    assert not c.allows(Constraint("darwin"))
-
-
-def test_allows_any():
-    c = UnionConstraint(Constraint("win32"), Constraint("linux"))
-
-    assert c.allows_any(c)
-    assert c.allows_any(UnionConstraint(Constraint("win32"), Constraint("darwin")))
-    assert not c.allows_any(UnionConstraint(Constraint("linux2"), Constraint("darwin")))
-    assert c.allows_any(Constraint("win32"))
-    assert not c.allows_any(Constraint("darwin"))
-
-
-def test_allows_all():
-    c = UnionConstraint(Constraint("win32"), Constraint("linux"))
-
-    assert c.allows_all(c)
-    assert not c.allows_all(UnionConstraint(Constraint("win32"), Constraint("darwin")))
-    assert not c.allows_all(UnionConstraint(Constraint("linux2"), Constraint("darwin")))
-    assert c.allows_all(Constraint("win32"))
-    assert not c.allows_all(Constraint("darwin"))
diff --git a/tests/packages/test_dependency.py b/tests/packages/test_dependency.py
deleted file mode 100644
index 91654f4b874..00000000000
--- a/tests/packages/test_dependency.py
+++ /dev/null
@@ -1,110 +0,0 @@
-from poetry.packages import Dependency
-from poetry.packages import Package
-
-
-def test_accepts():
-    dependency = Dependency("A", "^1.0")
-    package = Package("A", "1.4")
-
-    assert dependency.accepts(package)
-
-
-def test_accepts_prerelease():
-    dependency = Dependency("A", "^1.0", allows_prereleases=True)
-    package = Package("A", "1.4-beta.1")
-
-    assert dependency.accepts(package)
-
-
-def test_accepts_python_versions():
-    dependency = Dependency("A", "^1.0")
-    dependency.python_versions = "^3.6"
-    package = Package("A", "1.4")
-    package.python_versions = "~3.6"
-
-    assert dependency.accepts(package)
-
-
-def test_accepts_fails_with_different_names():
-    dependency = Dependency("A", "^1.0")
-    package = Package("B", "1.4")
-
-    assert not dependency.accepts(package)
-
-
-def test_accepts_fails_with_version_mismatch():
-    dependency = Dependency("A", "~1.0")
-    package = Package("B", "1.4")
-
-    assert not dependency.accepts(package)
-
-
-def test_accepts_fails_with_prerelease_mismatch():
-    dependency = Dependency("A", "^1.0")
-    package = Package("B", "1.4-beta.1")
-
-    assert not dependency.accepts(package)
-
-
-def test_accepts_fails_with_python_versions_mismatch():
-    dependency = Dependency("A", "^1.0")
-    dependency.python_versions = "^3.6"
-    package = Package("B", "1.4")
-    package.python_versions = "~3.5"
-
-    assert not dependency.accepts(package)
-
-
-def test_to_pep_508():
-    dependency = Dependency("Django", "^1.23")
-
-    result = dependency.to_pep_508()
-    assert result == "Django (>=1.23,<2.0)"
-
-    dependency = Dependency("Django", "^1.23")
-    dependency.python_versions = "~2.7 || ^3.6"
-
-    result = dependency.to_pep_508()
-    assert (
-        result == "Django (>=1.23,<2.0); "
-        'python_version >= "2.7" and python_version < "2.8" '
-        'or python_version >= "3.6" and python_version < "4.0"'
-    )
-
-
-def test_to_pep_508_wilcard():
-    dependency = Dependency("Django", "*")
-
-    result = dependency.to_pep_508()
-    assert result == "Django"
-
-
-def test_to_pep_508_in_extras():
-    dependency = Dependency("Django", "^1.23")
-    dependency.in_extras.append("foo")
-
-    result = dependency.to_pep_508()
-    assert result == 'Django (>=1.23,<2.0); extra == "foo"'
-
-    dependency.in_extras.append("bar")
-
-    result = dependency.to_pep_508()
-    assert result == 'Django (>=1.23,<2.0); extra == "foo" or extra == "bar"'
-
-    dependency.python_versions = "~2.7 || ^3.6"
-
-    result = dependency.to_pep_508()
-    assert result == (
-        "Django (>=1.23,<2.0); "
-        "("
-        'python_version >= "2.7" and python_version < "2.8" '
-        'or python_version >= "3.6" and python_version < "4.0"'
-        ") "
-        'and (extra == "foo" or extra == "bar")'
-    )
-
-
-def test_to_pep_508_with_single_version_excluded():
-    dependency = Dependency("foo", "!=1.2.3")
-
-    assert "foo (!=1.2.3)" == dependency.to_pep_508()
diff --git a/tests/packages/test_directory_dependency.py b/tests/packages/test_directory_dependency.py
deleted file mode 100644
index a557bb8c060..00000000000
--- a/tests/packages/test_directory_dependency.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from subprocess import CalledProcessError
-
-import pytest
-
-from poetry.packages.directory_dependency import DirectoryDependency
-from poetry.utils._compat import Path
-from poetry.utils.env import EnvCommandError
-from poetry.utils.env import MockEnv as BaseMockEnv
-
-
-class MockEnv(BaseMockEnv):
-    def run(self, bin, *args):
-        raise EnvCommandError(CalledProcessError(1, "python", output=""))
-
-
-DIST_PATH = Path(__file__).parent.parent / "fixtures" / "git" / "github.com" / "demo"
-
-
-def test_directory_dependency_must_exist():
-    with pytest.raises(ValueError):
-        DirectoryDependency("demo", DIST_PATH / "invalid")
diff --git a/tests/packages/test_file_dependency.py b/tests/packages/test_file_dependency.py
deleted file mode 100644
index f5808d26641..00000000000
--- a/tests/packages/test_file_dependency.py
+++ /dev/null
@@ -1,17 +0,0 @@
-import pytest
-
-from poetry.packages import FileDependency
-from poetry.utils._compat import Path
-
-
-DIST_PATH = Path(__file__).parent.parent / "fixtures" / "distributions"
-
-
-def test_file_dependency_wrong_path():
-    with pytest.raises(ValueError):
-        FileDependency("demo", DIST_PATH / "demo-0.2.0.tar.gz")
-
-
-def test_file_dependency_dir():
-    with pytest.raises(ValueError):
-        FileDependency("demo", DIST_PATH)
diff --git a/tests/packages/test_locker.py b/tests/packages/test_locker.py
index 2e166880612..1fe3ca1c48f 100644
--- a/tests/packages/test_locker.py
+++ b/tests/packages/test_locker.py
@@ -3,8 +3,8 @@
 import pytest
 import tomlkit
 
+from poetry.core.packages.project_package import ProjectPackage
 from poetry.packages.locker import Locker
-from poetry.packages.project_package import ProjectPackage
 
 from ..helpers import get_dependency
 from ..helpers import get_package
@@ -246,3 +246,40 @@ def test_locking_legacy_repository_package_should_include_source_section(root, l
 """
 
     assert expected == content
+
+
+def test_extras_dependencies_are_ordered(locker, root):
+    package_a = get_package("A", "1.0.0")
+    package_a.add_dependency(
+        "B", {"version": "^1.0.0", "optional": True, "extras": ["c", "a", "b"]}
+    )
+    package_a.requires[-1].activate()
+
+    locker.set_lock_data(root, [package_a])
+
+    expected = """[[package]]
+category = "main"
+description = ""
+name = "A"
+optional = false
+python-versions = "*"
+version = "1.0.0"
+
+[package.dependencies]
+[package.dependencies.B]
+extras = ["a", "b", "c"]
+optional = true
+version = "^1.0.0"
+
+[metadata]
+content-hash = "115cf985d932e9bf5f540555bbdd75decbb62cac81e399375fc19f6277f8c1d8"
+python-versions = "*"
+
+[metadata.files]
+A = []
+"""
+
+    with locker.lock.open(encoding="utf-8") as f:
+        content = f.read()
+
+    assert expected == content
diff --git a/tests/packages/test_main.py b/tests/packages/test_main.py
deleted file mode 100644
index 586be5a31b8..00000000000
--- a/tests/packages/test_main.py
+++ /dev/null
@@ -1,204 +0,0 @@
-from poetry.packages import dependency_from_pep_508
-
-
-def test_dependency_from_pep_508():
-    name = "requests"
-    dep = dependency_from_pep_508(name)
-
-    assert dep.name == name
-    assert str(dep.constraint) == "*"
-
-
-def test_dependency_from_pep_508_with_version():
-    name = "requests==2.18.0"
-    dep = dependency_from_pep_508(name)
-
-    assert dep.name == "requests"
-    assert str(dep.constraint) == "2.18.0"
-
-
-def test_dependency_from_pep_508_with_parens():
-    name = "requests (==2.18.0)"
-    dep = dependency_from_pep_508(name)
-
-    assert dep.name == "requests"
-    assert str(dep.constraint) == "2.18.0"
-
-
-def test_dependency_from_pep_508_with_constraint():
-    name = "requests>=2.12.0,!=2.17.*,<3.0"
-    dep = dependency_from_pep_508(name)
-
-    assert dep.name == "requests"
-    assert str(dep.constraint) == ">=2.12.0,<2.17.0 || >=2.18.0,<3.0"
-
-
-def test_dependency_from_pep_508_with_extras():
-    name = 'requests==2.18.0; extra == "foo" or extra == "bar"'
-    dep = dependency_from_pep_508(name)
-
-    assert dep.name == "requests"
-    assert str(dep.constraint) == "2.18.0"
-    assert dep.in_extras == ["foo", "bar"]
-    assert str(dep.marker) == 'extra == "foo" or extra == "bar"'
-
-
-def test_dependency_from_pep_508_with_python_version():
-    name = 'requests (==2.18.0); python_version == "2.7" or python_version == "2.6"'
-    dep = dependency_from_pep_508(name)
-
-    assert dep.name == "requests"
-    assert str(dep.constraint) == "2.18.0"
-    assert dep.extras == []
-    assert dep.python_versions == "~2.7 || ~2.6"
-    assert str(dep.marker) == 'python_version == "2.7" or python_version == "2.6"'
-
-
-def test_dependency_from_pep_508_with_single_python_version():
-    name = 'requests (==2.18.0); python_version == "2.7"'
-    dep = dependency_from_pep_508(name)
-
-    assert dep.name == "requests"
-    assert str(dep.constraint) == "2.18.0"
-    assert dep.extras == []
-    assert dep.python_versions == "~2.7"
-    assert str(dep.marker) == 'python_version == "2.7"'
-
-
-def test_dependency_from_pep_508_with_platform():
-    name = 'requests (==2.18.0); sys_platform == "win32" or sys_platform == "darwin"'
-    dep = dependency_from_pep_508(name)
-
-    assert dep.name == "requests"
-    assert str(dep.constraint) == "2.18.0"
-    assert dep.extras == []
-    assert dep.python_versions == "*"
-    assert str(dep.marker) == 'sys_platform == "win32" or sys_platform == "darwin"'
-
-
-def test_dependency_from_pep_508_complex():
-    name = (
-        "requests (==2.18.0); "
-        'python_version >= "2.7" and python_version != "3.2" '
-        'and (sys_platform == "win32" or sys_platform == "darwin") '
-        'and extra == "foo"'
-    )
-    dep = dependency_from_pep_508(name)
-
-    assert dep.name == "requests"
-    assert str(dep.constraint) == "2.18.0"
-    assert dep.in_extras == ["foo"]
-    assert dep.python_versions == ">=2.7 !=3.2.*"
-    assert str(dep.marker) == (
-        'python_version >= "2.7" and python_version != "3.2" '
-        'and (sys_platform == "win32" or sys_platform == "darwin") '
-        'and extra == "foo"'
-    )
-
-
-def test_dependency_python_version_in():
-    name = "requests (==2.18.0); python_version in '3.3 3.4 3.5'"
-    dep = dependency_from_pep_508(name)
-
-    assert dep.name == "requests"
-    assert str(dep.constraint) == "2.18.0"
-    assert dep.python_versions == "3.3.* || 3.4.* || 3.5.*"
-    assert str(dep.marker) == 'python_version in "3.3 3.4 3.5"'
-
-
-def test_dependency_python_version_in_comma():
-    name = "requests (==2.18.0); python_version in '3.3, 3.4, 3.5'"
-    dep = dependency_from_pep_508(name)
-
-    assert dep.name == "requests"
-    assert str(dep.constraint) == "2.18.0"
-    assert dep.python_versions == "3.3.* || 3.4.* || 3.5.*"
-    assert str(dep.marker) == 'python_version in "3.3, 3.4, 3.5"'
-
-
-def test_dependency_platform_in():
-    name = "requests (==2.18.0); sys_platform in 'win32 darwin'"
-    dep = dependency_from_pep_508(name)
-
-    assert dep.name == "requests"
-    assert str(dep.constraint) == "2.18.0"
-    assert str(dep.marker) == 'sys_platform in "win32 darwin"'
-
-
-def test_dependency_with_extra():
-    name = "requests[security] (==2.18.0)"
-    dep = dependency_from_pep_508(name)
-
-    assert dep.name == "requests"
-    assert str(dep.constraint) == "2.18.0"
-
-    assert len(dep.extras) == 1
-    assert dep.extras[0] == "security"
-
-
-def test_dependency_from_pep_508_with_python_version_union_of_multi():
-    name = (
-        "requests (==2.18.0); "
-        '(python_version >= "2.7" and python_version < "2.8") '
-        'or (python_version >= "3.4" and python_version < "3.5")'
-    )
-    dep = dependency_from_pep_508(name)
-
-    assert dep.name == "requests"
-    assert str(dep.constraint) == "2.18.0"
-    assert dep.extras == []
-    assert dep.python_versions == ">=2.7 <2.8 || >=3.4 <3.5"
-    assert str(dep.marker) == (
-        'python_version >= "2.7" and python_version < "2.8" '
-        'or python_version >= "3.4" and python_version < "3.5"'
-    )
-
-
-def test_dependency_from_pep_508_with_not_in_op_marker():
-    name = (
-        "jinja2 (>=2.7,<2.8)"
-        '; python_version not in "3.0,3.1,3.2" and extra == "export"'
-    )
-
-    dep = dependency_from_pep_508(name)
-
-    assert dep.name == "jinja2"
-    assert str(dep.constraint) == ">=2.7,<2.8"
-    assert dep.in_extras == ["export"]
-    assert dep.python_versions == "!=3.0.*, !=3.1.*, !=3.2.*"
-    assert (
-        str(dep.marker) == 'python_version not in "3.0,3.1,3.2" and extra == "export"'
-    )
-
-
-def test_dependency_from_pep_508_with_git_url():
-    name = "django-utils @ git+ssh://git@corp-gitlab.com/corp-utils.git@1.2"
-
-    dep = dependency_from_pep_508(name)
-
-    assert "django-utils" == dep.name
-    assert dep.is_vcs()
-    assert "git" == dep.vcs
-    assert "ssh://git@corp-gitlab.com/corp-utils.git" == dep.source
-    assert "1.2" == dep.reference
-
-
-def test_dependency_from_pep_508_with_url():
-    name = "django-utils @ https://example.com/django-utils-1.0.0.tar.gz"
-
-    dep = dependency_from_pep_508(name)
-
-    assert "django-utils" == dep.name
-    assert dep.is_url()
-    assert "https://example.com/django-utils-1.0.0.tar.gz" == dep.url
-
-
-def test_dependency_from_pep_508_with_wheel_url():
-    name = (
-        "example_wheel @ https://example.com/example_wheel-14.0.2-py2.py3-none-any.whl"
-    )
-
-    dep = dependency_from_pep_508(name)
-
-    assert "example-wheel" == dep.name
-    assert str(dep.constraint) == "14.0.2"
diff --git a/tests/packages/test_package.py b/tests/packages/test_package.py
deleted file mode 100644
index b61de86e540..00000000000
--- a/tests/packages/test_package.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-import pytest
-
-from poetry.packages import Package
-
-
-def test_package_authors():
-    package = Package("foo", "0.1.0")
-
-    package.authors.append("Sébastien Eustace ")
-    assert package.author_name == "Sébastien Eustace"
-    assert package.author_email == "sebastien@eustace.io"
-
-    package.authors.insert(0, "John Doe")
-    assert package.author_name == "John Doe"
-    assert package.author_email is None
-
-
-@pytest.mark.parametrize("category", ["main", "dev"])
-def test_package_add_dependency_vcs_category(category):
-    package = Package("foo", "0.1.0")
-
-    dependency = package.add_dependency(
-        "poetry",
-        constraint={"git": "https://github.com/python-poetry/poetry.git"},
-        category=category,
-    )
-    assert dependency.category == category
-
-
-def test_package_add_dependency_vcs_category_default_main():
-    package = Package("foo", "0.1.0")
-
-    dependency = package.add_dependency(
-        "poetry", constraint={"git": "https://github.com/python-poetry/poetry.git"}
-    )
-    assert dependency.category == "main"
diff --git a/tests/packages/test_vcs_dependency.py b/tests/packages/test_vcs_dependency.py
deleted file mode 100644
index dc9847d3d3b..00000000000
--- a/tests/packages/test_vcs_dependency.py
+++ /dev/null
@@ -1,72 +0,0 @@
-import pytest
-
-from poetry.packages.vcs_dependency import VCSDependency
-
-
-def test_to_pep_508():
-    dependency = VCSDependency(
-        "poetry", "git", "https://github.com/python-poetry/poetry.git"
-    )
-
-    expected = "poetry @ git+https://github.com/python-poetry/poetry.git@master"
-
-    assert expected == dependency.to_pep_508()
-
-
-def test_to_pep_508_ssh():
-    dependency = VCSDependency("poetry", "git", "git@github.com:sdispater/poetry.git")
-
-    expected = "poetry @ git+ssh://git@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/python-poetry/poetry.git"
-    )
-    dependency.extras.append("foo")
-
-    expected = "poetry[foo] @ git+https://github.com/python-poetry/poetry.git@master"
-
-    assert expected == dependency.to_pep_508()
-
-
-def test_to_pep_508_in_extras():
-    dependency = VCSDependency(
-        "poetry", "git", "https://github.com/python-poetry/poetry.git"
-    )
-    dependency.in_extras.append("foo")
-
-    expected = 'poetry @ git+https://github.com/python-poetry/poetry.git@master ; extra == "foo"'
-    assert expected == dependency.to_pep_508()
-
-    dependency = VCSDependency(
-        "poetry", "git", "https://github.com/python-poetry/poetry.git"
-    )
-    dependency.in_extras.append("foo")
-    dependency.extras.append("bar")
-
-    expected = 'poetry[bar] @ git+https://github.com/python-poetry/poetry.git@master ; extra == "foo"'
-
-    assert expected == dependency.to_pep_508()
-
-    dependency = VCSDependency(
-        "poetry", "git", "https://github.com/python-poetry/poetry.git", "b;ar;"
-    )
-    dependency.in_extras.append("foo;")
-
-    expected = 'poetry @ git+https://github.com/python-poetry/poetry.git@b;ar; ; extra == "foo;"'
-
-    assert expected == dependency.to_pep_508()
-
-
-@pytest.mark.parametrize("category", ["main", "dev"])
-def test_category(category):
-    dependency = VCSDependency(
-        "poetry",
-        "git",
-        "https://github.com/python-poetry/poetry.git",
-        category=category,
-    )
-    assert category == dependency.category
diff --git a/tests/packages/utils/__init__.py b/tests/packages/utils/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/packages/utils/test_utils.py b/tests/packages/utils/test_utils.py
deleted file mode 100644
index bf1abe262ba..00000000000
--- a/tests/packages/utils/test_utils.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from poetry.packages.utils.utils import convert_markers
-from poetry.version.markers import parse_marker
-
-
-def test_convert_markers():
-    marker = parse_marker(
-        'sys_platform == "win32" and python_version < "3.6" '
-        'or sys_platform == "win32" and python_version < "3.6" and python_version >= "3.3" '
-        'or sys_platform == "win32" and python_version < "3.3"'
-    )
-
-    converted = convert_markers(marker)
-
-    assert converted["python_version"] == [
-        [("<", "3.6")],
-        [("<", "3.6"), (">=", "3.3")],
-        [("<", "3.3")],
-    ]
-
-    marker = parse_marker('python_version == "2.7" or python_version == "2.6"')
-    converted = convert_markers(marker)
-
-    assert converted["python_version"] == [[("==", "2.7")], [("==", "2.6")]]
diff --git a/tests/masonry/builders/fixtures/default_with_excluded_data/my_package/__init__.py b/tests/publishing/__init__.py
similarity index 100%
rename from tests/masonry/builders/fixtures/default_with_excluded_data/my_package/__init__.py
rename to tests/publishing/__init__.py
diff --git a/tests/masonry/publishing/test_publisher.py b/tests/publishing/test_publisher.py
similarity index 63%
rename from tests/masonry/publishing/test_publisher.py
rename to tests/publishing/test_publisher.py
index 4058e255ae4..da376120645 100644
--- a/tests/masonry/publishing/test_publisher.py
+++ b/tests/publishing/test_publisher.py
@@ -1,14 +1,16 @@
+import os
+
 import pytest
 
 from poetry.factory import Factory
 from poetry.io.null_io import NullIO
-from poetry.masonry.publishing.publisher import Publisher
+from poetry.publishing.publisher import Publisher
 from poetry.utils._compat import Path
 
 
 def test_publish_publishes_to_pypi_by_default(fixture_dir, mocker, config):
-    uploader_auth = mocker.patch("poetry.masonry.publishing.uploader.Uploader.auth")
-    uploader_upload = mocker.patch("poetry.masonry.publishing.uploader.Uploader.upload")
+    uploader_auth = mocker.patch("poetry.publishing.uploader.Uploader.auth")
+    uploader_upload = mocker.patch("poetry.publishing.uploader.Uploader.upload")
     poetry = Factory().create_poetry(fixture_dir("sample_project"))
     poetry._config = config
     poetry.config.merge(
@@ -21,13 +23,13 @@ def test_publish_publishes_to_pypi_by_default(fixture_dir, mocker, config):
     assert [("foo", "bar")] == uploader_auth.call_args
     assert [
         ("https://upload.pypi.org/legacy/",),
-        {"cert": None, "client_cert": None},
+        {"cert": None, "client_cert": None, "dry_run": False},
     ] == uploader_upload.call_args
 
 
 def test_publish_can_publish_to_given_repository(fixture_dir, mocker, config):
-    uploader_auth = mocker.patch("poetry.masonry.publishing.uploader.Uploader.auth")
-    uploader_upload = mocker.patch("poetry.masonry.publishing.uploader.Uploader.upload")
+    uploader_auth = mocker.patch("poetry.publishing.uploader.Uploader.auth")
+    uploader_upload = mocker.patch("poetry.publishing.uploader.Uploader.upload")
     poetry = Factory().create_poetry(fixture_dir("sample_project"))
     poetry._config = config
     poetry.config.merge(
@@ -43,7 +45,7 @@ def test_publish_can_publish_to_given_repository(fixture_dir, mocker, config):
     assert [("foo", "bar")] == uploader_auth.call_args
     assert [
         ("http://foo.bar",),
-        {"cert": None, "client_cert": None},
+        {"cert": None, "client_cert": None, "dry_run": False},
     ] == uploader_upload.call_args
 
 
@@ -60,8 +62,8 @@ def test_publish_raises_error_for_undefined_repository(fixture_dir, mocker, conf
 
 
 def test_publish_uses_token_if_it_exists(fixture_dir, mocker, config):
-    uploader_auth = mocker.patch("poetry.masonry.publishing.uploader.Uploader.auth")
-    uploader_upload = mocker.patch("poetry.masonry.publishing.uploader.Uploader.upload")
+    uploader_auth = mocker.patch("poetry.publishing.uploader.Uploader.auth")
+    uploader_upload = mocker.patch("poetry.publishing.uploader.Uploader.upload")
     poetry = Factory().create_poetry(fixture_dir("sample_project"))
     poetry._config = config
     poetry.config.merge({"pypi-token": {"pypi": "my-token"}})
@@ -72,14 +74,14 @@ def test_publish_uses_token_if_it_exists(fixture_dir, mocker, config):
     assert [("__token__", "my-token")] == uploader_auth.call_args
     assert [
         ("https://upload.pypi.org/legacy/",),
-        {"cert": None, "client_cert": None},
+        {"cert": None, "client_cert": None, "dry_run": False},
     ] == uploader_upload.call_args
 
 
 def test_publish_uses_cert(fixture_dir, mocker, config):
     cert = "path/to/ca.pem"
-    uploader_auth = mocker.patch("poetry.masonry.publishing.uploader.Uploader.auth")
-    uploader_upload = mocker.patch("poetry.masonry.publishing.uploader.Uploader.upload")
+    uploader_auth = mocker.patch("poetry.publishing.uploader.Uploader.auth")
+    uploader_upload = mocker.patch("poetry.publishing.uploader.Uploader.upload")
     poetry = Factory().create_poetry(fixture_dir("sample_project"))
     poetry._config = config
     poetry.config.merge(
@@ -96,13 +98,13 @@ def test_publish_uses_cert(fixture_dir, mocker, config):
     assert [("foo", "bar")] == uploader_auth.call_args
     assert [
         ("https://foo.bar",),
-        {"cert": Path(cert), "client_cert": None},
+        {"cert": Path(cert), "client_cert": None, "dry_run": False},
     ] == uploader_upload.call_args
 
 
 def test_publish_uses_client_cert(fixture_dir, mocker, config):
     client_cert = "path/to/client.pem"
-    uploader_upload = mocker.patch("poetry.masonry.publishing.uploader.Uploader.upload")
+    uploader_upload = mocker.patch("poetry.publishing.uploader.Uploader.upload")
     poetry = Factory().create_poetry(fixture_dir("sample_project"))
     poetry._config = config
     poetry.config.merge(
@@ -117,5 +119,23 @@ def test_publish_uses_client_cert(fixture_dir, mocker, config):
 
     assert [
         ("https://foo.bar",),
-        {"cert": None, "client_cert": Path(client_cert)},
+        {"cert": None, "client_cert": Path(client_cert), "dry_run": False},
+    ] == uploader_upload.call_args
+
+
+def test_publish_read_from_environment_variable(fixture_dir, environ, mocker, config):
+    os.environ["POETRY_REPOSITORIES_FOO_URL"] = "https://foo.bar"
+    os.environ["POETRY_HTTP_BASIC_FOO_USERNAME"] = "bar"
+    os.environ["POETRY_HTTP_BASIC_FOO_PASSWORD"] = "baz"
+    uploader_auth = mocker.patch("poetry.publishing.uploader.Uploader.auth")
+    uploader_upload = mocker.patch("poetry.publishing.uploader.Uploader.upload")
+    poetry = Factory().create_poetry(fixture_dir("sample_project"))
+    publisher = Publisher(poetry, NullIO())
+
+    publisher.publish("foo", None, None)
+
+    assert [("bar", "baz")] == uploader_auth.call_args
+    assert [
+        ("https://foo.bar",),
+        {"cert": None, "client_cert": None, "dry_run": False},
     ] == uploader_upload.call_args
diff --git a/tests/masonry/publishing/test_uploader.py b/tests/publishing/test_uploader.py
similarity index 83%
rename from tests/masonry/publishing/test_uploader.py
rename to tests/publishing/test_uploader.py
index d99012dddb0..8c46057bf17 100644
--- a/tests/masonry/publishing/test_uploader.py
+++ b/tests/publishing/test_uploader.py
@@ -2,12 +2,12 @@
 
 from poetry.factory import Factory
 from poetry.io.null_io import NullIO
-from poetry.masonry.publishing.uploader import Uploader
-from poetry.masonry.publishing.uploader import UploadError
+from poetry.publishing.uploader import Uploader
+from poetry.publishing.uploader import UploadError
 from poetry.utils._compat import Path
 
 
-fixtures_dir = Path(__file__).parent.parent.parent / "fixtures"
+fixtures_dir = Path(__file__).parent.parent / "fixtures"
 
 
 def project(name):
@@ -35,7 +35,7 @@ def test_uploader_properly_handles_403_errors(http):
 
 
 def test_uploader_registers_for_appropriate_400_errors(mocker, http):
-    register = mocker.patch("poetry.masonry.publishing.uploader.Uploader._register")
+    register = mocker.patch("poetry.publishing.uploader.Uploader._register")
     http.register_uri(
         http.POST, "https://foo.com", status=400, body="No package was ever registered"
     )
diff --git a/tests/puzzle/conftest.py b/tests/puzzle/conftest.py
index fc4d69c3078..e3812530bf5 100644
--- a/tests/puzzle/conftest.py
+++ b/tests/puzzle/conftest.py
@@ -30,9 +30,9 @@ def mock_clone(self, source, dest):
 @pytest.fixture(autouse=True)
 def setup(mocker):
     # Patch git module to not actually clone projects
-    mocker.patch("poetry.vcs.git.Git.clone", new=mock_clone)
-    mocker.patch("poetry.vcs.git.Git.checkout", new=lambda *_: None)
-    p = mocker.patch("poetry.vcs.git.Git.rev_parse")
+    mocker.patch("poetry.core.vcs.git.Git.clone", new=mock_clone)
+    mocker.patch("poetry.core.vcs.git.Git.checkout", new=lambda *_: None)
+    p = mocker.patch("poetry.core.vcs.git.Git.rev_parse")
     p.return_value = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24"
 
     yield
diff --git a/tests/puzzle/test_provider.py b/tests/puzzle/test_provider.py
index d3bcba65688..ebbd7a984d6 100644
--- a/tests/puzzle/test_provider.py
+++ b/tests/puzzle/test_provider.py
@@ -4,10 +4,10 @@
 
 from clikit.io import NullIO
 
-from poetry.packages import ProjectPackage
-from poetry.packages.directory_dependency import DirectoryDependency
-from poetry.packages.file_dependency import FileDependency
-from poetry.packages.vcs_dependency import VCSDependency
+from poetry.core.packages import ProjectPackage
+from poetry.core.packages.directory_dependency import DirectoryDependency
+from poetry.core.packages.file_dependency import FileDependency
+from poetry.core.packages.vcs_dependency import VCSDependency
 from poetry.puzzle.provider import Provider
 from poetry.repositories.pool import Pool
 from poetry.repositories.repository import Repository
diff --git a/tests/puzzle/test_solver.py b/tests/puzzle/test_solver.py
index 415f6bcea09..9b99ac3def5 100644
--- a/tests/puzzle/test_solver.py
+++ b/tests/puzzle/test_solver.py
@@ -2,15 +2,15 @@
 
 from clikit.io import NullIO
 
-from poetry.packages import ProjectPackage
-from poetry.packages import dependency_from_pep_508
+from poetry.core.packages import ProjectPackage
+from poetry.core.packages import dependency_from_pep_508
+from poetry.core.version.markers import parse_marker
 from poetry.puzzle import Solver
 from poetry.puzzle.exceptions import SolverProblemError
 from poetry.repositories.installed_repository import InstalledRepository
 from poetry.repositories.pool import Pool
 from poetry.repositories.repository import Repository
 from poetry.utils._compat import Path
-from poetry.version.markers import parse_marker
 from tests.helpers import get_dependency
 from tests.helpers import get_package
 from tests.repositories.test_legacy_repository import (
@@ -1060,9 +1060,6 @@ def test_solver_triggers_conflict_for_dependency_python_not_fully_compatible_wit
         solver.solve()
 
 
-@pytest.mark.skip(
-    "This is not working at the moment due to limitations in the resolver"
-)
 def test_solver_finds_compatible_package_for_dependency_python_not_fully_compatible_with_package_python(
     solver, repo, package
 ):
@@ -1686,7 +1683,7 @@ def test_solver_chooses_from_correct_repository_if_forced(
         ops, [{"job": "install", "package": get_package("tomlkit", "0.5.2")}]
     )
 
-    assert "http://foo.bar" == ops[0].package.source_url
+    assert "http://legacy.foo.bar" == ops[0].package.source_url
 
 
 def test_solver_chooses_from_correct_repository_if_forced_and_transitive_dependency(
@@ -1714,7 +1711,7 @@ def test_solver_chooses_from_correct_repository_if_forced_and_transitive_depende
         ],
     )
 
-    assert "http://foo.bar" == ops[0].package.source_url
+    assert "http://legacy.foo.bar" == ops[0].package.source_url
 
     assert "" == ops[1].package.source_type
     assert "" == ops[1].package.source_url
@@ -1743,10 +1740,10 @@ def test_solver_does_not_choose_from_secondary_repository_by_default(
         ],
     )
 
-    assert "http://foo.bar" == ops[0].package.source_url
+    assert "http://legacy.foo.bar" == ops[0].package.source_url
     assert "" == ops[1].package.source_type
     assert "" == ops[1].package.source_url
-    assert "http://foo.bar" == ops[2].package.source_url
+    assert "http://legacy.foo.bar" == ops[2].package.source_url
 
 
 def test_solver_chooses_from_secondary_if_explicit(package, installed, locked, io):
@@ -1770,7 +1767,7 @@ def test_solver_chooses_from_secondary_if_explicit(package, installed, locked, i
         ],
     )
 
-    assert "http://foo.bar" == ops[0].package.source_url
+    assert "http://legacy.foo.bar" == ops[0].package.source_url
     assert "" == ops[1].package.source_type
     assert "" == ops[1].package.source_url
     assert "" == ops[2].package.source_type
@@ -1928,3 +1925,37 @@ def test_solver_properly_propagates_markers(solver, repo, package):
         str(ops[0].package.marker)
         == 'python_version >= "3.6" and implementation_name != "pypy"'
     )
+
+
+def test_solver_should_not_go_into_an_infinite_loop_on_duplicate_dependencies(
+    solver, repo, package
+):
+    package.python_versions = "~2.7 || ^3.5"
+    package.add_dependency("A", "^1.0")
+
+    package_a = get_package("A", "1.0.0")
+    package_a.add_dependency("B")
+    package_a.add_dependency(
+        "B", {"version": "^1.0", "markers": "implementation_name == 'pypy'"}
+    )
+
+    package_b20 = get_package("B", "2.0.0")
+    package_b10 = get_package("B", "1.0.0")
+
+    repo.add_package(package_a)
+    repo.add_package(package_b10)
+    repo.add_package(package_b20)
+
+    ops = solver.solve()
+
+    check_solver_result(
+        ops,
+        [
+            {"job": "install", "package": package_b10},
+            {"job": "install", "package": package_b20},
+            {"job": "install", "package": package_a},
+        ],
+    )
+
+    assert 'implementation_name == "pypy"' == str(ops[0].package.marker)
+    assert 'implementation_name != "pypy"' == str(ops[1].package.marker)
diff --git a/tests/repositories/fixtures/installed/vendor/py3.7/attrs-19.3.0.dist-info/METADATA b/tests/repositories/fixtures/installed/vendor/py3.7/attrs-19.3.0.dist-info/METADATA
new file mode 100644
index 00000000000..a1064151030
--- /dev/null
+++ b/tests/repositories/fixtures/installed/vendor/py3.7/attrs-19.3.0.dist-info/METADATA
@@ -0,0 +1,229 @@
+Metadata-Version: 2.1
+Name: attrs
+Version: 19.3.0
+Summary: Classes Without Boilerplate
+Home-page: https://www.attrs.org/
+Author: Hynek Schlawack
+Author-email: hs@ox.cx
+Maintainer: Hynek Schlawack
+Maintainer-email: hs@ox.cx
+License: MIT
+Project-URL: Documentation, https://www.attrs.org/
+Project-URL: Bug Tracker, https://github.com/python-attrs/attrs/issues
+Project-URL: Source Code, https://github.com/python-attrs/attrs
+Keywords: class,attribute,boilerplate
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: Natural Language :: English
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
+Description-Content-Type: text/x-rst
+Provides-Extra: azure-pipelines
+Requires-Dist: coverage ; extra == 'azure-pipelines'
+Requires-Dist: hypothesis ; extra == 'azure-pipelines'
+Requires-Dist: pympler ; extra == 'azure-pipelines'
+Requires-Dist: pytest (>=4.3.0) ; extra == 'azure-pipelines'
+Requires-Dist: six ; extra == 'azure-pipelines'
+Requires-Dist: zope.interface ; extra == 'azure-pipelines'
+Requires-Dist: pytest-azurepipelines ; extra == 'azure-pipelines'
+Provides-Extra: dev
+Requires-Dist: coverage ; extra == 'dev'
+Requires-Dist: hypothesis ; extra == 'dev'
+Requires-Dist: pympler ; extra == 'dev'
+Requires-Dist: pytest (>=4.3.0) ; extra == 'dev'
+Requires-Dist: six ; extra == 'dev'
+Requires-Dist: zope.interface ; extra == 'dev'
+Requires-Dist: sphinx ; extra == 'dev'
+Requires-Dist: pre-commit ; extra == 'dev'
+Provides-Extra: docs
+Requires-Dist: sphinx ; extra == 'docs'
+Requires-Dist: zope.interface ; extra == 'docs'
+Provides-Extra: tests
+Requires-Dist: coverage ; extra == 'tests'
+Requires-Dist: hypothesis ; extra == 'tests'
+Requires-Dist: pympler ; extra == 'tests'
+Requires-Dist: pytest (>=4.3.0) ; extra == 'tests'
+Requires-Dist: six ; extra == 'tests'
+Requires-Dist: zope.interface ; extra == 'tests'
+
+.. image:: https://www.attrs.org/en/latest/_static/attrs_logo.png
+   :alt: attrs Logo
+
+======================================
+``attrs``: Classes Without Boilerplate
+======================================
+
+.. image:: https://readthedocs.org/projects/attrs/badge/?version=stable
+   :target: https://www.attrs.org/en/stable/?badge=stable
+   :alt: Documentation Status
+
+.. image:: https://attrs.visualstudio.com/attrs/_apis/build/status/python-attrs.attrs?branchName=master
+   :target: https://attrs.visualstudio.com/attrs/_build/latest?definitionId=1&branchName=master
+   :alt: CI Status
+
+.. image:: https://codecov.io/github/python-attrs/attrs/branch/master/graph/badge.svg
+   :target: https://codecov.io/github/python-attrs/attrs
+   :alt: Test Coverage
+
+.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
+   :target: https://github.com/psf/black
+   :alt: Code style: black
+
+.. teaser-begin
+
+``attrs`` is the Python package that will bring back the **joy** of **writing classes** by relieving you from the drudgery of implementing object protocols (aka `dunder `_ methods).
+
+Its main goal is to help you to write **concise** and **correct** software without slowing down your code.
+
+.. -spiel-end-
+
+For that, it gives you a class decorator and a way to declaratively define the attributes on that class:
+
+.. -code-begin-
+
+.. code-block:: pycon
+
+   >>> import attr
+
+   >>> @attr.s
+   ... class SomeClass(object):
+   ...     a_number = attr.ib(default=42)
+   ...     list_of_numbers = attr.ib(factory=list)
+   ...
+   ...     def hard_math(self, another_number):
+   ...         return self.a_number + sum(self.list_of_numbers) * another_number
+
+
+   >>> sc = SomeClass(1, [1, 2, 3])
+   >>> sc
+   SomeClass(a_number=1, list_of_numbers=[1, 2, 3])
+
+   >>> sc.hard_math(3)
+   19
+   >>> sc == SomeClass(1, [1, 2, 3])
+   True
+   >>> sc != SomeClass(2, [3, 2, 1])
+   True
+
+   >>> attr.asdict(sc)
+   {'a_number': 1, 'list_of_numbers': [1, 2, 3]}
+
+   >>> SomeClass()
+   SomeClass(a_number=42, list_of_numbers=[])
+
+   >>> C = attr.make_class("C", ["a", "b"])
+   >>> C("foo", "bar")
+   C(a='foo', b='bar')
+
+
+After *declaring* your attributes ``attrs`` gives you:
+
+- a concise and explicit overview of the class's attributes,
+- a nice human-readable ``__repr__``,
+- a complete set of comparison methods (equality and ordering),
+- an initializer,
+- and much more,
+
+*without* writing dull boilerplate code again and again and *without* runtime performance penalties.
+
+On Python 3.6 and later, you can often even drop the calls to ``attr.ib()`` by using `type annotations `_.
+
+This gives you the power to use actual classes with actual types in your code instead of confusing ``tuple``\ s or `confusingly behaving `_ ``namedtuple``\ s.
+Which in turn encourages you to write *small classes* that do `one thing well `_.
+Never again violate the `single responsibility principle `_ just because implementing ``__init__`` et al is a painful drag.
+
+
+.. -testimonials-
+
+Testimonials
+============
+
+**Amber Hawkie Brown**, Twisted Release Manager and Computer Owl:
+
+  Writing a fully-functional class using attrs takes me less time than writing this testimonial.
+
+
+**Glyph Lefkowitz**, creator of `Twisted `_, `Automat `_, and other open source software, in `The One Python Library Everyone Needs `_:
+
+  I’m looking forward to is being able to program in Python-with-attrs everywhere.
+  It exerts a subtle, but positive, design influence in all the codebases I’ve see it used in.
+
+
+**Kenneth Reitz**, creator of `Requests `_ (`on paper no less `_!):
+
+  attrs—classes for humans.  I like it.
+
+
+**Łukasz Langa**, creator of `Black `_, prolific Python core developer, and release manager for Python 3.8 and 3.9:
+
+  I'm increasingly digging your attr.ocity. Good job!
+
+
+.. -end-
+
+.. -project-information-
+
+Getting Help
+============
+
+Please use the ``python-attrs`` tag on `StackOverflow `_ to get help.
+
+Answering questions of your fellow developers is also great way to help the project!
+
+
+Project Information
+===================
+
+``attrs`` is released under the `MIT `_ license,
+its documentation lives at `Read the Docs `_,
+the code on `GitHub `_,
+and the latest release on `PyPI `_.
+It’s rigorously tested on Python 2.7, 3.4+, and PyPy.
+
+We collect information on **third-party extensions** in our `wiki `_.
+Feel free to browse and add your own!
+
+If you'd like to contribute to ``attrs`` you're most welcome and we've written `a little guide `_ to get you started!
+
+
+Release Information
+===================
+
+19.3.0 (2019-10-15)
+-------------------
+
+Changes
+^^^^^^^
+
+- Fixed ``auto_attribs`` usage when default values cannot be compared directly with ``==``, such as ``numpy`` arrays.
+  `#585 `_
+
+`Full changelog `_.
+
+Credits
+=======
+
+``attrs`` is written and maintained by `Hynek Schlawack `_.
+
+The development is kindly supported by `Variomedia AG `_.
+
+A full list of contributors can be found in `GitHub's overview `_.
+
+It’s the spiritual successor of `characteristic `_ and aspires to fix some of it clunkiness and unfortunate decisions.
+Both were inspired by Twisted’s `FancyEqMixin `_ but both are implemented using class decorators because `subclassing is bad for you `_, m’kay?
+
+
diff --git a/tests/repositories/test_installed_repository.py b/tests/repositories/test_installed_repository.py
index 27a3a5bf2bd..c35ad49df4a 100644
--- a/tests/repositories/test_installed_repository.py
+++ b/tests/repositories/test_installed_repository.py
@@ -9,12 +9,14 @@
 ENV_DIR = (FIXTURES_DIR / "installed").resolve()
 SITE_PACKAGES = ENV_DIR / "lib" / "python3.7" / "site-packages"
 SRC = ENV_DIR / "src"
+VENDOR_DIR = ENV_DIR / "vendor" / "py3.7"
 INSTALLED_RESULTS = [
     metadata.PathDistribution(SITE_PACKAGES / "cleo-0.7.6.dist-info"),
     metadata.PathDistribution(SRC / "pendulum" / "pendulum.egg-info"),
     metadata.PathDistribution(
         zipp.Path(str(SITE_PACKAGES / "foo-0.1.0-py3.8.egg"), "EGG-INFO")
     ),
+    metadata.PathDistribution(VENDOR_DIR / "attrs-19.3.0.dist-info"),
 ]
 
 
@@ -30,16 +32,17 @@ def test_load(mocker):
         return_value=INSTALLED_RESULTS,
     )
     mocker.patch(
-        "poetry.vcs.git.Git.rev_parse",
+        "poetry.core.vcs.git.Git.rev_parse",
         return_value="bb058f6b78b2d28ef5d9a5e759cfa179a1a713d6",
     )
     mocker.patch(
-        "poetry.vcs.git.Git.remote_urls",
+        "poetry.core.vcs.git.Git.remote_urls",
         side_effect=[
             {"remote.origin.url": "https://github.com/sdispater/pendulum.git"},
             {"remote.origin.url": "git@github.com:sdispater/pendulum.git"},
         ],
     )
+    mocker.patch("poetry.repositories.installed_repository._VENDORS", str(VENDOR_DIR))
     repository = InstalledRepository.load(MockEnv(path=ENV_DIR))
 
     assert len(repository.packages) == 3
@@ -63,3 +66,6 @@ def test_load(mocker):
     assert pendulum.source_type == "git"
     assert pendulum.source_url == "https://github.com/sdispater/pendulum.git"
     assert pendulum.source_reference == "bb058f6b78b2d28ef5d9a5e759cfa179a1a713d6"
+
+    for pkg in repository.packages:
+        assert pkg.name != "attrs"
diff --git a/tests/repositories/test_legacy_repository.py b/tests/repositories/test_legacy_repository.py
index e2fe53a3773..5413dfc7090 100644
--- a/tests/repositories/test_legacy_repository.py
+++ b/tests/repositories/test_legacy_repository.py
@@ -2,7 +2,7 @@
 
 import pytest
 
-from poetry.packages import Dependency
+from poetry.core.packages import Dependency
 from poetry.repositories.auth import Auth
 from poetry.repositories.exceptions import PackageNotFound
 from poetry.repositories.legacy_repository import LegacyRepository
@@ -23,7 +23,7 @@ class MockRepository(LegacyRepository):
 
     def __init__(self, auth=None):
         super(MockRepository, self).__init__(
-            "legacy", url="http://foo.bar", auth=auth, disable_cache=True
+            "legacy", url="http://legacy.foo.bar", auth=auth, disable_cache=True
         )
 
     def _get(self, endpoint):
@@ -50,7 +50,7 @@ def test_page_relative_links_path_are_correct():
     page = repo._get("/relative")
 
     for link in page.links:
-        assert link.netloc == "foo.bar"
+        assert link.netloc == "legacy.foo.bar"
         assert link.path.startswith("/relative/poetry")
 
 
@@ -267,7 +267,7 @@ def test_get_package_retrieves_packages_with_no_hashes():
 
 
 def test_username_password_special_chars():
-    auth = Auth("http://foo.bar", "user:", "p@ssword")
+    auth = Auth("http://legacy.foo.bar", "user:", "/%2Fp@ssword")
     repo = MockRepository(auth=auth)
 
-    assert "http://user%3A:p%40ssword@foo.bar" == repo.authenticated_url
+    assert "http://user%3A:%2F%252Fp%40ssword@legacy.foo.bar" == repo.authenticated_url
diff --git a/tests/repositories/test_pypi_repository.py b/tests/repositories/test_pypi_repository.py
index 48f47880046..be522bdb375 100644
--- a/tests/repositories/test_pypi_repository.py
+++ b/tests/repositories/test_pypi_repository.py
@@ -8,7 +8,7 @@
 from requests.exceptions import TooManyRedirects
 from requests.models import Response
 
-from poetry.packages import Dependency
+from poetry.core.packages import Dependency
 from poetry.repositories.pypi_repository import PyPiRepository
 from poetry.utils._compat import PY35
 from poetry.utils._compat import Path
@@ -208,3 +208,10 @@ def test_get_should_invalid_cache_on_too_many_redirects_error(mocker):
     repository._get("https://pypi.org/pypi/async-timeout/json")
 
     assert delete_cache.called
+
+
+def test_urls():
+    repository = PyPiRepository()
+
+    assert "https://pypi.org/simple/" == repository.url
+    assert "https://pypi.org/simple/" == repository.authenticated_url
diff --git a/tests/semver/__init__.py b/tests/semver/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/semver/test_main.py b/tests/semver/test_main.py
deleted file mode 100644
index 4610e8d4573..00000000000
--- a/tests/semver/test_main.py
+++ /dev/null
@@ -1,200 +0,0 @@
-import pytest
-
-from poetry.semver import Version
-from poetry.semver import VersionRange
-from poetry.semver import VersionUnion
-from poetry.semver import parse_constraint
-
-
-@pytest.mark.parametrize(
-    "input,constraint",
-    [
-        ("*", VersionRange()),
-        ("*.*", VersionRange()),
-        ("v*.*", VersionRange()),
-        ("*.x.*", VersionRange()),
-        ("x.X.x.*", VersionRange()),
-        # ('!=1.0.0', Constraint('!=', '1.0.0.0')),
-        (">1.0.0", VersionRange(min=Version(1, 0, 0))),
-        ("<1.2.3", VersionRange(max=Version(1, 2, 3))),
-        ("<=1.2.3", VersionRange(max=Version(1, 2, 3), include_max=True)),
-        (">=1.2.3", VersionRange(min=Version(1, 2, 3), include_min=True)),
-        ("=1.2.3", Version(1, 2, 3)),
-        ("1.2.3", Version(1, 2, 3)),
-        ("=1.0", Version(1, 0, 0)),
-        ("1.2.3b5", Version(1, 2, 3, pre="b5")),
-        (">= 1.2.3", VersionRange(min=Version(1, 2, 3), include_min=True)),
-        (">dev", VersionRange(min=Version(0, 0, pre="dev"))),  # Issue 206
-    ],
-)
-def test_parse_constraint(input, constraint):
-    assert parse_constraint(input) == constraint
-
-
-@pytest.mark.parametrize(
-    "input,constraint",
-    [
-        ("v2.*", VersionRange(Version(2, 0, 0), Version(3, 0, 0), True)),
-        ("2.*.*", VersionRange(Version(2, 0, 0), Version(3, 0, 0), True)),
-        ("20.*", VersionRange(Version(20, 0, 0), Version(21, 0, 0), True)),
-        ("20.*.*", VersionRange(Version(20, 0, 0), Version(21, 0, 0), True)),
-        ("2.0.*", VersionRange(Version(2, 0, 0), Version(2, 1, 0), True)),
-        ("2.x", VersionRange(Version(2, 0, 0), Version(3, 0, 0), True)),
-        ("2.x.x", VersionRange(Version(2, 0, 0), Version(3, 0, 0), True)),
-        ("2.2.X", VersionRange(Version(2, 2, 0), Version(2, 3, 0), True)),
-        ("0.*", VersionRange(max=Version(1, 0, 0))),
-        ("0.*.*", VersionRange(max=Version(1, 0, 0))),
-        ("0.x", VersionRange(max=Version(1, 0, 0))),
-    ],
-)
-def test_parse_constraint_wildcard(input, constraint):
-    assert parse_constraint(input) == constraint
-
-
-@pytest.mark.parametrize(
-    "input,constraint",
-    [
-        ("~v1", VersionRange(Version(1, 0, 0), Version(2, 0, 0), True)),
-        ("~1.0", VersionRange(Version(1, 0, 0), Version(1, 1, 0), True)),
-        ("~1.0.0", VersionRange(Version(1, 0, 0), Version(1, 1, 0), True)),
-        ("~1.2", VersionRange(Version(1, 2, 0), Version(1, 3, 0), True)),
-        ("~1.2.3", VersionRange(Version(1, 2, 3), Version(1, 3, 0), True)),
-        (
-            "~1.2-beta",
-            VersionRange(Version(1, 2, 0, pre="beta"), Version(1, 3, 0), True),
-        ),
-        ("~1.2-b2", VersionRange(Version(1, 2, 0, pre="b2"), Version(1, 3, 0), True)),
-        ("~0.3", VersionRange(Version(0, 3, 0), Version(0, 4, 0), True)),
-        ("~3.5", VersionRange(Version(3, 5, 0), Version(3, 6, 0), True)),
-        ("~=3.5", VersionRange(Version(3, 5, 0), Version(4, 0, 0), True)),  # PEP 440
-        ("~=3.5.3", VersionRange(Version(3, 5, 3), Version(3, 6, 0), True)),  # PEP 440
-        (
-            "~=3.5.3rc1",
-            VersionRange(Version(3, 5, 3, pre="rc1"), Version(3, 6, 0), True),
-        ),  # PEP 440
-    ],
-)
-def test_parse_constraint_tilde(input, constraint):
-    assert parse_constraint(input) == constraint
-
-
-@pytest.mark.parametrize(
-    "input,constraint",
-    [
-        ("^v1", VersionRange(Version(1, 0, 0), Version(2, 0, 0), True)),
-        ("^0", VersionRange(Version(0, 0, 0), Version(1, 0, 0), True)),
-        ("^0.0", VersionRange(Version(0, 0, 0), Version(0, 1, 0), True)),
-        ("^1.2", VersionRange(Version(1, 2, 0), Version(2, 0, 0), True)),
-        (
-            "^1.2.3-beta.2",
-            VersionRange(Version(1, 2, 3, pre="beta.2"), Version(2, 0, 0), True),
-        ),
-        ("^1.2.3", VersionRange(Version(1, 2, 3), Version(2, 0, 0), True)),
-        ("^0.2.3", VersionRange(Version(0, 2, 3), Version(0, 3, 0), True)),
-        ("^0.2", VersionRange(Version(0, 2, 0), Version(0, 3, 0), True)),
-        ("^0.2.0", VersionRange(Version(0, 2, 0), Version(0, 3, 0), True)),
-        ("^0.0.3", VersionRange(Version(0, 0, 3), Version(0, 0, 4), True)),
-    ],
-)
-def test_parse_constraint_caret(input, constraint):
-    assert parse_constraint(input) == constraint
-
-
-@pytest.mark.parametrize(
-    "input",
-    [
-        ">2.0,<=3.0",
-        ">2.0 <=3.0",
-        ">2.0  <=3.0",
-        ">2.0, <=3.0",
-        ">2.0 ,<=3.0",
-        ">2.0 , <=3.0",
-        ">2.0   , <=3.0",
-        "> 2.0   <=  3.0",
-        "> 2.0  ,  <=  3.0",
-        "  > 2.0  ,  <=  3.0 ",
-    ],
-)
-def test_parse_constraint_multi(input):
-    assert parse_constraint(input) == VersionRange(
-        Version(2, 0, 0), Version(3, 0, 0), include_min=False, include_max=True
-    )
-
-
-@pytest.mark.parametrize(
-    "input",
-    [">=2.7,!=3.0.*,!=3.1.*", ">=2.7, !=3.0.*, !=3.1.*", ">= 2.7, != 3.0.*, != 3.1.*"],
-)
-def test_parse_constraint_multi_wilcard(input):
-    assert parse_constraint(input) == VersionUnion(
-        VersionRange(Version(2, 7, 0), Version(3, 0, 0), True, False),
-        VersionRange(Version(3, 2, 0), None, True, False),
-    )
-
-
-@pytest.mark.parametrize(
-    "input,constraint",
-    [
-        (
-            "!=v2.*",
-            VersionRange(max=Version.parse("2.0")).union(
-                VersionRange(Version.parse("3.0"), include_min=True)
-            ),
-        ),
-        (
-            "!=2.*.*",
-            VersionRange(max=Version.parse("2.0")).union(
-                VersionRange(Version.parse("3.0"), include_min=True)
-            ),
-        ),
-        (
-            "!=2.0.*",
-            VersionRange(max=Version.parse("2.0")).union(
-                VersionRange(Version.parse("2.1"), include_min=True)
-            ),
-        ),
-        ("!=0.*", VersionRange(Version.parse("1.0"), include_min=True)),
-        ("!=0.*.*", VersionRange(Version.parse("1.0"), include_min=True)),
-    ],
-)
-def test_parse_constraints_negative_wildcard(input, constraint):
-    assert parse_constraint(input) == constraint
-
-
-@pytest.mark.parametrize(
-    "input, expected",
-    [
-        ("1", "1"),
-        ("1.2", "1.2"),
-        ("1.2.3", "1.2.3"),
-        ("!=1", "!=1"),
-        ("!=1.2", "!=1.2"),
-        ("!=1.2.3", "!=1.2.3"),
-        ("^1", ">=1,<2"),
-        ("^1.0", ">=1.0,<2.0"),
-        ("^1.0.0", ">=1.0.0,<2.0.0"),
-        ("~1", ">=1,<2"),
-        ("~1.0", ">=1.0,<1.1"),
-        ("~1.0.0", ">=1.0.0,<1.1.0"),
-    ],
-)
-def test_constraints_keep_version_precision(input, expected):
-    assert str(parse_constraint(input)) == expected
-
-
-@pytest.mark.parametrize(
-    "unsorted, sorted_",
-    [
-        (["1.0.3", "1.0.2", "1.0.1"], ["1.0.1", "1.0.2", "1.0.3"]),
-        (["1.0.0.2", "1.0.0.0rc2"], ["1.0.0.0rc2", "1.0.0.2"]),
-        (["1.0.0.0", "1.0.0.0rc2"], ["1.0.0.0rc2", "1.0.0.0"]),
-        (["1.0.0.0.0", "1.0.0.0rc2"], ["1.0.0.0rc2", "1.0.0.0.0"]),
-        (["1.0.0rc2", "1.0.0rc1"], ["1.0.0rc1", "1.0.0rc2"]),
-        (["1.0.0rc2", "1.0.0b1"], ["1.0.0b1", "1.0.0rc2"]),
-    ],
-)
-def test_versions_are_sortable(unsorted, sorted_):
-    unsorted = [parse_constraint(u) for u in unsorted]
-    sorted_ = [parse_constraint(s) for s in sorted_]
-
-    assert sorted(unsorted) == sorted_
diff --git a/tests/semver/test_version.py b/tests/semver/test_version.py
deleted file mode 100644
index b05167dd5dd..00000000000
--- a/tests/semver/test_version.py
+++ /dev/null
@@ -1,165 +0,0 @@
-import pytest
-
-from poetry.semver import EmptyConstraint
-from poetry.semver import Version
-from poetry.semver import VersionRange
-from poetry.semver.exceptions import ParseVersionError
-
-
-@pytest.mark.parametrize(
-    "input,version",
-    [
-        ("1.0.0", Version(1, 0, 0)),
-        ("1", Version(1, 0, 0)),
-        ("1.0", Version(1, 0, 0)),
-        ("1b1", Version(1, 0, 0, pre="beta1")),
-        ("1.0b1", Version(1, 0, 0, pre="beta1")),
-        ("1.0.0b1", Version(1, 0, 0, pre="beta1")),
-        ("1.0.0-b1", Version(1, 0, 0, pre="beta1")),
-        ("1.0.0-beta.1", Version(1, 0, 0, pre="beta1")),
-        ("1.0.0+1", Version(1, 0, 0, build="1")),
-        ("1.0.0-1", Version(1, 0, 0, build="1")),
-        ("1.0.0.0", Version(1, 0, 0)),
-        ("1.0.0-post", Version(1, 0, 0)),
-        ("1.0.0-post1", Version(1, 0, 0, build="1")),
-        ("0.6c", Version(0, 6, 0, pre="rc0")),
-        ("0.6pre", Version(0, 6, 0, pre="rc0")),
-    ],
-)
-def test_parse_valid(input, version):
-    parsed = Version.parse(input)
-
-    assert parsed == version
-    assert parsed.text == input
-
-
-@pytest.mark.parametrize("input", [(None, "example")])
-def test_parse_invalid(input):
-    with pytest.raises(ParseVersionError):
-        Version.parse(input)
-
-
-def test_comparison():
-    versions = [
-        "1.0.0-alpha",
-        "1.0.0-alpha.1",
-        "1.0.0-beta.2",
-        "1.0.0-beta.11",
-        "1.0.0-rc.1",
-        "1.0.0-rc.1+build.1",
-        "1.0.0",
-        "1.0.0+0.3.7",
-        "1.3.7+build",
-        "1.3.7+build.2.b8f12d7",
-        "1.3.7+build.11.e0f985a",
-        "2.0.0",
-        "2.1.0",
-        "2.2.0",
-        "2.11.0",
-        "2.11.1",
-    ]
-
-    for i in range(len(versions)):
-        for j in range(len(versions)):
-            a = Version.parse(versions[i])
-            b = Version.parse(versions[j])
-
-            assert (a < b) == (i < j)
-            assert (a > b) == (i > j)
-            assert (a <= b) == (i <= j)
-            assert (a >= b) == (i >= j)
-            assert (a == b) == (i == j)
-            assert (a != b) == (i != j)
-
-
-def test_equality():
-    assert Version.parse("1.2.3") == Version.parse("01.2.3")
-    assert Version.parse("1.2.3") == Version.parse("1.02.3")
-    assert Version.parse("1.2.3") == Version.parse("1.2.03")
-    assert Version.parse("1.2.3-1") == Version.parse("1.2.3-01")
-    assert Version.parse("1.2.3+1") == Version.parse("1.2.3+01")
-
-
-def test_allows():
-    v = Version.parse("1.2.3")
-    assert v.allows(v)
-    assert not v.allows(Version.parse("2.2.3"))
-    assert not v.allows(Version.parse("1.3.3"))
-    assert not v.allows(Version.parse("1.2.4"))
-    assert not v.allows(Version.parse("1.2.3-dev"))
-    assert not v.allows(Version.parse("1.2.3+build"))
-
-
-def test_allows_all():
-    v = Version.parse("1.2.3")
-
-    assert v.allows_all(v)
-    assert not v.allows_all(Version.parse("0.0.3"))
-    assert not v.allows_all(
-        VersionRange(Version.parse("1.1.4"), Version.parse("1.2.4"))
-    )
-    assert not v.allows_all(VersionRange())
-    assert v.allows_all(EmptyConstraint())
-
-
-def test_allows_any():
-    v = Version.parse("1.2.3")
-
-    assert v.allows_any(v)
-    assert not v.allows_any(Version.parse("0.0.3"))
-    assert v.allows_any(VersionRange(Version.parse("1.1.4"), Version.parse("1.2.4")))
-    assert v.allows_any(VersionRange())
-    assert not v.allows_any(EmptyConstraint())
-
-
-def test_intersect():
-    v = Version.parse("1.2.3")
-
-    assert v.intersect(v) == v
-    assert v.intersect(Version.parse("1.1.4")).is_empty()
-    assert (
-        v.intersect(VersionRange(Version.parse("1.1.4"), Version.parse("1.2.4"))) == v
-    )
-    assert (
-        Version.parse("1.1.4")
-        .intersect(VersionRange(v, Version.parse("1.2.4")))
-        .is_empty()
-    )
-
-
-def test_union():
-    v = Version.parse("1.2.3")
-
-    assert v.union(v) == v
-
-    result = v.union(Version.parse("0.8.0"))
-    assert result.allows(v)
-    assert result.allows(Version.parse("0.8.0"))
-    assert not result.allows(Version.parse("1.1.4"))
-
-    range = VersionRange(Version.parse("1.1.4"), Version.parse("1.2.4"))
-    assert v.union(range) == range
-
-    union = Version.parse("1.1.4").union(
-        VersionRange(Version.parse("1.1.4"), Version.parse("1.2.4"))
-    )
-    assert union == VersionRange(
-        Version.parse("1.1.4"), Version.parse("1.2.4"), include_min=True
-    )
-
-    result = v.union(VersionRange(Version.parse("0.0.3"), Version.parse("1.1.4")))
-    assert result.allows(v)
-    assert result.allows(Version.parse("0.1.0"))
-
-
-def test_difference():
-    v = Version.parse("1.2.3")
-
-    assert v.difference(v).is_empty()
-    assert v.difference(Version.parse("0.8.0")) == v
-    assert v.difference(
-        VersionRange(Version.parse("1.1.4"), Version.parse("1.2.4"))
-    ).is_empty()
-    assert (
-        v.difference(VersionRange(Version.parse("1.4.0"), Version.parse("3.0.0"))) == v
-    )
diff --git a/tests/semver/test_version_range.py b/tests/semver/test_version_range.py
deleted file mode 100644
index fa5cde59be4..00000000000
--- a/tests/semver/test_version_range.py
+++ /dev/null
@@ -1,260 +0,0 @@
-import pytest
-
-from poetry.semver import EmptyConstraint
-from poetry.semver import Version
-from poetry.semver import VersionRange
-
-
-@pytest.fixture()
-def v003():
-    return Version.parse("0.0.3")
-
-
-@pytest.fixture()
-def v010():
-    return Version.parse("0.1.0")
-
-
-@pytest.fixture()
-def v080():
-    return Version.parse("0.8.0")
-
-
-@pytest.fixture()
-def v072():
-    return Version.parse("0.7.2")
-
-
-@pytest.fixture()
-def v114():
-    return Version.parse("1.1.4")
-
-
-@pytest.fixture()
-def v123():
-    return Version.parse("1.2.3")
-
-
-@pytest.fixture()
-def v124():
-    return Version.parse("1.2.4")
-
-
-@pytest.fixture()
-def v130():
-    return Version.parse("1.3.0")
-
-
-@pytest.fixture()
-def v140():
-    return Version.parse("1.4.0")
-
-
-@pytest.fixture()
-def v200():
-    return Version.parse("2.0.0")
-
-
-@pytest.fixture()
-def v234():
-    return Version.parse("2.3.4")
-
-
-@pytest.fixture()
-def v250():
-    return Version.parse("2.5.0")
-
-
-@pytest.fixture()
-def v300():
-    return Version.parse("3.0.0")
-
-
-def test_allows_all(v003, v010, v080, v114, v123, v124, v140, v200, v234, v250, v300):
-    assert VersionRange(v123, v250).allows_all(EmptyConstraint())
-
-    range = VersionRange(v123, v250, include_max=True)
-    assert not range.allows_all(v123)
-    assert range.allows_all(v124)
-    assert range.allows_all(v250)
-    assert not range.allows_all(v300)
-
-    # with no min
-    range = VersionRange(max=v250)
-    assert range.allows_all(VersionRange(v080, v140))
-    assert not range.allows_all(VersionRange(v080, v300))
-    assert range.allows_all(VersionRange(max=v140))
-    assert not range.allows_all(VersionRange(max=v300))
-    assert range.allows_all(range)
-    assert not range.allows_all(VersionRange())
-
-    # with no max
-    range = VersionRange(min=v010)
-    assert range.allows_all(VersionRange(v080, v140))
-    assert not range.allows_all(VersionRange(v003, v140))
-    assert range.allows_all(VersionRange(v080))
-    assert not range.allows_all(VersionRange(v003))
-    assert range.allows_all(range)
-    assert not range.allows_all(VersionRange())
-
-    # Allows bordering range that is not more inclusive
-    exclusive = VersionRange(v010, v250)
-    inclusive = VersionRange(v010, v250, True, True)
-    assert inclusive.allows_all(exclusive)
-    assert inclusive.allows_all(inclusive)
-    assert not exclusive.allows_all(inclusive)
-    assert exclusive.allows_all(exclusive)
-
-    # Allows unions that are completely contained
-    range = VersionRange(v114, v200)
-    assert range.allows_all(VersionRange(v123, v124).union(v140))
-    assert not range.allows_all(VersionRange(v010, v124).union(v140))
-    assert not range.allows_all(VersionRange(v123, v234).union(v140))
-
-
-def test_allows_any(
-    v003, v010, v072, v080, v114, v123, v124, v140, v200, v234, v250, v300
-):
-    # disallows an empty constraint
-    assert not VersionRange(v123, v250).allows_any(EmptyConstraint())
-
-    # allows allowed versions
-    range = VersionRange(v123, v250, include_max=True)
-    assert not range.allows_any(v123)
-    assert range.allows_any(v124)
-    assert range.allows_any(v250)
-    assert not range.allows_any(v300)
-
-    # with no min
-    range = VersionRange(max=v200)
-    assert range.allows_any(VersionRange(v140, v300))
-    assert not range.allows_any(VersionRange(v234, v300))
-    assert range.allows_any(VersionRange(v140))
-    assert not range.allows_any(VersionRange(v234))
-    assert range.allows_any(range)
-
-    # with no max
-    range = VersionRange(min=v072)
-    assert range.allows_any(VersionRange(v003, v140))
-    assert not range.allows_any(VersionRange(v003, v010))
-    assert range.allows_any(VersionRange(max=v080))
-    assert not range.allows_any(VersionRange(max=v003))
-    assert range.allows_any(range)
-
-    # with min and max
-    range = VersionRange(v072, v200)
-    assert range.allows_any(VersionRange(v003, v140))
-    assert range.allows_any(VersionRange(v140, v300))
-    assert not range.allows_any(VersionRange(v003, v010))
-    assert not range.allows_any(VersionRange(v234, v300))
-    assert not range.allows_any(VersionRange(max=v010))
-    assert not range.allows_any(VersionRange(v234))
-    assert range.allows_any(range)
-
-    # allows a bordering range when both are inclusive
-    assert not VersionRange(max=v250).allows_any(VersionRange(min=v250))
-    assert not VersionRange(max=v250, include_max=True).allows_any(
-        VersionRange(min=v250)
-    )
-    assert not VersionRange(max=v250).allows_any(
-        VersionRange(min=v250, include_min=True)
-    )
-    assert not VersionRange(min=v250).allows_any(VersionRange(max=v250))
-    assert VersionRange(max=v250, include_max=True).allows_any(
-        VersionRange(min=v250, include_min=True)
-    )
-
-    # allows unions that are partially contained'
-    range = VersionRange(v114, v200)
-    assert range.allows_any(VersionRange(v010, v080).union(v140))
-    assert range.allows_any(VersionRange(v123, v234).union(v300))
-    assert not range.allows_any(VersionRange(v234, v300).union(v010))
-
-    # pre-release min does not allow lesser than itself
-    range = VersionRange(Version.parse("1.9b1"), include_min=True)
-    assert not range.allows_any(
-        VersionRange(
-            Version.parse("1.8.0"),
-            Version.parse("1.9.0"),
-            include_min=True,
-            always_include_max_prerelease=True,
-        )
-    )
-
-
-def test_intersect(v114, v123, v124, v200, v250, v300):
-    # two overlapping ranges
-    assert VersionRange(v123, v250).intersect(VersionRange(v200, v300)) == VersionRange(
-        v200, v250
-    )
-
-    # a non-overlapping range allows no versions
-    a = VersionRange(v114, v124)
-    b = VersionRange(v200, v250)
-    assert a.intersect(b).is_empty()
-
-    # adjacent ranges allow no versions if exclusive
-    a = VersionRange(v114, v124)
-    b = VersionRange(v124, v200)
-    assert a.intersect(b).is_empty()
-
-    # adjacent ranges allow version if inclusive
-    a = VersionRange(v114, v124, include_max=True)
-    b = VersionRange(v124, v200, include_min=True)
-    assert a.intersect(b) == v124
-
-    # with an open range
-    open = VersionRange()
-    a = VersionRange(v114, v124)
-    assert open.intersect(open) == open
-    assert open.intersect(a) == a
-
-    # returns the version if the range allows it
-    assert VersionRange(v114, v124).intersect(v123) == v123
-    assert VersionRange(v123, v124).intersect(v114).is_empty()
-
-
-def test_union(
-    v003, v010, v072, v080, v114, v123, v124, v130, v140, v200, v234, v250, v300
-):
-    # with a version returns the range if it contains the version
-    range = VersionRange(v114, v124)
-    assert range.union(v123) == range
-
-    # with a version on the edge of the range, expands the range
-    range = VersionRange(v114, v124)
-    assert range.union(v124) == VersionRange(v114, v124, include_max=True)
-    assert range.union(v114) == VersionRange(v114, v124, include_min=True)
-
-    # with a version allows both the range and the version if the range
-    # doesn't contain the version
-    result = VersionRange(v003, v114).union(v124)
-    assert result.allows(v010)
-    assert not result.allows(v123)
-    assert result.allows(v124)
-
-    # returns a VersionUnion for a disjoint range
-    result = VersionRange(v003, v114).union(VersionRange(v130, v200))
-    assert result.allows(v080)
-    assert not result.allows(v123)
-    assert result.allows(v140)
-
-    # considers open ranges disjoint
-    result = VersionRange(v003, v114).union(VersionRange(v114, v200))
-    assert result.allows(v080)
-    assert not result.allows(v114)
-    assert result.allows(v140)
-    result = VersionRange(v114, v200).union(VersionRange(v003, v114))
-    assert result.allows(v080)
-    assert not result.allows(v114)
-    assert result.allows(v140)
-
-    # returns a merged range for an overlapping range
-    result = VersionRange(v003, v114).union(VersionRange(v080, v200))
-    assert result == VersionRange(v003, v200)
-
-    # considers closed ranges overlapping
-    result = VersionRange(v003, v114, include_max=True).union(VersionRange(v114, v200))
-    assert result == VersionRange(v003, v200)
-    result = VersionRange(v003, v114).union(VersionRange(v114, v200, include_min=True))
-    assert result == VersionRange(v003, v200)
diff --git a/tests/spdx/__init__.py b/tests/spdx/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/spdx/test_license.py b/tests/spdx/test_license.py
deleted file mode 100644
index 2589045063c..00000000000
--- a/tests/spdx/test_license.py
+++ /dev/null
@@ -1,50 +0,0 @@
-from poetry.spdx import license_by_id
-
-
-def test_classifier_name():
-    license = license_by_id("lgpl-3.0-or-later")
-
-    assert (
-        license.classifier_name
-        == "GNU Lesser General Public License v3 or later (LGPLv3+)"
-    )
-
-
-def test_classifier_name_no_classifer_osi_approved():
-    license = license_by_id("LiLiQ-R-1.1")
-
-    assert license.classifier_name is None
-
-
-def test_classifier_name_no_classifer():
-    license = license_by_id("Leptonica")
-
-    assert license.classifier_name == "Other/Proprietary License"
-
-
-def test_classifier():
-    license = license_by_id("lgpl-3.0-or-later")
-
-    assert license.classifier == (
-        "License :: "
-        "OSI Approved :: "
-        "GNU Lesser General Public License v3 or later (LGPLv3+)"
-    )
-
-
-def test_classifier_no_classifer_osi_approved():
-    license = license_by_id("LiLiQ-R-1.1")
-
-    assert license.classifier == "License :: OSI Approved"
-
-
-def test_classifier_no_classifer():
-    license = license_by_id("Leptonica")
-
-    assert license.classifier == "License :: Other/Proprietary License"
-
-
-def test_proprietary_license():
-    license = license_by_id("Proprietary")
-
-    assert "License :: Other/Proprietary License" == license.classifier
diff --git a/tests/spdx/test_main.py b/tests/spdx/test_main.py
deleted file mode 100644
index 00e0910044d..00000000000
--- a/tests/spdx/test_main.py
+++ /dev/null
@@ -1,43 +0,0 @@
-import pytest
-
-from poetry.spdx import license_by_id
-
-
-def test_license_by_id():
-    license = license_by_id("MIT")
-
-    assert license.id == "MIT"
-    assert license.name == "MIT License"
-    assert license.is_osi_approved
-    assert not license.is_deprecated
-
-    license = license_by_id("LGPL-3.0-or-later")
-
-    assert license.id == "LGPL-3.0-or-later"
-    assert license.name == "GNU Lesser General Public License v3.0 or later"
-    assert license.is_osi_approved
-    assert not license.is_deprecated
-
-
-def test_license_by_id_is_case_insensitive():
-    license = license_by_id("mit")
-
-    assert license.id == "MIT"
-
-    license = license_by_id("miT")
-
-    assert license.id == "MIT"
-
-
-def test_license_by_id_with_full_name():
-    license = license_by_id("GNU Lesser General Public License v3.0 or later")
-
-    assert license.id == "LGPL-3.0-or-later"
-    assert license.name == "GNU Lesser General Public License v3.0 or later"
-    assert license.is_osi_approved
-    assert not license.is_deprecated
-
-
-def test_license_by_id_invalid():
-    with pytest.raises(ValueError):
-        license_by_id("invalid")
diff --git a/tests/test_factory.py b/tests/test_factory.py
index bf3493ae5fa..ffb48965096 100644
--- a/tests/test_factory.py
+++ b/tests/test_factory.py
@@ -113,9 +113,7 @@ def test_create_poetry():
 
 
 def test_create_poetry_with_packages_and_includes():
-    poetry = Factory().create_poetry(
-        fixtures_dir.parent / "masonry" / "builders" / "fixtures" / "with-include"
-    )
+    poetry = Factory().create_poetry(fixtures_dir / "with-include")
 
     package = poetry.package
 
diff --git a/tests/utils/test_env.py b/tests/utils/test_env.py
index e5926e68862..98d8e96700e 100644
--- a/tests/utils/test_env.py
+++ b/tests/utils/test_env.py
@@ -7,8 +7,8 @@
 
 from clikit.io import NullIO
 
+from poetry.core.semver import Version
 from poetry.factory import Factory
-from poetry.semver import Version
 from poetry.utils._compat import WINDOWS
 from poetry.utils._compat import Path
 from poetry.utils.env import EnvCommandError
diff --git a/tests/utils/test_extras.py b/tests/utils/test_extras.py
index 83a184d97ae..424ccc5ee9e 100644
--- a/tests/utils/test_extras.py
+++ b/tests/utils/test_extras.py
@@ -1,6 +1,6 @@
 import pytest
 
-from poetry.packages import Package
+from poetry.core.packages import Package
 from poetry.utils.extras import get_extra_package_names
 
 
diff --git a/tests/utils/test_helpers.py b/tests/utils/test_helpers.py
index d34061c88d6..c4143701643 100644
--- a/tests/utils/test_helpers.py
+++ b/tests/utils/test_helpers.py
@@ -1,7 +1,7 @@
+from poetry.core.utils.helpers import parse_requires
 from poetry.utils._compat import Path
 from poetry.utils.helpers import get_cert
 from poetry.utils.helpers import get_client_cert
-from poetry.utils.helpers import parse_requires
 
 
 def test_parse_requires():
diff --git a/tests/vcs/__init__.py b/tests/vcs/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/vcs/test_git.py b/tests/vcs/test_git.py
deleted file mode 100644
index 062272151fb..00000000000
--- a/tests/vcs/test_git.py
+++ /dev/null
@@ -1,261 +0,0 @@
-import pytest
-
-from poetry.vcs.git import Git
-from poetry.vcs.git import GitUrl
-from poetry.vcs.git import ParsedUrl
-
-
-@pytest.mark.parametrize(
-    "url, normalized",
-    [
-        (
-            "git+ssh://user@hostname:project.git#commit",
-            GitUrl("user@hostname:project.git", "commit"),
-        ),
-        (
-            "git+http://user@hostname/project/blah.git@commit",
-            GitUrl("http://user@hostname/project/blah.git", "commit"),
-        ),
-        (
-            "git+https://user@hostname/project/blah.git",
-            GitUrl("https://user@hostname/project/blah.git", None),
-        ),
-        (
-            "git+https://user@hostname/project~_-.foo/blah~_-.bar.git",
-            GitUrl("https://user@hostname/project~_-.foo/blah~_-.bar.git", None),
-        ),
-        (
-            "git+https://user@hostname:project/blah.git",
-            GitUrl("https://user@hostname/project/blah.git", None),
-        ),
-        (
-            "git+ssh://git@github.com:sdispater/poetry.git#v1.0.27",
-            GitUrl("git@github.com:sdispater/poetry.git", "v1.0.27"),
-        ),
-        (
-            "git+ssh://git@github.com:/sdispater/poetry.git",
-            GitUrl("git@github.com:/sdispater/poetry.git", None),
-        ),
-        ("git+ssh://git@github.com:org/repo", GitUrl("git@github.com:org/repo", None),),
-        (
-            "git+ssh://git@github.com/org/repo",
-            GitUrl("ssh://git@github.com/org/repo", None),
-        ),
-        ("git+ssh://foo:22/some/path", GitUrl("ssh://foo:22/some/path", None)),
-        ("git@github.com:org/repo", GitUrl("git@github.com:org/repo", None)),
-        (
-            "git+https://github.com/sdispater/pendulum",
-            GitUrl("https://github.com/sdispater/pendulum", None),
-        ),
-        (
-            "git+https://github.com/sdispater/pendulum#7a018f2d075b03a73409e8356f9b29c9ad4ea2c5",
-            GitUrl(
-                "https://github.com/sdispater/pendulum",
-                "7a018f2d075b03a73409e8356f9b29c9ad4ea2c5",
-            ),
-        ),
-        (
-            "git+ssh://git@git.example.com:b/b.git#v1.0.0",
-            GitUrl("git@git.example.com:b/b.git", "v1.0.0"),
-        ),
-        (
-            "git+ssh://git@github.com:sdispater/pendulum.git#foo/bar",
-            GitUrl("git@github.com:sdispater/pendulum.git", "foo/bar"),
-        ),
-        ("git+file:///foo/bar.git", GitUrl("file:///foo/bar.git", None)),
-        (
-            "git+file://C:\\Users\\hello\\testing.git#zkat/windows-files",
-            GitUrl("file://C:\\Users\\hello\\testing.git", "zkat/windows-files"),
-        ),
-        (
-            "git+https://git.example.com/sdispater/project/my_repo.git",
-            GitUrl("https://git.example.com/sdispater/project/my_repo.git", None),
-        ),
-        (
-            "git+ssh://git@git.example.com:sdispater/project/my_repo.git",
-            GitUrl("git@git.example.com:sdispater/project/my_repo.git", None),
-        ),
-    ],
-)
-def test_normalize_url(url, normalized):
-    assert normalized == Git.normalize_url(url)
-
-
-@pytest.mark.parametrize(
-    "url, parsed",
-    [
-        (
-            "git+ssh://user@hostname:project.git#commit",
-            ParsedUrl(
-                "ssh", "hostname", ":project.git", "user", None, "project", "commit"
-            ),
-        ),
-        (
-            "git+http://user@hostname/project/blah.git@commit",
-            ParsedUrl(
-                "http", "hostname", "/project/blah.git", "user", None, "blah", "commit"
-            ),
-        ),
-        (
-            "git+https://user@hostname/project/blah.git",
-            ParsedUrl(
-                "https", "hostname", "/project/blah.git", "user", None, "blah", None
-            ),
-        ),
-        (
-            "git+https://user@hostname/project~_-.foo/blah~_-.bar.git",
-            ParsedUrl(
-                "https",
-                "hostname",
-                "/project~_-.foo/blah~_-.bar.git",
-                "user",
-                None,
-                "blah~_-.bar",
-                None,
-            ),
-        ),
-        (
-            "git+https://user@hostname:project/blah.git",
-            ParsedUrl(
-                "https", "hostname", ":project/blah.git", "user", None, "blah", None
-            ),
-        ),
-        (
-            "git+ssh://git@github.com:sdispater/poetry.git#v1.0.27",
-            ParsedUrl(
-                "ssh",
-                "github.com",
-                ":sdispater/poetry.git",
-                "git",
-                None,
-                "poetry",
-                "v1.0.27",
-            ),
-        ),
-        (
-            "git+ssh://git@github.com:/sdispater/poetry.git",
-            ParsedUrl(
-                "ssh",
-                "github.com",
-                ":/sdispater/poetry.git",
-                "git",
-                None,
-                "poetry",
-                None,
-            ),
-        ),
-        (
-            "git+ssh://git@github.com:org/repo",
-            ParsedUrl("ssh", "github.com", ":org/repo", "git", None, "repo", None),
-        ),
-        (
-            "git+ssh://git@github.com/org/repo",
-            ParsedUrl("ssh", "github.com", "/org/repo", "git", None, "repo", None),
-        ),
-        (
-            "git+ssh://foo:22/some/path",
-            ParsedUrl("ssh", "foo", "/some/path", None, "22", "path", None),
-        ),
-        (
-            "git@github.com:org/repo",
-            ParsedUrl(None, "github.com", ":org/repo", "git", None, "repo", None),
-        ),
-        (
-            "git+https://github.com/sdispater/pendulum",
-            ParsedUrl(
-                "https",
-                "github.com",
-                "/sdispater/pendulum",
-                None,
-                None,
-                "pendulum",
-                None,
-            ),
-        ),
-        (
-            "git+https://github.com/sdispater/pendulum#7a018f2d075b03a73409e8356f9b29c9ad4ea2c5",
-            ParsedUrl(
-                "https",
-                "github.com",
-                "/sdispater/pendulum",
-                None,
-                None,
-                "pendulum",
-                "7a018f2d075b03a73409e8356f9b29c9ad4ea2c5",
-            ),
-        ),
-        (
-            "git+ssh://git@git.example.com:b/b.git#v1.0.0",
-            ParsedUrl("ssh", "git.example.com", ":b/b.git", "git", None, "b", "v1.0.0"),
-        ),
-        (
-            "git+ssh://git@github.com:sdispater/pendulum.git#foo/bar",
-            ParsedUrl(
-                "ssh",
-                "github.com",
-                ":sdispater/pendulum.git",
-                "git",
-                None,
-                "pendulum",
-                "foo/bar",
-            ),
-        ),
-        (
-            "git+file:///foo/bar.git",
-            ParsedUrl("file", None, "/foo/bar.git", None, None, "bar", None),
-        ),
-        (
-            "git+file://C:\\Users\\hello\\testing.git#zkat/windows-files",
-            ParsedUrl(
-                "file",
-                "C",
-                ":\\Users\\hello\\testing.git",
-                None,
-                None,
-                "testing",
-                "zkat/windows-files",
-            ),
-        ),
-        (
-            "git+https://git.example.com/sdispater/project/my_repo.git",
-            ParsedUrl(
-                "https",
-                "git.example.com",
-                "/sdispater/project/my_repo.git",
-                None,
-                None,
-                "my_repo",
-                None,
-            ),
-        ),
-        (
-            "git+ssh://git@git.example.com:sdispater/project/my_repo.git",
-            ParsedUrl(
-                "ssh",
-                "git.example.com",
-                ":sdispater/project/my_repo.git",
-                "git",
-                None,
-                "my_repo",
-                None,
-            ),
-        ),
-    ],
-)
-def test_parse_url(url, parsed):
-    result = ParsedUrl.parse(url)
-    assert parsed.name == result.name
-    assert parsed.pathname == result.pathname
-    assert parsed.port == result.port
-    assert parsed.protocol == result.protocol
-    assert parsed.resource == result.resource
-    assert parsed.rev == result.rev
-    assert parsed.url == result.url
-    assert parsed.user == result.user
-
-
-def test_parse_url_should_fail():
-    url = "https://" + "@" * 64 + "!"
-
-    with pytest.raises(ValueError):
-        ParsedUrl.parse(url)
diff --git a/tests/version/__init__.py b/tests/version/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/tests/version/test_helpers.py b/tests/version/test_helpers.py
deleted file mode 100644
index e57de62abc5..00000000000
--- a/tests/version/test_helpers.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from poetry.semver import parse_constraint
-from poetry.version.helpers import format_python_constraint
-
-
-def test_format_python_constraint():
-    constraint = parse_constraint("~2.7 || ^3.6")
-
-    result = format_python_constraint(constraint)
-
-    assert result == ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
-
-
-def test_format_python_constraint_single_version():
-    constraint = parse_constraint("3.6")
-
-    result = format_python_constraint(constraint)
-
-    assert result == ">=3.6,<3.7"
-
-    constraint = parse_constraint("3")
-
-    result = format_python_constraint(constraint)
-
-    assert result == ">=3.0,<4.0"
diff --git a/tests/version/test_markers.py b/tests/version/test_markers.py
deleted file mode 100644
index 2ef15c6ea27..00000000000
--- a/tests/version/test_markers.py
+++ /dev/null
@@ -1,606 +0,0 @@
-import os
-
-import pytest
-
-from poetry.version.markers import MarkerUnion
-from poetry.version.markers import MultiMarker
-from poetry.version.markers import SingleMarker
-from poetry.version.markers import parse_marker
-
-
-def test_single_marker():
-    m = parse_marker('sys_platform == "darwin"')
-
-    assert isinstance(m, SingleMarker)
-    assert m.name == "sys_platform"
-    assert m.constraint_string == "==darwin"
-
-    m = parse_marker('python_version in "2.7, 3.0, 3.1"')
-
-    assert isinstance(m, SingleMarker)
-    assert m.name == "python_version"
-    assert m.constraint_string == "in 2.7, 3.0, 3.1"
-    assert str(m.constraint) == ">=2.7.0,<2.8.0 || >=3.0.0,<3.2.0"
-
-    m = parse_marker('"2.7" in python_version')
-
-    assert isinstance(m, SingleMarker)
-    assert m.name == "python_version"
-    assert m.constraint_string == "in 2.7"
-    assert str(m.constraint) == ">=2.7.0,<2.8.0"
-
-    m = parse_marker('python_version not in "2.7, 3.0, 3.1"')
-
-    assert isinstance(m, SingleMarker)
-    assert m.name == "python_version"
-    assert m.constraint_string == "not in 2.7, 3.0, 3.1"
-    assert str(m.constraint) == "<2.7.0 || >=2.8.0,<3.0.0 || >=3.2.0"
-
-
-def test_single_marker_intersect():
-    m = parse_marker('sys_platform == "darwin"')
-
-    intersection = m.intersect(parse_marker('implementation_name == "cpython"'))
-    assert (
-        str(intersection)
-        == 'sys_platform == "darwin" and implementation_name == "cpython"'
-    )
-
-    m = parse_marker('python_version >= "3.4"')
-
-    intersection = m.intersect(parse_marker('python_version < "3.6"'))
-    assert str(intersection) == 'python_version >= "3.4" and python_version < "3.6"'
-
-
-def test_single_marker_intersect_compacts_constraints():
-    m = parse_marker('python_version < "3.6"')
-
-    intersection = m.intersect(parse_marker('python_version < "3.4"'))
-    assert str(intersection) == 'python_version < "3.4"'
-
-
-def test_single_marker_intersect_with_multi():
-    m = parse_marker('sys_platform == "darwin"')
-
-    intersection = m.intersect(
-        parse_marker('implementation_name == "cpython" and python_version >= "3.6"')
-    )
-    assert (
-        str(intersection)
-        == 'implementation_name == "cpython" and python_version >= "3.6" and sys_platform == "darwin"'
-    )
-
-
-def test_single_marker_intersect_with_multi_with_duplicate():
-    m = parse_marker('python_version < "4.0"')
-
-    intersection = m.intersect(
-        parse_marker('sys_platform == "darwin" and python_version < "4.0"')
-    )
-    assert str(intersection) == 'sys_platform == "darwin" and python_version < "4.0"'
-
-
-def test_single_marker_intersect_with_multi_compacts_constraint():
-    m = parse_marker('python_version < "3.6"')
-
-    intersection = m.intersect(
-        parse_marker('implementation_name == "cpython" and python_version < "3.4"')
-    )
-    assert (
-        str(intersection)
-        == 'implementation_name == "cpython" and python_version < "3.4"'
-    )
-
-
-def test_single_marker_not_in_python_intersection():
-    m = parse_marker('python_version not in "2.7, 3.0, 3.1"')
-
-    intersection = m.intersect(
-        parse_marker('python_version not in "2.7, 3.0, 3.1, 3.2"')
-    )
-    assert str(intersection) == 'python_version not in "2.7, 3.0, 3.1, 3.2"'
-
-
-def test_single_marker_union():
-    m = parse_marker('sys_platform == "darwin"')
-
-    intersection = m.union(parse_marker('implementation_name == "cpython"'))
-    assert (
-        str(intersection)
-        == 'sys_platform == "darwin" or implementation_name == "cpython"'
-    )
-
-    m = parse_marker('python_version >= "3.4"')
-
-    intersection = m.union(parse_marker('python_version < "3.6"'))
-    assert str(intersection) == 'python_version >= "3.4" or python_version < "3.6"'
-
-
-def test_single_marker_union_compacts_constraints():
-    m = parse_marker('python_version < "3.6"')
-
-    union = m.union(parse_marker('python_version < "3.4"'))
-    assert str(union) == 'python_version < "3.6"'
-
-
-def test_single_marker_union_with_multi():
-    m = parse_marker('sys_platform == "darwin"')
-
-    union = m.union(
-        parse_marker('implementation_name == "cpython" and python_version >= "3.6"')
-    )
-    assert (
-        str(union)
-        == 'implementation_name == "cpython" and python_version >= "3.6" or sys_platform == "darwin"'
-    )
-
-
-def test_single_marker_union_with_multi_duplicate():
-    m = parse_marker('sys_platform == "darwin" and python_version >= "3.6"')
-
-    union = m.union(
-        parse_marker('sys_platform == "darwin" and python_version >= "3.6"')
-    )
-    assert str(union) == 'sys_platform == "darwin" and python_version >= "3.6"'
-
-
-def test_single_marker_union_with_union():
-    m = parse_marker('sys_platform == "darwin"')
-
-    union = m.union(
-        parse_marker('implementation_name == "cpython" or python_version >= "3.6"')
-    )
-    assert (
-        str(union)
-        == 'implementation_name == "cpython" or python_version >= "3.6" or sys_platform == "darwin"'
-    )
-
-
-def test_single_marker_not_in_python_union():
-    m = parse_marker('python_version not in "2.7, 3.0, 3.1"')
-
-    union = m.union(parse_marker('python_version not in "2.7, 3.0, 3.1, 3.2"'))
-    assert str(union) == 'python_version not in "2.7, 3.0, 3.1"'
-
-
-def test_single_marker_union_with_union_duplicate():
-    m = parse_marker('sys_platform == "darwin"')
-
-    union = m.union(parse_marker('sys_platform == "darwin" or python_version >= "3.6"'))
-    assert str(union) == 'sys_platform == "darwin" or python_version >= "3.6"'
-
-    m = parse_marker('python_version >= "3.7"')
-
-    union = m.union(parse_marker('sys_platform == "darwin" or python_version >= "3.6"'))
-    assert str(union) == 'sys_platform == "darwin" or python_version >= "3.6"'
-
-    m = parse_marker('python_version <= "3.6"')
-
-    union = m.union(parse_marker('sys_platform == "darwin" or python_version < "3.4"'))
-    assert str(union) == 'sys_platform == "darwin" or python_version <= "3.6"'
-
-
-def test_multi_marker():
-    m = parse_marker('sys_platform == "darwin" and implementation_name == "cpython"')
-
-    assert isinstance(m, MultiMarker)
-    assert m.markers == [
-        parse_marker('sys_platform == "darwin"'),
-        parse_marker('implementation_name == "cpython"'),
-    ]
-
-
-def test_multi_marker_is_empty_is_contradictory():
-    m = parse_marker(
-        'sys_platform == "linux" and python_version >= "3.5" and python_version < "2.8"'
-    )
-
-    assert m.is_empty()
-
-    m = parse_marker('sys_platform == "linux" and sys_platform == "win32"')
-
-    assert m.is_empty()
-
-
-def test_multi_marker_intersect_multi():
-    m = parse_marker('sys_platform == "darwin" and implementation_name == "cpython"')
-
-    intersection = m.intersect(
-        parse_marker('python_version >= "3.6" and os_name == "Windows"')
-    )
-    assert str(intersection) == (
-        'sys_platform == "darwin" and implementation_name == "cpython" '
-        'and python_version >= "3.6" and os_name == "Windows"'
-    )
-
-
-def test_multi_marker_intersect_multi_with_overlapping_constraints():
-    m = parse_marker('sys_platform == "darwin" and python_version < "3.6"')
-
-    intersection = m.intersect(
-        parse_marker(
-            'python_version <= "3.4" and os_name == "Windows" and sys_platform == "darwin"'
-        )
-    )
-    assert str(intersection) == (
-        'sys_platform == "darwin" and python_version <= "3.4" and os_name == "Windows"'
-    )
-
-
-def test_multi_marker_union_multi():
-    m = parse_marker('sys_platform == "darwin" and implementation_name == "cpython"')
-
-    intersection = m.union(
-        parse_marker('python_version >= "3.6" and os_name == "Windows"')
-    )
-    assert str(intersection) == (
-        'sys_platform == "darwin" and implementation_name == "cpython" '
-        'or python_version >= "3.6" and os_name == "Windows"'
-    )
-
-
-def test_multi_marker_union_with_union():
-    m = parse_marker('sys_platform == "darwin" and implementation_name == "cpython"')
-
-    intersection = m.union(
-        parse_marker('python_version >= "3.6" or os_name == "Windows"')
-    )
-    assert str(intersection) == (
-        'python_version >= "3.6" or os_name == "Windows"'
-        ' or sys_platform == "darwin" and implementation_name == "cpython"'
-    )
-
-
-def test_marker_union():
-    m = parse_marker('sys_platform == "darwin" or implementation_name == "cpython"')
-
-    assert isinstance(m, MarkerUnion)
-    assert m.markers == [
-        parse_marker('sys_platform == "darwin"'),
-        parse_marker('implementation_name == "cpython"'),
-    ]
-
-
-def test_marker_union_deduplicate():
-    m = parse_marker(
-        'sys_platform == "darwin" or implementation_name == "cpython" or sys_platform == "darwin"'
-    )
-
-    assert str(m) == 'sys_platform == "darwin" or implementation_name == "cpython"'
-
-
-def test_marker_union_intersect_single_marker():
-    m = parse_marker('sys_platform == "darwin" or python_version < "3.4"')
-
-    intersection = m.intersect(parse_marker('implementation_name == "cpython"'))
-    assert str(intersection) == (
-        'sys_platform == "darwin" and implementation_name == "cpython" '
-        'or python_version < "3.4" and implementation_name == "cpython"'
-    )
-
-
-def test_marker_union_intersect_single_with_overlapping_constraints():
-    m = parse_marker('sys_platform == "darwin" or python_version < "3.4"')
-
-    intersection = m.intersect(parse_marker('python_version <= "3.6"'))
-    assert (
-        str(intersection)
-        == 'sys_platform == "darwin" and python_version <= "3.6" or python_version < "3.4"'
-    )
-
-    m = parse_marker('sys_platform == "darwin" or python_version < "3.4"')
-    intersection = m.intersect(parse_marker('sys_platform == "darwin"'))
-    assert (
-        str(intersection)
-        == 'sys_platform == "darwin" or python_version < "3.4" and sys_platform == "darwin"'
-    )
-
-
-def test_marker_union_intersect_marker_union():
-    m = parse_marker('sys_platform == "darwin" or python_version < "3.4"')
-
-    intersection = m.intersect(
-        parse_marker('implementation_name == "cpython" or os_name == "Windows"')
-    )
-    assert str(intersection) == (
-        'sys_platform == "darwin" and implementation_name == "cpython" '
-        'or sys_platform == "darwin" and os_name == "Windows" or '
-        'python_version < "3.4" and implementation_name == "cpython" or '
-        'python_version < "3.4" and os_name == "Windows"'
-    )
-
-
-def test_marker_union_intersect_marker_union_drops_unnecessary_markers():
-    m = parse_marker(
-        'python_version >= "2.7" and python_version < "2.8" '
-        'or python_version >= "3.4" and python_version < "4.0"'
-    )
-    m2 = parse_marker(
-        'python_version >= "2.7" and python_version < "2.8" '
-        'or python_version >= "3.4" and python_version < "4.0"'
-    )
-
-    intersection = m.intersect(m2)
-    expected = (
-        'python_version >= "2.7" and python_version < "2.8" '
-        'or python_version >= "3.4" and python_version < "4.0"'
-    )
-    assert expected == str(intersection)
-
-
-def test_marker_union_intersect_multi_marker():
-    m = parse_marker('sys_platform == "darwin" or python_version < "3.4"')
-
-    intersection = m.intersect(
-        parse_marker('implementation_name == "cpython" and os_name == "Windows"')
-    )
-    assert str(intersection) == (
-        'implementation_name == "cpython" and os_name == "Windows" and sys_platform == "darwin" '
-        'or implementation_name == "cpython" and os_name == "Windows" and python_version < "3.4"'
-    )
-
-
-def test_marker_union_union_with_union():
-    m = parse_marker('sys_platform == "darwin" or python_version < "3.4"')
-
-    union = m.union(
-        parse_marker('implementation_name == "cpython" or os_name == "Windows"')
-    )
-    assert str(union) == (
-        'sys_platform == "darwin" or python_version < "3.4" '
-        'or implementation_name == "cpython" or os_name == "Windows"'
-    )
-
-
-def test_marker_union_union_duplicates():
-    m = parse_marker('sys_platform == "darwin" or python_version < "3.4"')
-
-    union = m.union(parse_marker('sys_platform == "darwin" or os_name == "Windows"'))
-    assert str(union) == (
-        'sys_platform == "darwin" or python_version < "3.4" or os_name == "Windows"'
-    )
-
-    m = parse_marker('sys_platform == "darwin" or python_version < "3.4"')
-
-    union = m.union(
-        parse_marker(
-            'sys_platform == "darwin" or os_name == "Windows" or python_version <= "3.6"'
-        )
-    )
-    assert str(union) == (
-        'sys_platform == "darwin" or python_version <= "3.6" or os_name == "Windows"'
-    )
-
-
-def test_marker_union_all_any():
-    union = MarkerUnion(parse_marker(""), parse_marker(""))
-
-    assert union.is_any()
-
-
-def test_marker_union_not_all_any():
-    union = MarkerUnion(parse_marker(""), parse_marker(""), parse_marker(""))
-
-    assert union.is_any()
-
-
-def test_marker_union_all_empty():
-    union = MarkerUnion(parse_marker(""), parse_marker(""))
-
-    assert union.is_empty()
-
-
-def test_marker_union_not_all_empty():
-    union = MarkerUnion(
-        parse_marker(""), parse_marker(""), parse_marker("")
-    )
-
-    assert not union.is_empty()
-
-
-def test_marker_str_conversion_skips_empty_and_any():
-    union = MarkerUnion(
-        parse_marker(""),
-        parse_marker(
-            'sys_platform == "darwin" or python_version <= "3.6" or os_name == "Windows"'
-        ),
-        parse_marker(""),
-    )
-
-    assert str(union) == (
-        'sys_platform == "darwin" or python_version <= "3.6" or os_name == "Windows"'
-    )
-
-
-def test_intersect_compacts_constraints():
-    m = parse_marker('python_version < "4.0"')
-
-    intersection = m.intersect(parse_marker('python_version < "5.0"'))
-    assert str(intersection) == 'python_version < "4.0"'
-
-
-def test_multi_marker_removes_duplicates():
-    m = parse_marker('sys_platform == "win32" and sys_platform == "win32"')
-
-    assert 'sys_platform == "win32"' == str(m)
-
-    m = parse_marker(
-        'sys_platform == "darwin" and implementation_name == "cpython" '
-        'and sys_platform == "darwin" and implementation_name == "cpython"'
-    )
-
-    assert 'sys_platform == "darwin" and implementation_name == "cpython"' == str(m)
-
-
-@pytest.mark.parametrize(
-    ("marker_string", "environment", "expected"),
-    [
-        ("os_name == '{0}'".format(os.name), None, True),
-        ("os_name == 'foo'", {"os_name": "foo"}, True),
-        ("os_name == 'foo'", {"os_name": "bar"}, False),
-        ("'2.7' in python_version", {"python_version": "2.7.5"}, True),
-        ("'2.7' not in python_version", {"python_version": "2.7"}, False),
-        (
-            "os_name == 'foo' and python_version ~= '2.7.0'",
-            {"os_name": "foo", "python_version": "2.7.6"},
-            True,
-        ),
-        (
-            "python_version ~= '2.7.0' and (os_name == 'foo' or " "os_name == 'bar')",
-            {"os_name": "foo", "python_version": "2.7.4"},
-            True,
-        ),
-        (
-            "python_version ~= '2.7.0' and (os_name == 'foo' or " "os_name == 'bar')",
-            {"os_name": "bar", "python_version": "2.7.4"},
-            True,
-        ),
-        (
-            "python_version ~= '2.7.0' and (os_name == 'foo' or " "os_name == 'bar')",
-            {"os_name": "other", "python_version": "2.7.4"},
-            False,
-        ),
-        ("extra == 'security'", {"extra": "quux"}, False),
-        ("extra == 'security'", {"extra": "security"}, True),
-        ("os.name == '{0}'".format(os.name), None, True),
-        ("sys.platform == 'win32'", {"sys_platform": "linux2"}, False),
-        ("platform.version in 'Ubuntu'", {"platform_version": "#39"}, False),
-        ("platform.machine=='x86_64'", {"platform_machine": "x86_64"}, True),
-        (
-            "platform.python_implementation=='Jython'",
-            {"platform_python_implementation": "CPython"},
-            False,
-        ),
-        (
-            "python_version == '2.5' and platform.python_implementation" "!= 'Jython'",
-            {"python_version": "2.7"},
-            False,
-        ),
-    ],
-)
-def test_validate(marker_string, environment, expected):
-    m = parse_marker(marker_string)
-
-    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)
-
-
-@pytest.mark.parametrize(
-    "marker, expected",
-    [
-        ('python_version >= "3.6"', 'python_version >= "3.6"'),
-        ('python_version >= "3.6" and extra == "foo"', 'python_version >= "3.6"'),
-        (
-            'python_version >= "3.6" and (extra == "foo" or extra == "bar")',
-            'python_version >= "3.6"',
-        ),
-        (
-            'python_version >= "3.6" and (extra == "foo" or extra == "bar") or implementation_name == "pypy"',
-            'python_version >= "3.6" or implementation_name == "pypy"',
-        ),
-        (
-            'python_version >= "3.6" and extra == "foo" or implementation_name == "pypy" and extra == "bar"',
-            'python_version >= "3.6" or implementation_name == "pypy"',
-        ),
-        (
-            'python_version >= "3.6" or extra == "foo" and implementation_name == "pypy" or extra == "bar"',
-            'python_version >= "3.6" or implementation_name == "pypy"',
-        ),
-    ],
-)
-def test_without_extras(marker, expected):
-    m = parse_marker(marker)
-
-    assert expected == str(m.without_extras())
-
-
-@pytest.mark.parametrize(
-    "marker, excluded, expected",
-    [
-        ('python_version >= "3.6"', "implementation_name", 'python_version >= "3.6"'),
-        ('python_version >= "3.6"', "python_version", "*"),
-        (
-            'python_version >= "3.6" and extra == "foo"',
-            "extra",
-            'python_version >= "3.6"',
-        ),
-        (
-            'python_version >= "3.6" and (extra == "foo" or extra == "bar")',
-            "python_version",
-            '(extra == "foo" or extra == "bar")',
-        ),
-        (
-            'python_version >= "3.6" and (extra == "foo" or extra == "bar") or implementation_name == "pypy"',
-            "python_version",
-            '(extra == "foo" or extra == "bar") or implementation_name == "pypy"',
-        ),
-        (
-            'python_version >= "3.6" and extra == "foo" or implementation_name == "pypy" and extra == "bar"',
-            "implementation_name",
-            'python_version >= "3.6" and extra == "foo" or extra == "bar"',
-        ),
-        (
-            'python_version >= "3.6" or extra == "foo" and implementation_name == "pypy" or extra == "bar"',
-            "implementation_name",
-            'python_version >= "3.6" or extra == "foo" or extra == "bar"',
-        ),
-    ],
-)
-def test_exclude(marker, excluded, expected):
-    m = parse_marker(marker)
-
-    if expected == "*":
-        assert m.exclude(excluded).is_any()
-    else:
-        assert expected == str(m.exclude(excluded))
-
-
-@pytest.mark.parametrize(
-    "marker, only, expected",
-    [
-        ('python_version >= "3.6"', "python_version", 'python_version >= "3.6"'),
-        (
-            'python_version >= "3.6" and extra == "foo"',
-            "python_version",
-            'python_version >= "3.6"',
-        ),
-        (
-            'python_version >= "3.6" and (extra == "foo" or extra == "bar")',
-            "extra",
-            '(extra == "foo" or extra == "bar")',
-        ),
-        (
-            'python_version >= "3.6" and (extra == "foo" or extra == "bar") or implementation_name == "pypy"',
-            "implementation_name",
-            'implementation_name == "pypy"',
-        ),
-        (
-            'python_version >= "3.6" and extra == "foo" or implementation_name == "pypy" and extra == "bar"',
-            "implementation_name",
-            'implementation_name == "pypy"',
-        ),
-        (
-            'python_version >= "3.6" or extra == "foo" and implementation_name == "pypy" or extra == "bar"',
-            "implementation_name",
-            'implementation_name == "pypy"',
-        ),
-    ],
-)
-def test_only(marker, only, expected):
-    m = parse_marker(marker)
-
-    assert expected == str(m.only(only))
diff --git a/tox.ini b/tox.ini
index e4808b72bda..1f0a4b9ede4 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,10 +1,11 @@
 [tox]
-skipsdist = True
-envlist = py27, py34, py35, py36, py37, py38
+minversion = 3.3.0
+isolated_build = True
+envlist = py27, py35, py36, py37, py38
 
 [testenv]
 whitelist_externals = poetry
 skip_install = true
 commands =
     poetry install -vvv
-    poetry run pytest tests/
+    poetry run pytest {posargs} tests/