Commit 832e8fea by Sébastien Eustace

Merge branch 'master' into develop

parents 695cade9 e30cd20b
...@@ -11,6 +11,26 @@ ...@@ -11,6 +11,26 @@
- Fixed transitive extra dependencies being removed when updating a specific dependency. - Fixed transitive extra dependencies being removed when updating a specific dependency.
## [0.12.10] - 2018-11-22
### Fixed
- Fixed `run` not executing scripts.
- Fixed environment detection.
- Fixed handling of authentication for legacy repositories.
## [0.12.9] - 2018-11-19
### Fixed
- Fixed executables from outside the virtualenv not being accessible.
- Fixed a possible error when building distributions with the `exclude` option.
- Fixed the `run` command for namespaced packages.
- Fixed errors for virtualenvs with spaces in their path.
- Fixed prerelease versions being selected with the `add` command.
## [0.12.8] - 2018-11-13 ## [0.12.8] - 2018-11-13
### Fixed ### Fixed
...@@ -597,7 +617,9 @@ Initial release ...@@ -597,7 +617,9 @@ Initial release
[Unreleased]: https://github.com/sdispater/poetry/compare/0.12.8...master [Unreleased]: https://github.com/sdispater/poetry/compare/0.12.10...master
[0.12.10]: https://github.com/sdispater/poetry/releases/tag/0.12.10
[0.12.9]: https://github.com/sdispater/poetry/releases/tag/0.12.9
[0.12.8]: https://github.com/sdispater/poetry/releases/tag/0.12.8 [0.12.8]: https://github.com/sdispater/poetry/releases/tag/0.12.8
[0.12.7]: https://github.com/sdispater/poetry/releases/tag/0.12.7 [0.12.7]: https://github.com/sdispater/poetry/releases/tag/0.12.7
[0.12.6]: https://github.com/sdispater/poetry/releases/tag/0.12.6 [0.12.6]: https://github.com/sdispater/poetry/releases/tag/0.12.6
......
...@@ -443,7 +443,7 @@ Note that, at the moment, only pure python wheels are supported. ...@@ -443,7 +443,7 @@ Note that, at the moment, only pure python wheels are supported.
#### Options #### Options
* `-F|--format`: Limit the format to either wheel or sdist. * `-f|--format`: Limit the format to either wheel or sdist.
### publish ### publish
......
...@@ -163,7 +163,7 @@ or create a brand new one for you to always work isolated from your global Pytho ...@@ -163,7 +163,7 @@ or create a brand new one for you to always work isolated from your global Pytho
To easily switch between Python versions, it is recommended to To easily switch between Python versions, it is recommended to
use [pyenv](https://github.com/pyenv/pyenv) or similar tools. use [pyenv](https://github.com/pyenv/pyenv) or similar tools.
For instance, if you project is Python 2.7 only, a standard workflow For instance, if your project is Python 2.7 only, a standard workflow
would be: would be:
```bash ```bash
......
...@@ -190,7 +190,7 @@ poetry add my-package --path ../my-package/dist/my_package-0.1.0.whl ...@@ -190,7 +190,7 @@ poetry add my-package --path ../my-package/dist/my_package-0.1.0.whl
## remove ## remove
The `remove` command removes a package from the current The `remove` command removes a package from the current
list of installed packages list of installed packages.
```bash ```bash
poetry remove pendulum poetry remove pendulum
...@@ -296,7 +296,7 @@ The `run` command executes the given command inside the project's virtualenv. ...@@ -296,7 +296,7 @@ The `run` command executes the given command inside the project's virtualenv.
poetry run python -V poetry run python -V
``` ```
It can also executes one of the scripts defined in `pyproject.toml`. It can also execute one of the scripts defined in `pyproject.toml`.
So, if you have a script defined like this: So, if you have a script defined like this:
...@@ -326,7 +326,7 @@ poetry shell ...@@ -326,7 +326,7 @@ poetry shell
## check ## check
The `check` command validate the structure of the `pyproject.toml` file The `check` command validates the structure of the `pyproject.toml` file
and returns a detailed report if there are any errors. and returns a detailed report if there are any errors.
```bash ```bash
......
...@@ -8,7 +8,7 @@ This file can typically be found in one of the following directories: ...@@ -8,7 +8,7 @@ This file can typically be found in one of the following directories:
- Windows: `C:\Users\<username>\AppData\Roaming\pypoetry` - Windows: `C:\Users\<username>\AppData\Roaming\pypoetry`
For Unix, we follow the XDG spec and support `$XDG_CONFIG_HOME`. For Unix, we follow the XDG spec and support `$XDG_CONFIG_HOME`.
That means, by default `~/.config/pypoetry` That means, by default `~/.config/pypoetry`.
## Available settings ## Available settings
......
...@@ -97,7 +97,7 @@ Now, you will need to install the required dependency for Poetry and be sure tha ...@@ -97,7 +97,7 @@ Now, you will need to install the required dependency for Poetry and be sure tha
tests are passing on your machine: tests are passing on your machine:
```bash ```bash
$ poetry develop $ poetry install
$ poetry run pytest tests/ $ poetry run pytest tests/
``` ```
......
...@@ -11,7 +11,7 @@ and, as such, they are not available via the PyPI JSON API. At this point, Poetr ...@@ -11,7 +11,7 @@ and, as such, they are not available via the PyPI JSON API. At this point, Poetr
but downloading the packages and inspect them to get the necessary information. This is an expensive but downloading the packages and inspect them to get the necessary information. This is an expensive
operation, both in bandwidth and time, which is why it seems this is a long process. operation, both in bandwidth and time, which is why it seems this is a long process.
At the moment there is not way around it. At the moment there is no way around it.
!!!note !!!note
...@@ -38,7 +38,7 @@ The `^` operator works very well with libraries following [semantic versioning]( ...@@ -38,7 +38,7 @@ The `^` operator works very well with libraries following [semantic versioning](
Yes. By using the [isolated builds](https://tox.readthedocs.io/en/latest/config.html#conf-isolated_build) `tox` provides, Yes. By using the [isolated builds](https://tox.readthedocs.io/en/latest/config.html#conf-isolated_build) `tox` provides,
you can use it in combination with the PEP 517 compliant build system provided by Poetry. you can use it in combination with the PEP 517 compliant build system provided by Poetry.
So, in your `pyproject.toml` file add this section if does not already exists: So, in your `pyproject.toml` file, add this section if it does not already exist:
```toml ```toml
[build-system] [build-system]
......
...@@ -68,7 +68,7 @@ Once this is done, your library will be available to anyone. ...@@ -68,7 +68,7 @@ Once this is done, your library will be available to anyone.
## Publishing to a private repository ## Publishing to a private repository
Sometimes, you may want to keep your library private but also being accessible to you team. Sometimes, you may want to keep your library private but also being accessible to your team.
In this case, you will need to use a private repository. In this case, you will need to use a private repository.
......
...@@ -119,7 +119,7 @@ packages = [ ...@@ -119,7 +119,7 @@ packages = [
**explicitly** specify the "default" package. **explicitly** specify the "default" package.
For instance, if you have a package named `my_package` and you want to also include For instance, if you have a package named `my_package` and you want to also include
another package named `extra_package`, you will need to specify `my_package` explicitely: another package named `extra_package`, you will need to specify `my_package` explicitly:
```toml ```toml
packages = [ packages = [
...@@ -132,7 +132,7 @@ packages = [ ...@@ -132,7 +132,7 @@ packages = [
Poetry is clever enough to detect Python subpackages. Poetry is clever enough to detect Python subpackages.
So, if you only have to specify the directory where you root package resides. Thus, you only have to specify the directory where your root package resides.
## include and exclude ## include and exclude
......
...@@ -8,7 +8,7 @@ for package installation and publishing. ...@@ -8,7 +8,7 @@ for package installation and publishing.
So, when you add dependencies to your project, Poetry will assume they are available So, when you add dependencies to your project, Poetry will assume they are available
on PyPI. on PyPI.
This represent most cases and will likely be enough for most users. This represents most cases and will likely be enough for most users.
## Using a private repository ## Using a private repository
...@@ -66,5 +66,5 @@ From now on, Poetry will also look for packages in your private repository. ...@@ -66,5 +66,5 @@ From now on, Poetry will also look for packages in your private repository.
If your private repository requires HTTP Basic Auth be sure to add the username and If your private repository requires HTTP Basic Auth be sure to add the username and
password to your `http-basic` config using the example above (be sure to use the password to your `http-basic` config using the example above (be sure to use the
same name than in the `tool.poetry.source` section). Poetry will use these values same name that is in the `tool.poetry.source` section). Poetry will use these values
to authenticate to your private repository when downloading or looking for packages. to authenticate to your private repository when downloading or looking for packages.
...@@ -205,7 +205,7 @@ if __name__ == "__main__": ...@@ -205,7 +205,7 @@ if __name__ == "__main__":
main() main()
""" """
BAT = "@echo off\r\npython {poetry_bin} %*\r\n" BAT = '@echo off\r\npython "{poetry_bin}" %*\r\n'
PRE_MESSAGE = """# Welcome to {poetry}! PRE_MESSAGE = """# Welcome to {poetry}!
......
...@@ -524,7 +524,7 @@ description = "Persistent/Functional/Immutable data structures" ...@@ -524,7 +524,7 @@ description = "Persistent/Functional/Immutable data structures"
name = "pyrsistent" name = "pyrsistent"
optional = false optional = false
python-versions = "*" python-versions = "*"
version = "0.14.5" version = "0.14.6"
[package.dependencies] [package.dependencies]
six = "*" six = "*"
...@@ -675,7 +675,7 @@ description = "Style preserving TOML library" ...@@ -675,7 +675,7 @@ description = "Style preserving TOML library"
name = "tomlkit" name = "tomlkit"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.5.2" version = "0.5.3"
[package.dependencies] [package.dependencies]
[package.dependencies.enum34] [package.dependencies.enum34]
...@@ -803,7 +803,7 @@ pygments-github-lexers = ["0f9e9fb607d351c127a1e55e82a6eb491ed1fc11b2d6a0444ba21 ...@@ -803,7 +803,7 @@ pygments-github-lexers = ["0f9e9fb607d351c127a1e55e82a6eb491ed1fc11b2d6a0444ba21
pylev = ["063910098161199b81e453025653ec53556c1be7165a9b7c50be2f4d57eae1c3", "1d29a87beb45ebe1e821e7a3b10da2b6b2f4c79b43f482c2df1a1f748a6e114e"] pylev = ["063910098161199b81e453025653ec53556c1be7165a9b7c50be2f4d57eae1c3", "1d29a87beb45ebe1e821e7a3b10da2b6b2f4c79b43f482c2df1a1f748a6e114e"]
pymdown-extensions = ["25b0a7967fa697b5035e23340a48594e3e93acb10b06d74574218ace3347d1df", "6cf0cf36b5a03b291ace22dc2f320f4789ce56fbdb6635a3be5fadbf5d7694dd"] pymdown-extensions = ["25b0a7967fa697b5035e23340a48594e3e93acb10b06d74574218ace3347d1df", "6cf0cf36b5a03b291ace22dc2f320f4789ce56fbdb6635a3be5fadbf5d7694dd"]
pyparsing = ["40856e74d4987de5d01761a22d1621ae1c7f8774585acae358aa5c5936c6c90b", "f353aab21fd474459d97b709e527b5571314ee5f067441dc9f88e33eecd96592"] pyparsing = ["40856e74d4987de5d01761a22d1621ae1c7f8774585acae358aa5c5936c6c90b", "f353aab21fd474459d97b709e527b5571314ee5f067441dc9f88e33eecd96592"]
pyrsistent = ["f64dd1b706c31f7aa24495a7da58c0407c072981289b675331e2a16364355102"] pyrsistent = ["5a31f6b093da3401fefdeb53a0980e3145bb9d2bf852b579cc7b39c7f0016c87"]
pytest = ["3f193df1cfe1d1609d4c583838bea3d532b18d6160fd3f55c9447fdca30848ec", "e246cf173c01169b9617fc07264b7b1316e78d7a650055235d6d897bc80d9660"] pytest = ["3f193df1cfe1d1609d4c583838bea3d532b18d6160fd3f55c9447fdca30848ec", "e246cf173c01169b9617fc07264b7b1316e78d7a650055235d6d897bc80d9660"]
pytest-cov = ["513c425e931a0344944f84ea47f3956be0e416d95acbd897a44970c8d926d5d7", "e360f048b7dae3f2f2a9a4d067b2dd6b6a015d384d1577c994a43f3f7cbad762"] pytest-cov = ["513c425e931a0344944f84ea47f3956be0e416d95acbd897a44970c8d926d5d7", "e360f048b7dae3f2f2a9a4d067b2dd6b6a015d384d1577c994a43f3f7cbad762"]
pytest-mock = ["53801e621223d34724926a5c98bd90e8e417ce35264365d39d6c896388dcc928", "d89a8209d722b8307b5e351496830d5cc5e192336003a485443ae9adeb7dd4c0"] pytest-mock = ["53801e621223d34724926a5c98bd90e8e417ce35264365d39d6c896388dcc928", "d89a8209d722b8307b5e351496830d5cc5e192336003a485443ae9adeb7dd4c0"]
...@@ -816,7 +816,7 @@ shellingham = ["c9fd71508d4363e8a3dadf405e681021461dca9ca9a2b48c9461fdfbfceaebff ...@@ -816,7 +816,7 @@ shellingham = ["c9fd71508d4363e8a3dadf405e681021461dca9ca9a2b48c9461fdfbfceaebff
six = ["70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", "832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"] six = ["70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", "832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"]
termcolor = ["1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b"] termcolor = ["1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b"]
toml = ["229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", "235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e", "f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"] toml = ["229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", "235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e", "f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"]
tomlkit = ["82a8fbb8d8c6af72e96ba00b9db3e20ef61be6c79082552c9363f4559702258b", "a43e0195edc9b3c198cd4b5f0f3d427a395d47c4a76ceba7cc875ed030756c39"] tomlkit = ["d6506342615d051bc961f70bfcfa3d29b6616cc08a3ddfd4bc24196f16fd4ec2", "f077456d35303e7908cc233b340f71e0bec96f63429997f38ca9272b7d64029e"]
tornado = ["0662d28b1ca9f67108c7e3b77afabfb9c7e87bde174fbda78186ecedc2499a9d", "4e5158d97583502a7e2739951553cbd88a72076f152b4b11b64b9a10c4c49409", "732e836008c708de2e89a31cb2fa6c0e5a70cb60492bee6f1ea1047500feaf7f", "8154ec22c450df4e06b35f131adc4f2f3a12ec85981a203301d310abf580500f", "8e9d728c4579682e837c92fdd98036bd5cdefa1da2aaf6acf26947e6dd0c01c5", "d4b3e5329f572f055b587efc57d29bd051589fb5a43ec8898c77a47ec2fa2bbb", "e5f2585afccbff22390cddac29849df463b252b711aa2ce7c5f3f342a5b3b444"] tornado = ["0662d28b1ca9f67108c7e3b77afabfb9c7e87bde174fbda78186ecedc2499a9d", "4e5158d97583502a7e2739951553cbd88a72076f152b4b11b64b9a10c4c49409", "732e836008c708de2e89a31cb2fa6c0e5a70cb60492bee6f1ea1047500feaf7f", "8154ec22c450df4e06b35f131adc4f2f3a12ec85981a203301d310abf580500f", "8e9d728c4579682e837c92fdd98036bd5cdefa1da2aaf6acf26947e6dd0c01c5", "d4b3e5329f572f055b587efc57d29bd051589fb5a43ec8898c77a47ec2fa2bbb", "e5f2585afccbff22390cddac29849df463b252b711aa2ce7c5f3f342a5b3b444"]
tox = ["513e32fdf2f9e2d583c2f248f47ba9886428c949f068ac54a0469cac55df5862", "75fa30e8329b41b664585f5fb837e23ce1d7e6fa1f7811f2be571c990f9d911b"] tox = ["513e32fdf2f9e2d583c2f248f47ba9886428c949f068ac54a0469cac55df5862", "75fa30e8329b41b664585f5fb837e23ce1d7e6fa1f7811f2be571c990f9d911b"]
typing = ["4027c5f6127a6267a435201981ba156de91ad0d1d98e9ddc2aa173453453492d", "57dcf675a99b74d64dacf6fba08fb17cf7e3d5fdff53d4a30ea2a5e7e52543d4", "a4c8473ce11a65999c8f59cb093e70686b6c84c98df58c1dae9b3b196089858a"] typing = ["4027c5f6127a6267a435201981ba156de91ad0d1d98e9ddc2aa173453453492d", "57dcf675a99b74d64dacf6fba08fb17cf7e3d5fdff53d4a30ea2a5e7e52543d4", "a4c8473ce11a65999c8f59cb093e70686b6c84c98df58c1dae9b3b196089858a"]
......
__version__ = "0.12.8" __version__ = "0.12.10"
...@@ -15,7 +15,7 @@ class DebugInfoCommand(Command): ...@@ -15,7 +15,7 @@ class DebugInfoCommand(Command):
from ....utils.env import Env from ....utils.env import Env
poetry = self.poetry poetry = self.poetry
env = Env.get(cwd=poetry.file.parent) env = Env.get(poetry.file.parent)
poetry_python_version = ".".join(str(s) for s in sys.version_info[:3]) poetry_python_version = ".".join(str(s) for s in sys.version_info[:3])
......
...@@ -79,7 +79,7 @@ class DebugResolveCommand(Command): ...@@ -79,7 +79,7 @@ class DebugResolveCommand(Command):
return 0 return 0
env = Env.get() env = Env.get(self.poetry.file.parent)
current_python_version = parse_constraint( current_python_version = parse_constraint(
".".join(str(v) for v in env.version_info) ".".join(str(v) for v in env.version_info)
) )
......
...@@ -15,7 +15,7 @@ class EnvCommand(Command): ...@@ -15,7 +15,7 @@ class EnvCommand(Command):
# Checking compatibility of the current environment with # Checking compatibility of the current environment with
# the python dependency specified in pyproject.toml # the python dependency specified in pyproject.toml
current_env = Env.get() current_env = Env.get(self.poetry.file.parent)
supported_python = self.poetry.package.python_constraint supported_python = self.poetry.package.python_constraint
current_python = parse_constraint( current_python = parse_constraint(
".".join(str(v) for v in current_env.version_info[:3]) ".".join(str(v) for v in current_env.version_info[:3])
...@@ -30,7 +30,7 @@ class EnvCommand(Command): ...@@ -30,7 +30,7 @@ class EnvCommand(Command):
) )
self._env = Env.create_venv( self._env = Env.create_venv(
o, self.poetry.package.name, cwd=self.poetry.file.parent self.poetry.file.parent, o, self.poetry.package.name
) )
if self._env.is_venv() and o.is_verbose(): if self._env.is_venv() and o.is_verbose():
......
...@@ -102,7 +102,7 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in ...@@ -102,7 +102,7 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in
question.validator = self._validate_license question.validator = self._validate_license
license = self.ask(question) license = self.ask(question)
current_env = Env.get() current_env = Env.get(Path.cwd())
default_python = "^{}".format( default_python = "^{}".format(
".".join(str(v) for v in current_env.version_info[:2]) ".".join(str(v) for v in current_env.version_info[:2])
) )
......
...@@ -45,7 +45,7 @@ class NewCommand(Command): ...@@ -45,7 +45,7 @@ class NewCommand(Command):
if author_email: if author_email:
author += " <{}>".format(author_email) author += " <{}>".format(author_email)
current_env = Env.get() current_env = Env.get(Path.cwd())
default_python = "^{}".format( default_python = "^{}".format(
".".join(str(v) for v in current_env.version_info[:2]) ".".join(str(v) for v in current_env.version_info[:2])
) )
......
...@@ -47,7 +47,7 @@ class RunCommand(EnvCommand): ...@@ -47,7 +47,7 @@ class RunCommand(EnvCommand):
poetry = self.poetry poetry = self.poetry
package = poetry.package package = poetry.package
path = poetry.file.parent path = poetry.file.parent
module = Module(package.name, path.as_posix()) module = Module(package.name, path.as_posix(), package.packages)
return module return module
def merge_application_definition(self, merge_args=True): def merge_application_definition(self, merge_args=True):
......
...@@ -53,7 +53,7 @@ class Builder(object): ...@@ -53,7 +53,7 @@ class Builder(object):
explicitely_excluded = set() explicitely_excluded = set()
for excluded_glob in self._package.exclude: for excluded_glob in self._package.exclude:
for excluded in self._path.glob(excluded_glob): for excluded in self._path.glob(str(excluded_glob)):
explicitely_excluded.add(excluded.relative_to(self._path).as_posix()) explicitely_excluded.add(excluded.relative_to(self._path).as_posix())
ignored = vcs_ignored_files | explicitely_excluded ignored = vcs_ignored_files | explicitely_excluded
......
...@@ -14,17 +14,11 @@ from requests_toolbelt.multipart import MultipartEncoder, MultipartEncoderMonito ...@@ -14,17 +14,11 @@ from requests_toolbelt.multipart import MultipartEncoder, MultipartEncoderMonito
from poetry.__version__ import __version__ from poetry.__version__ import __version__
from poetry.utils.helpers import normalize_version from poetry.utils.helpers import normalize_version
from poetry.utils.patterns import wheel_file_re
from ..metadata import Metadata from ..metadata import Metadata
wheel_file_re = re.compile(
r"""^(?P<namever>(?P<name>.+?)(-(?P<ver>\d.+?))?)
((-(?P<build>\d.*?))?-(?P<pyver>.+?)-(?P<abi>.+?)-(?P<plat>.+?)
\.whl|\.dist-info)$""",
re.VERBOSE,
)
_has_blake2 = hasattr(hashlib, "blake2b") _has_blake2 = hasattr(hashlib, "blake2b")
......
...@@ -8,16 +8,18 @@ from typing import List ...@@ -8,16 +8,18 @@ from typing import List
from .__version__ import __version__ from .__version__ import __version__
from .config import Config from .config import Config
from .exceptions import InvalidProjectFile
from .json import validate_object from .json import validate_object
from .packages import Dependency from .packages import Dependency
from .packages import Locker from .packages import Locker
from .packages import Package from .packages import Package
from .packages import ProjectPackage from .packages import ProjectPackage
from .repositories import Pool from .repositories import Pool
from .repositories.auth import Auth
from .repositories.legacy_repository import LegacyRepository
from .repositories.pypi_repository import PyPiRepository from .repositories.pypi_repository import PyPiRepository
from .spdx import license_by_id from .spdx import license_by_id
from .utils._compat import Path from .utils._compat import Path
from .utils.helpers import get_http_basic_auth
from .utils.toml_file import TomlFile from .utils.toml_file import TomlFile
...@@ -42,9 +44,9 @@ class Poetry: ...@@ -42,9 +44,9 @@ class Poetry:
# Configure sources # Configure sources
self._pool = Pool() self._pool = Pool()
for source in self._local_config.get("source", []): for source in self._local_config.get("source", []):
self._pool.configure(source) self._pool.add_repository(self.create_legacy_repository(source))
# Always put PyPI last to prefere private repositories # Always put PyPI last to prefer private repositories
self._pool.add_repository(PyPiRepository()) self._pool.add_repository(PyPiRepository())
@property @property
...@@ -194,6 +196,26 @@ class Poetry: ...@@ -194,6 +196,26 @@ class Poetry:
return cls(poetry_file, local_config, package, locker) return cls(poetry_file, local_config, package, locker)
def create_legacy_repository(
self, source
): # type: (Dict[str, str]) -> LegacyRepository
if "url" in source:
# PyPI-like repository
if "name" not in source:
raise RuntimeError("Missing [name] in source.")
else:
raise RuntimeError("Unsupported source specified")
name = source["name"]
url = source["url"]
credentials = get_http_basic_auth(self._auth_config, name)
if not credentials:
return LegacyRepository(name, url)
auth = Auth(url, credentials[0], credentials[1])
return LegacyRepository(name, url, auth=auth)
@classmethod @classmethod
def check(cls, config, strict=False): # type: (dict, bool) -> Dict[str, List[str]] def check(cls, config, strict=False): # type: (dict, bool) -> Dict[str, List[str]]
""" """
......
...@@ -275,7 +275,7 @@ class Provider: ...@@ -275,7 +275,7 @@ class Provider:
try: try:
cwd = dependency.full_path cwd = dependency.full_path
venv = Env.get(NullIO(), cwd=cwd) venv = Env.get(cwd)
venv.run("python", "setup.py", "egg_info") venv.run("python", "setup.py", "egg_info")
except EnvCommandError: except EnvCommandError:
result = SetupReader.read_from_directory(dependency.full_path) result = SetupReader.read_from_directory(dependency.full_path)
......
from requests import Request
from requests.auth import AuthBase
from requests.auth import HTTPBasicAuth
from poetry.utils._compat import urlparse
class Auth(AuthBase):
def __init__(self, url, username, password): # type: (str, str, str) -> None
self._netloc = urlparse.urlparse(url).netloc
self._auth = HTTPBasicAuth(username, password)
def __call__(self, r): # type: (Request) -> Request
if urlparse.urlparse(r.url).netloc != self._netloc:
return r
self._auth(r)
return r
...@@ -17,6 +17,7 @@ except ImportError: ...@@ -17,6 +17,7 @@ except ImportError:
unescape = HTMLParser().unescape unescape = HTMLParser().unescape
from typing import Generator from typing import Generator
from typing import Optional
from typing import Union from typing import Union
import html5lib import html5lib
...@@ -28,19 +29,20 @@ from cachy import CacheManager ...@@ -28,19 +29,20 @@ from cachy import CacheManager
import poetry.packages import poetry.packages
from poetry.config import Config
from poetry.locations import CACHE_DIR from poetry.locations import CACHE_DIR
from poetry.masonry.publishing.uploader import wheel_file_re
from poetry.packages import Package from poetry.packages import Package
from poetry.packages import dependency_from_pep_508 from poetry.packages import dependency_from_pep_508
from poetry.packages.utils.link import Link from poetry.packages.utils.link import Link
from poetry.semver import parse_constraint from poetry.semver import parse_constraint
from poetry.semver import Version from poetry.semver import Version
from poetry.semver import VersionConstraint from poetry.semver import VersionConstraint
from poetry.semver import VersionRange
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils.helpers import canonicalize_name, get_http_basic_auth from poetry.utils.helpers import canonicalize_name
from poetry.utils.patterns import wheel_file_re
from poetry.version.markers import InvalidMarker from poetry.version.markers import InvalidMarker
from .auth import Auth
from .exceptions import PackageNotFound from .exceptions import PackageNotFound
from .pypi_repository import PyPiRepository from .pypi_repository import PyPiRepository
...@@ -145,7 +147,9 @@ class Page: ...@@ -145,7 +147,9 @@ class Page:
class LegacyRepository(PyPiRepository): class LegacyRepository(PyPiRepository):
def __init__(self, name, url, disable_cache=False): def __init__(
self, name, url, auth=None, disable_cache=False
): # type: (str, str, Optional[Auth], bool) -> None
if name == "pypi": if name == "pypi":
raise ValueError("The name [pypi] is reserved for repositories") raise ValueError("The name [pypi] is reserved for repositories")
...@@ -171,10 +175,8 @@ class LegacyRepository(PyPiRepository): ...@@ -171,10 +175,8 @@ class LegacyRepository(PyPiRepository):
) )
url_parts = urlparse.urlparse(self._url) url_parts = urlparse.urlparse(self._url)
if not url_parts.username: if not url_parts.username and auth:
self._session.auth = get_http_basic_auth( self._session.auth = auth
Config.create("auth.toml"), self.name
)
self._disable_cache = disable_cache self._disable_cache = disable_cache
...@@ -187,11 +189,23 @@ class LegacyRepository(PyPiRepository): ...@@ -187,11 +189,23 @@ class LegacyRepository(PyPiRepository):
): ):
packages = [] packages = []
if constraint is not None and not isinstance(constraint, VersionConstraint): if constraint is None:
constraint = "*"
if not isinstance(constraint, VersionConstraint):
constraint = parse_constraint(constraint) constraint = parse_constraint(constraint)
if isinstance(constraint, VersionRange):
if (
constraint.max is not None
and constraint.max.is_prerelease()
or constraint.min is not None
and constraint.min.is_prerelease()
):
allow_prereleases = True
key = name key = name
if constraint: if not constraint.is_any():
key = "{}:{}".format(key, str(constraint)) key = "{}:{}".format(key, str(constraint))
if self._cache.store("matches").has(key): if self._cache.store("matches").has(key):
...@@ -203,7 +217,10 @@ class LegacyRepository(PyPiRepository): ...@@ -203,7 +217,10 @@ class LegacyRepository(PyPiRepository):
versions = [] versions = []
for version in page.versions: for version in page.versions:
if not constraint or (constraint and constraint.allows(version)): if version.is_prerelease() and not allow_prereleases:
continue
if constraint.allows(version):
versions.append(version) versions.append(version)
self._cache.store("matches").put(key, versions, 5) self._cache.store("matches").put(key, versions, 5)
...@@ -252,6 +269,9 @@ class LegacyRepository(PyPiRepository): ...@@ -252,6 +269,9 @@ class LegacyRepository(PyPiRepository):
release_info = self.get_release_info(name, version) release_info = self.get_release_info(name, version)
package = poetry.packages.Package(name, version, version) package = poetry.packages.Package(name, version, version)
if release_info["requires_python"]:
package.python_versions = release_info["requires_python"]
package.source_type = "legacy" package.source_type = "legacy"
package.source_url = self._url package.source_url = self._url
package.source_reference = self.name package.source_reference = self.name
...@@ -313,7 +333,7 @@ class LegacyRepository(PyPiRepository): ...@@ -313,7 +333,7 @@ class LegacyRepository(PyPiRepository):
"version": version, "version": version,
"summary": "", "summary": "",
"requires_dist": [], "requires_dist": [],
"requires_python": [], "requires_python": None,
"digests": [], "digests": [],
} }
...@@ -329,7 +349,11 @@ class LegacyRepository(PyPiRepository): ...@@ -329,7 +349,11 @@ class LegacyRepository(PyPiRepository):
default_link = links[0] default_link = links[0]
for link in links: for link in links:
if link.is_wheel: if link.is_wheel:
urls["bdist_wheel"] = link.url m = wheel_file_re.match(default_link.filename)
python = m.group("pyver")
platform = m.group("plat")
if python == "py2.py3" and platform == "any":
urls["bdist_wheel"] = default_link.url
elif link.filename.endswith(".tar.gz"): elif link.filename.endswith(".tar.gz"):
urls["sdist"] = link.url urls["sdist"] = link.url
elif ( elif (
...@@ -346,10 +370,6 @@ class LegacyRepository(PyPiRepository): ...@@ -346,10 +370,6 @@ class LegacyRepository(PyPiRepository):
if not urls: if not urls:
if default_link.is_wheel: if default_link.is_wheel:
m = wheel_file_re.match(default_link.filename)
python = m.group("pyver")
platform = m.group("plat")
if python == "py2.py3" and platform == "any":
urls["bdist_wheel"] = default_link.url urls["bdist_wheel"] = default_link.url
elif default_link.filename.endswith(".tar.gz"): elif default_link.filename.endswith(".tar.gz"):
urls["sdist"] = default_link.url urls["sdist"] = default_link.url
......
...@@ -40,24 +40,6 @@ class Pool(BaseRepository): ...@@ -40,24 +40,6 @@ class Pool(BaseRepository):
return self return self
def configure(self, source): # type: (dict) -> Pool
"""
Configures a repository based on a source
specification and add it to the pool.
"""
from .legacy_repository import LegacyRepository
if "url" in source:
# PyPI-like repository
if "name" not in source:
raise RuntimeError("Missing [name] in source.")
repository = LegacyRepository(source["name"], source["url"])
else:
raise RuntimeError("Unsupported source specified")
return self.add_repository(repository)
def has_package(self, package): def has_package(self, package):
raise NotImplementedError() raise NotImplementedError()
......
...@@ -28,17 +28,16 @@ from cachy import CacheManager ...@@ -28,17 +28,16 @@ from cachy import CacheManager
from requests import get from requests import get
from requests import session from requests import session
from poetry.io import NullIO
from poetry.locations import CACHE_DIR from poetry.locations import CACHE_DIR
from poetry.packages import dependency_from_pep_508 from poetry.packages import dependency_from_pep_508
from poetry.packages import Package from poetry.packages import Package
from poetry.semver import parse_constraint from poetry.semver import parse_constraint
from poetry.semver import VersionConstraint from poetry.semver import VersionConstraint
from poetry.semver import VersionRange
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils._compat import to_str from poetry.utils._compat import to_str
from poetry.utils.helpers import parse_requires from poetry.utils.helpers import parse_requires
from poetry.utils.helpers import temporary_directory from poetry.utils.helpers import temporary_directory
from poetry.utils.env import Env
from poetry.utils.setup_reader import SetupReader from poetry.utils.setup_reader import SetupReader
from poetry.version.markers import InvalidMarker from poetry.version.markers import InvalidMarker
...@@ -93,6 +92,15 @@ class PyPiRepository(Repository): ...@@ -93,6 +92,15 @@ class PyPiRepository(Repository):
if not isinstance(constraint, VersionConstraint): if not isinstance(constraint, VersionConstraint):
constraint = parse_constraint(constraint) constraint = parse_constraint(constraint)
if isinstance(constraint, VersionRange):
if (
constraint.max is not None
and constraint.max.is_prerelease()
or constraint.min is not None
and constraint.min.is_prerelease()
):
allow_prereleases = True
info = self.get_package_info(name) info = self.get_package_info(name)
packages = [] packages = []
...@@ -110,11 +118,7 @@ class PyPiRepository(Repository): ...@@ -110,11 +118,7 @@ class PyPiRepository(Repository):
package = Package(name, version) package = Package(name, version)
if ( if package.is_prerelease() and not allow_prereleases:
package.is_prerelease()
and not allow_prereleases
and not constraint.allows(package.version)
):
continue continue
if not constraint or (constraint and constraint.allows(package.version)): if not constraint or (constraint and constraint.allows(package.version)):
...@@ -387,13 +391,18 @@ class PyPiRepository(Repository): ...@@ -387,13 +391,18 @@ class PyPiRepository(Repository):
): # type: (Dict[str, str]) -> Dict[str, Union[str, List, None]] ): # type: (Dict[str, str]) -> Dict[str, Union[str, List, None]]
if "bdist_wheel" in urls: if "bdist_wheel" in urls:
self._log( self._log(
"Downloading wheel: {}".format(urls["bdist_wheel"].split("/")[-1]), "Downloading wheel: {}".format(
urlparse.urlparse(urls["bdist_wheel"]).path.rsplit("/")[-1]
),
level="debug", level="debug",
) )
return self._get_info_from_wheel(urls["bdist_wheel"]) return self._get_info_from_wheel(urls["bdist_wheel"])
self._log( self._log(
"Downloading sdist: {}".format(urls["sdist"].split("/")[-1]), level="debug" "Downloading sdist: {}".format(
urlparse.urlparse(urls["sdist"]).path.rsplit("/")[-1]
),
level="debug",
) )
return self._get_info_from_sdist(urls["sdist"]) return self._get_info_from_sdist(urls["sdist"])
...@@ -402,7 +411,7 @@ class PyPiRepository(Repository): ...@@ -402,7 +411,7 @@ class PyPiRepository(Repository):
): # type: (str) -> Dict[str, Union[str, List, None]] ): # type: (str) -> Dict[str, Union[str, List, None]]
info = {"summary": "", "requires_python": None, "requires_dist": None} info = {"summary": "", "requires_python": None, "requires_dist": None}
filename = os.path.basename(urlparse.urlparse(url).path) filename = os.path.basename(urlparse.urlparse(url).path.rsplit("/")[-1])
with temporary_directory() as temp_dir: with temporary_directory() as temp_dir:
filepath = os.path.join(temp_dir, filename) filepath = os.path.join(temp_dir, filename)
...@@ -509,7 +518,13 @@ class PyPiRepository(Repository): ...@@ -509,7 +518,13 @@ class PyPiRepository(Repository):
# Still nothing, try reading (without executing it) # Still nothing, try reading (without executing it)
# the setup.py file. # the setup.py file.
try: try:
info.update(self._inspect_sdist_with_setup(sdist_dir)) 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 return info
except Exception as e: except Exception as e:
...@@ -547,6 +562,8 @@ class PyPiRepository(Repository): ...@@ -547,6 +562,8 @@ class PyPiRepository(Repository):
def _download(self, url, dest): # type: (str, str) -> None def _download(self, url, dest): # type: (str, str) -> None
r = get(url, stream=True) r = get(url, stream=True)
r.raise_for_status()
with open(dest, "wb") as f: with open(dest, "wb") as f:
for chunk in r.iter_content(chunk_size=1024): for chunk in r.iter_content(chunk_size=1024):
if chunk: if chunk:
......
from poetry.semver import parse_constraint from poetry.semver import parse_constraint
from poetry.semver import VersionConstraint from poetry.semver import VersionConstraint
from poetry.semver import VersionRange
from .base_repository import BaseRepository from .base_repository import BaseRepository
...@@ -46,16 +47,21 @@ class Repository(BaseRepository): ...@@ -46,16 +47,21 @@ class Repository(BaseRepository):
if not isinstance(constraint, VersionConstraint): if not isinstance(constraint, VersionConstraint):
constraint = parse_constraint(constraint) constraint = parse_constraint(constraint)
for package in self.packages: if isinstance(constraint, VersionRange):
if name == package.name:
if ( if (
package.is_prerelease() constraint.max is not None
and not allow_prereleases and constraint.max.is_prerelease()
and not constraint.allows(package.version) or constraint.min is not None
and constraint.min.is_prerelease()
): ):
allow_prereleases = True
for package in self.packages:
if name == package.name:
if package.is_prerelease() and not allow_prereleases:
continue continue
if constraint is None or constraint.allows(package.version): if constraint.allows(package.version):
for dep in package.requires: for dep in package.requires:
for extra in extras: for extra in extras:
if extra not in package.extras: if extra not in package.extras:
......
import subprocess
import sys import sys
try: try:
...@@ -5,6 +6,11 @@ try: ...@@ -5,6 +6,11 @@ try:
except ImportError: except ImportError:
from functools import lru_cache from functools import lru_cache
try:
import urllib.parse as urlparse
except ImportError:
import urlparse
try: # Python 2 try: # Python 2
long = long long = long
unicode = unicode unicode = unicode
...@@ -19,6 +25,17 @@ PY2 = sys.version_info[0] == 2 ...@@ -19,6 +25,17 @@ PY2 = sys.version_info[0] == 2
PY35 = sys.version_info >= (3, 5) PY35 = sys.version_info >= (3, 5)
PY36 = sys.version_info >= (3, 6) PY36 = sys.version_info >= (3, 6)
WINDOWS = sys.platform == "win32"
if PY2:
import pipes
shell_quote = pipes.quote
else:
import shlex
shell_quote = shlex.quote
if PY35: if PY35:
from pathlib import Path from pathlib import Path
...@@ -80,3 +97,13 @@ def to_str(string): ...@@ -80,3 +97,13 @@ def to_str(string):
pass pass
return getattr(string, method)(encodings[0], errors="ignore") return getattr(string, method)(encodings[0], errors="ignore")
def list_to_shell_command(cmd):
executable = cmd[0]
if " " in executable:
executable = '"{}"'.format(executable)
cmd[0] = executable
return " ".join(cmd)
...@@ -17,9 +17,72 @@ from poetry.config import Config ...@@ -17,9 +17,72 @@ from poetry.config import Config
from poetry.locations import CACHE_DIR from poetry.locations import CACHE_DIR
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils._compat import decode from poetry.utils._compat import decode
from poetry.utils._compat import encode
from poetry.utils._compat import list_to_shell_command
from poetry.version.markers import BaseMarker from poetry.version.markers import BaseMarker
GET_ENVIRONMENT_INFO = """\
import json
import os
import platform
import sys
if hasattr(sys, "implementation"):
info = sys.implementation.version
iver = "{0.major}.{0.minor}.{0.micro}".format(info)
kind = info.releaselevel
if kind != "final":
iver += kind[0] + str(info.serial)
implementation_name = sys.implementation.name
else:
iver = "0"
implementation_name = ""
env = {
"implementation_name": implementation_name,
"implementation_version": iver,
"os_name": os.name,
"platform_machine": platform.machine(),
"platform_release": platform.release(),
"platform_system": platform.system(),
"platform_version": platform.version(),
"python_full_version": platform.python_version(),
"platform_python_implementation": platform.python_implementation(),
"python_version": platform.python_version()[:3],
"sys_platform": sys.platform,
"version_info": tuple(sys.version_info),
}
print(json.dumps(env))
"""
GET_BASE_PREFIX = """\
import sys
if hasattr(sys, "real_prefix"):
print(sys.real_prefix)
elif hasattr(sys, "base_prefix"):
print(sys.base_prefix)
else:
print(sys.prefix)
"""
GET_CONFIG_VAR = """\
import sysconfig
print(sysconfig.get_config_var("{config_var}")),
"""
GET_PYTHON_VERSION = """\
import sys
print('.'.join([str(s) for s in sys.version_info[:3]]))
"""
class EnvError(Exception): class EnvError(Exception):
pass pass
...@@ -90,7 +153,7 @@ class Env(object): ...@@ -90,7 +153,7 @@ class Env(object):
return self._bin("pip") return self._bin("pip")
@classmethod @classmethod
def get(cls, reload=False, cwd=None): # type: (bool, Path) -> Env def get(cls, cwd, reload=False): # type: (Path, bool) -> Env
if cls._env is not None and not reload: if cls._env is not None and not reload:
return cls._env return cls._env
...@@ -99,7 +162,7 @@ class Env(object): ...@@ -99,7 +162,7 @@ class Env(object):
if not in_venv: if not in_venv:
# Checking if a local virtualenv exists # Checking if a local virtualenv exists
if cwd and (cwd / ".venv").exists(): if (cwd / ".venv").exists():
venv = cwd / ".venv" venv = cwd / ".venv"
return VirtualEnv(venv) return VirtualEnv(venv)
...@@ -116,9 +179,6 @@ class Env(object): ...@@ -116,9 +179,6 @@ class Env(object):
else: else:
venv_path = Path(venv_path) venv_path = Path(venv_path)
if cwd is None:
cwd = Path.cwd()
name = cwd.name name = cwd.name
name = "{}-py{}".format( name = "{}-py{}".format(
name, ".".join([str(v) for v in sys.version_info[:2]]) name, ".".join([str(v) for v in sys.version_info[:2]])
...@@ -141,11 +201,11 @@ class Env(object): ...@@ -141,11 +201,11 @@ class Env(object):
return VirtualEnv(prefix, base_prefix) return VirtualEnv(prefix, base_prefix)
@classmethod @classmethod
def create_venv(cls, io, name=None, cwd=None): # type: (IO, bool, Path) -> Env def create_venv(cls, cwd, io, name=None): # type: (Path, IO, bool) -> Env
if cls._env is not None: if cls._env is not None:
return cls._env return cls._env
env = cls.get(cwd=cwd) env = cls.get(cwd)
if env.is_venv(): if env.is_venv():
# Already inside a virtualenv. # Already inside a virtualenv.
return env return env
...@@ -157,9 +217,6 @@ class Env(object): ...@@ -157,9 +217,6 @@ class Env(object):
venv_path = config.setting("settings.virtualenvs.path") venv_path = config.setting("settings.virtualenvs.path")
if root_venv: if root_venv:
if not cwd:
raise RuntimeError("Unable to determine the project's directory")
venv_path = cwd / ".venv" venv_path = cwd / ".venv"
elif venv_path is None: elif venv_path is None:
venv_path = Path(CACHE_DIR) / "virtualenvs" venv_path = Path(CACHE_DIR) / "virtualenvs"
...@@ -167,9 +224,6 @@ class Env(object): ...@@ -167,9 +224,6 @@ class Env(object):
venv_path = Path(venv_path) venv_path = Path(venv_path)
if not name: if not name:
if not cwd:
cwd = Path.cwd()
name = cwd.name name = cwd.name
name = "{}-py{}".format(name, ".".join([str(v) for v in sys.version_info[:2]])) name = "{}-py{}".format(name, ".".join([str(v) for v in sys.version_info[:2]]))
...@@ -272,18 +326,30 @@ class Env(object): ...@@ -272,18 +326,30 @@ class Env(object):
cmd = [bin] + list(args) cmd = [bin] + list(args)
shell = kwargs.get("shell", False) shell = kwargs.get("shell", False)
call = kwargs.pop("call", False) call = kwargs.pop("call", False)
input_ = kwargs.pop("input_", None)
if shell: if shell:
cmd = " ".join(cmd) cmd = list_to_shell_command(cmd)
try: try:
if self._is_windows: if self._is_windows:
kwargs["shell"] = True kwargs["shell"] = True
if call: if input_:
p = subprocess.Popen(
cmd,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
**kwargs
)
output = p.communicate(encode(input_))[0]
elif call:
return subprocess.call(cmd, stderr=subprocess.STDOUT, **kwargs) return subprocess.call(cmd, stderr=subprocess.STDOUT, **kwargs)
else:
output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, **kwargs) output = subprocess.check_output(
cmd, stderr=subprocess.STDOUT, **kwargs
)
except CalledProcessError as e: except CalledProcessError as e:
raise EnvCommandError(e) raise EnvCommandError(e)
...@@ -302,6 +368,8 @@ class Env(object): ...@@ -302,6 +368,8 @@ class Env(object):
Return path to the given executable. Return path to the given executable.
""" """
bin_path = (self._bin_dir / bin).with_suffix(".exe" if self._is_windows else "") bin_path = (self._bin_dir / bin).with_suffix(".exe" if self._is_windows else "")
if not bin_path.exists():
return bin
return str(bin_path) return str(bin_path)
...@@ -373,29 +441,10 @@ class VirtualEnv(Env): ...@@ -373,29 +441,10 @@ class VirtualEnv(Env):
# In this case we need to get sys.base_prefix # In this case we need to get sys.base_prefix
# from inside the virtualenv. # from inside the virtualenv.
if base is None: if base is None:
self._base = Path( self._base = Path(self.run("python", "-", input_=GET_BASE_PREFIX).strip())
self.run(
"python",
"-c",
'"import sys; '
"print("
" getattr("
" sys,"
" 'real_prefix', "
" getattr(sys, 'base_prefix', sys.prefix)"
" )"
')"',
shell=True,
).strip()
)
def get_version_info(self): # type: () -> Tuple[int] def get_version_info(self): # type: () -> Tuple[int]
output = self.run( output = self.run("python", "-", input_=GET_PYTHON_VERSION)
"python",
"-c",
"\"import sys; print('.'.join([str(s) for s in sys.version_info[:3]]))\"",
shell=True,
)
return tuple([int(s) for s in output.strip().split(".")]) return tuple([int(s) for s in output.strip().split(".")])
...@@ -403,41 +452,14 @@ class VirtualEnv(Env): ...@@ -403,41 +452,14 @@ class VirtualEnv(Env):
return self.marker_env["platform_python_implementation"] return self.marker_env["platform_python_implementation"]
def get_marker_env(self): # type: () -> Dict[str, Any] def get_marker_env(self): # type: () -> Dict[str, Any]
output = self.run( output = self.run("python", "-", input_=GET_ENVIRONMENT_INFO)
"python",
"-c",
'"import json; import os; import platform; import sys; '
"implementation = getattr(sys, 'implementation', None); "
"iver = '{0.major}.{0.minor}.{0.micro}'.format(implementation.version) if implementation else '0'; "
"implementation_name = implementation.name if implementation else ''; "
"env = {"
"'implementation_name': implementation_name,"
"'implementation_version': iver,"
"'os_name': os.name,"
"'platform_machine': platform.machine(),"
"'platform_release': platform.release(),"
"'platform_system': platform.system(),"
"'platform_version': platform.version(),"
"'python_full_version': platform.python_version(),"
"'platform_python_implementation': platform.python_implementation(),"
"'python_version': platform.python_version()[:3],"
"'sys_platform': sys.platform,"
"'version_info': sys.version_info[:3],"
"};"
'print(json.dumps(env))"',
shell=True,
)
return json.loads(output) return json.loads(output)
def config_var(self, var): # type: (str) -> Any def config_var(self, var): # type: (str) -> Any
try: try:
value = self.run( value = self.run(
"python", "python", "-", input_=GET_CONFIG_VAR.format(config_var=var)
"-c",
'"import sysconfig; '
"print(sysconfig.get_config_var('{}'))\"".format(var),
shell=True,
).strip() ).strip()
except EnvCommandError as e: except EnvCommandError as e:
warnings.warn("{0}".format(e), RuntimeWarning) warnings.warn("{0}".format(e), RuntimeWarning)
...@@ -517,11 +539,22 @@ class NullEnv(SystemEnv): ...@@ -517,11 +539,22 @@ class NullEnv(SystemEnv):
class MockEnv(NullEnv): class MockEnv(NullEnv):
def __init__(self, version_info=(3, 7, 0), python_implementation="cpython"): def __init__(
super(MockEnv, self).__init__() self,
version_info=(3, 7, 0),
python_implementation="CPython",
platform="darwin",
os_name="posix",
is_venv=False,
**kwargs
):
super(MockEnv, self).__init__(**kwargs)
self._version_info = version_info self._version_info = version_info
self._python_implementation = python_implementation self._python_implementation = python_implementation
self._platform = platform
self._os_name = os_name
self._is_venv = is_venv
@property @property
def version_info(self): # type: () -> Tuple[int] def version_info(self): # type: () -> Tuple[int]
...@@ -530,3 +563,14 @@ class MockEnv(NullEnv): ...@@ -530,3 +563,14 @@ class MockEnv(NullEnv):
@property @property
def python_implementation(self): # type: () -> str def python_implementation(self): # type: () -> str
return self._python_implementation return self._python_implementation
@property
def platform(self): # type: () -> str
return self._platform
@property
def os(self): # type: () -> str
return self._os_name
def is_venv(self): # type: () -> bool
return self._is_venv
import re
wheel_file_re = re.compile(
r"""^(?P<namever>(?P<name>.+?)(-(?P<ver>\d.+?))?)
((-(?P<build>\d.*?))?-(?P<pyver>.+?)-(?P<abi>.+?)-(?P<plat>.+?)
\.whl|\.dist-info)$""",
re.VERBOSE,
)
[tool.poetry] [tool.poetry]
name = "poetry" name = "poetry"
version = "0.12.8" version = "0.12.10"
description = "Python dependency management and packaging made easy." description = "Python dependency management and packaging made easy."
authors = [ authors = [
"Sébastien Eustace <sebastien@eustace.io>" "Sébastien Eustace <sebastien@eustace.io>"
......
import os
import pytest import pytest
import shutil import shutil
import tempfile import tempfile
...@@ -13,6 +14,15 @@ from poetry.utils.toml_file import TomlFile ...@@ -13,6 +14,15 @@ from poetry.utils.toml_file import TomlFile
@pytest.fixture @pytest.fixture
def tmp_dir():
dir_ = tempfile.mkdtemp(prefix="poetry_")
yield dir_
shutil.rmtree(dir_)
@pytest.fixture
def config(): # type: () -> Config def config(): # type: () -> Config
with tempfile.NamedTemporaryFile() as f: with tempfile.NamedTemporaryFile() as f:
f.close() f.close()
...@@ -36,6 +46,15 @@ def mock_clone(_, source, dest): ...@@ -36,6 +46,15 @@ def mock_clone(_, source, dest):
shutil.copytree(str(folder), str(dest)) shutil.copytree(str(folder), str(dest))
@pytest.fixture
def environ():
original_environ = os.environ
yield os.environ
os.environ = original_environ
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def git_mock(mocker): def git_mock(mocker):
# Patch git module to not actually clone projects # Patch git module to not actually clone projects
......
...@@ -418,3 +418,36 @@ Writing lock file ...@@ -418,3 +418,36 @@ Writing lock file
assert "cachy" in content["dev-dependencies"] assert "cachy" in content["dev-dependencies"]
assert content["dev-dependencies"]["cachy"] == "^0.2.0" assert content["dev-dependencies"]["cachy"] == "^0.2.0"
def test_add_should_not_select_prereleases(app, repo, installer):
command = app.find("add")
tester = CommandTester(command)
repo.add_package(get_package("pyyaml", "3.13"))
repo.add_package(get_package("pyyaml", "4.2b2"))
tester.execute([("command", command.get_name()), ("name", ["pyyaml"])])
expected = """\
Using version ^3.13 for pyyaml
Updating dependencies
Resolving dependencies...
Package operations: 1 install, 0 updates, 0 removals
Writing lock file
- Installing pyyaml (3.13)
"""
assert tester.get_display(True) == expected
assert len(installer.installs) == 1
content = app.poetry.file.read()["tool"]["poetry"]
assert "pyyaml" in content["dependencies"]
assert content["dependencies"]["pyyaml"] == "^3.13"
import pytest
import shutil
import tempfile
from cleo.testers import CommandTester from cleo.testers import CommandTester
from poetry.utils._compat import Path from poetry.utils._compat import Path
...@@ -9,15 +5,6 @@ from poetry.utils._compat import Path ...@@ -9,15 +5,6 @@ from poetry.utils._compat import Path
from tests.helpers import get_package from tests.helpers import get_package
@pytest.fixture
def tmp_dir():
dir_ = tempfile.mkdtemp(prefix="poetry_")
yield dir_
shutil.rmtree(dir_)
def test_basic_interactive(app, mocker, poetry): def test_basic_interactive(app, mocker, poetry):
command = app.find("init") command = app.find("init")
command._pool = poetry.pool command._pool = poetry.pool
......
...@@ -50,7 +50,9 @@ def installed(): ...@@ -50,7 +50,9 @@ def installed():
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def setup(mocker, installer, installed): def setup(mocker, installer, installed):
Env._env = MockEnv() mocker.patch(
"poetry.utils.env.Env.get", return_value=MockEnv(is_venv=True, execute=True)
)
# Set Installer's installer # Set Installer's installer
p = mocker.patch("poetry.installation.installer.Installer._get_installer") p = mocker.patch("poetry.installation.installer.Installer._get_installer")
...@@ -78,7 +80,6 @@ def setup(mocker, installer, installed): ...@@ -78,7 +80,6 @@ def setup(mocker, installer, installed):
os.environ.clear() os.environ.clear()
os.environ.update(environ) os.environ.update(environ)
Env._env = None
class Application(BaseApplication): class Application(BaseApplication):
......
from poetry.io import NullIO
from poetry.masonry.builders.builder import Builder
from poetry.poetry import Poetry
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(
Poetry.create(Path(__file__).parent / "fixtures" / "complete"),
NullEnv(),
NullIO(),
)
assert builder.find_excluded_files() == {"my_package/sub_pkg1/extra_file.xml"}
...@@ -163,6 +163,8 @@ def test_complete(): ...@@ -163,6 +163,8 @@ def test_complete():
zip = zipfile.ZipFile(str(whl)) zip = zipfile.ZipFile(str(whl))
try: 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") entry_points = zip.read("my_package-1.2.3.dist-info/entry_points.txt")
assert ( assert (
......
...@@ -15,6 +15,9 @@ from poetry.version.markers import parse_marker ...@@ -15,6 +15,9 @@ from poetry.version.markers import parse_marker
from tests.helpers import get_dependency from tests.helpers import get_dependency
from tests.helpers import get_package from tests.helpers import get_package
from tests.repositories.test_legacy_repository import (
MockRepository as MockLegacyRepository,
)
@pytest.fixture() @pytest.fixture()
...@@ -1488,3 +1491,46 @@ def test_solver_can_resolve_wheel_dependencies_with_extras(solver, repo, package ...@@ -1488,3 +1491,46 @@ def test_solver_can_resolve_wheel_dependencies_with_extras(solver, repo, package
assert op.package.version.text == "0.1.0" assert op.package.version.text == "0.1.0"
assert op.package.source_type == "file" assert op.package.source_type == "file"
assert op.package.source_url == path assert op.package.source_url == path
def test_solver_can_solve_with_legacy_repository_using_proper_dists(
package, installed, locked, io
):
repo = MockLegacyRepository()
pool = Pool([repo])
solver = Solver(package, pool, installed, locked, io)
package.add_dependency("isort", "4.3.4")
ops = solver.solve()
check_solver_result(
ops,
[
{"job": "install", "package": get_package("futures", "3.2.0")},
{"job": "install", "package": get_package("isort", "4.3.4")},
],
)
futures = ops[0].package
assert futures.python_versions == ">=2.6, <3"
def test_solver_can_solve_with_legacy_repository_using_proper_python_compatible_dists(
package, installed, locked, io
):
package.python_versions = "^3.7"
repo = MockLegacyRepository()
pool = Pool([repo])
solver = Solver(package, pool, installed, locked, io)
package.add_dependency("isort", "4.3.4")
ops = solver.solve()
check_solver_result(
ops, [{"job": "install", "package": get_package("isort", "4.3.4")}]
)
<!DOCTYPE html>
<html>
<head>
<title>Links for futures</title>
</head>
<body>
<h1>Links for futures</h1>
<a href="https://files.pythonhosted.org/packages/2d/99/b2c4e9d5a30f6471e410a146232b4118e697fa3ffc06d6a65efde84debd0/futures-3.2.0-py2-none-any.whl#sha256=ec0a6cb848cc212002b9828c3e34c675e0c9ff6741dc445cab6fdd4e1085d1f1" data-requires-python="&gt;=2.6, &lt;3">futures-3.2.0-py2-none-any.whl</a><br/>
<a href="https://files.pythonhosted.org/packages/1f/9e/7b2ff7e965fc654592269f2906ade1c7d705f1bf25b7d469fa153f7d19eb/futures-3.2.0.tar.gz#sha256=9ec02aa7d674acb8618afb127e27fde7fc68994c0437ad759fa094a574adb265" data-requires-python="&gt;=2.6, &lt;3">futures-3.2.0.tar.gz</a><br/>
</body>
</html>
<!--SERIAL 3865286-->
<!DOCTYPE html>
<html>
<head>
<title>Links for isort</title>
</head>
<body>
<h1>Links for isort</h1>
<a href="https://files.pythonhosted.org/packages/41/d8/a945da414f2adc1d9e2f7d6e7445b27f2be42766879062a2e63616ad4199/isort-4.3.4-py2-none-any.whl#sha256=ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497">isort-4.3.4-py2-none-any.whl</a><br/>
<a href="https://files.pythonhosted.org/packages/1f/2c/22eee714d7199ae0464beda6ad5fedec8fee6a2f7ffd1e8f1840928fe318/isort-4.3.4-py3-none-any.whl#sha256=1153601da39a25b14ddc54955dbbacbb6b2d19135386699e2ad58517953b34af">isort-4.3.4-py3-none-any.whl</a><br/>
<a href="https://files.pythonhosted.org/packages/b1/de/a628d16fdba0d38cafb3d7e34d4830f2c9cb3881384ce5c08c44762e1846/isort-4.3.4.tar.gz#sha256=b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8">isort-4.3.4.tar.gz</a><br/>
</body>
</html>
<!--SERIAL 3575149-->
<!DOCTYPE html>
<html>
<head>
<title>Links for python-language-server</title>
</head>
<body>
<h1>Links for python-language-server</h1>
<a href="https://files.pythonhosted.org/packages/9e/a3/1d13970c3f36777c583f136c136f804d70f500168edc1edea6daa7200769/PyYAML-3.13.tar.gz#sha256=3ef3092145e9b70e3ddd2c7ad59bdd0252a94dfe3949721633e41344de00a6bf">PyYAML-3.13.tar.gz</a><br/>
<a href="https://files.pythonhosted.org/packages/0f/9d/f98ed0a460dc540f720bbe5c6e076f025595cdfa3e318fad27165db13cf9/PyYAML-4.2b2.tar.gz#sha256=406b717f739e2d00c49873068b71f5454c2420157db51b082d4d2beb17ffffb6">PyYAML-4.2b2.tar.gz</a><br/>
</body>
</html>
<!--SERIAL 4245719-->
{
"info": {
"author": "Kirill Simonov",
"author_email": "xi@resolvent.net",
"bugtrack_url": null,
"classifiers": [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Text Processing :: Markup"
],
"description": "",
"description_content_type": "",
"docs_url": null,
"download_url": "http://pyyaml.org/download/pyyaml/PyYAML-3.13.tar.gz",
"downloads": {
"last_day": -1,
"last_month": -1,
"last_week": -1
},
"home_page": "http://pyyaml.org/wiki/PyYAML",
"keywords": "",
"license": "MIT",
"maintainer": "",
"maintainer_email": "",
"name": "PyYAML",
"package_url": "https://pypi.org/project/PyYAML/",
"platform": "Any",
"project_url": "https://pypi.org/project/PyYAML/",
"project_urls": {
"Download": "http://pyyaml.org/download/pyyaml/PyYAML-3.13.tar.gz",
"Homepage": "http://pyyaml.org/wiki/PyYAML"
},
"release_url": "https://pypi.org/project/PyYAML/3.13/",
"requires_dist": null,
"requires_python": "",
"summary": "YAML parser and emitter for Python",
"version": "3.13"
},
"last_serial": 4034753,
"releases": {
"3.13": [
{
"comment_text": "",
"digests": {
"md5": "a83441aa7004e474bed6f6daeb61f27a",
"sha256": "d5eef459e30b09f5a098b9cea68bebfeb268697f78d647bd255a085371ac7f3f"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp27-cp27m-win32.whl",
"has_sig": false,
"md5_digest": "a83441aa7004e474bed6f6daeb61f27a",
"packagetype": "bdist_wheel",
"python_version": "cp27",
"requires_python": null,
"size": 191712,
"upload_time": "2018-07-05T22:53:15",
"url": "https://files.pythonhosted.org/packages/b8/2e/9c2285870c9de070a1fa5ede702ab5fb329901b3cc4028c24f44eda27c5f/PyYAML-3.13-cp27-cp27m-win32.whl"
},
{
"comment_text": "",
"digests": {
"md5": "dd05ba2d6cb042452a3849dea13b94f0",
"sha256": "e01d3203230e1786cd91ccfdc8f8454c8069c91bee3962ad93b87a4b2860f537"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp27-cp27m-win_amd64.whl",
"has_sig": false,
"md5_digest": "dd05ba2d6cb042452a3849dea13b94f0",
"packagetype": "bdist_wheel",
"python_version": "cp27",
"requires_python": null,
"size": 209872,
"upload_time": "2018-07-05T22:53:16",
"url": "https://files.pythonhosted.org/packages/df/4d/1ef8d60464a171112401e17a3a3e88fdb1d5b44af7606e8652b2f39ee9ce/PyYAML-3.13-cp27-cp27m-win_amd64.whl"
},
{
"comment_text": "",
"digests": {
"md5": "49365caa070d53e30deceae118e4fea8",
"sha256": "558dd60b890ba8fd982e05941927a3911dc409a63dcb8b634feaa0cda69330d3"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp34-cp34m-win32.whl",
"has_sig": false,
"md5_digest": "49365caa070d53e30deceae118e4fea8",
"packagetype": "bdist_wheel",
"python_version": "cp34",
"requires_python": null,
"size": 192898,
"upload_time": "2018-07-05T22:53:19",
"url": "https://files.pythonhosted.org/packages/35/f0/cf0363b5c431c3a828284903aeacc6bdbba342fd4d7871dda9a3b0b00d15/PyYAML-3.13-cp34-cp34m-win32.whl"
},
{
"comment_text": "",
"digests": {
"md5": "0c486a54c19dd18b9e65a559886935c4",
"sha256": "d46d7982b62e0729ad0175a9bc7e10a566fc07b224d2c79fafb5e032727eaa04"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp34-cp34m-win_amd64.whl",
"has_sig": false,
"md5_digest": "0c486a54c19dd18b9e65a559886935c4",
"packagetype": "bdist_wheel",
"python_version": "cp34",
"requires_python": null,
"size": 206242,
"upload_time": "2018-07-05T22:53:20",
"url": "https://files.pythonhosted.org/packages/8c/bc/8950092a86259dc511e02a4c3a517ed4b28a254e4da134e3c04e5264e5a3/PyYAML-3.13-cp34-cp34m-win_amd64.whl"
},
{
"comment_text": "",
"digests": {
"md5": "53ce2b9f6b741fb2f070d12839b5789e",
"sha256": "a7c28b45d9f99102fa092bb213aa12e0aaf9a6a1f5e395d36166639c1f96c3a1"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp35-cp35m-win32.whl",
"has_sig": false,
"md5_digest": "53ce2b9f6b741fb2f070d12839b5789e",
"packagetype": "bdist_wheel",
"python_version": "cp35",
"requires_python": null,
"size": 187499,
"upload_time": "2018-07-05T22:53:22",
"url": "https://files.pythonhosted.org/packages/29/33/8bbcd3740d9e96cfb57427b8db7a12093402a3a83f2054887e027b2849de/PyYAML-3.13-cp35-cp35m-win32.whl"
},
{
"comment_text": "",
"digests": {
"md5": "1b70e7ced4c82364bda4ac9094d6e259",
"sha256": "bc558586e6045763782014934bfaf39d48b8ae85a2713117d16c39864085c613"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp35-cp35m-win_amd64.whl",
"has_sig": false,
"md5_digest": "1b70e7ced4c82364bda4ac9094d6e259",
"packagetype": "bdist_wheel",
"python_version": "cp35",
"requires_python": null,
"size": 205387,
"upload_time": "2018-07-05T22:53:24",
"url": "https://files.pythonhosted.org/packages/ad/d4/d895fb7ac1b0828151b829a32cefc8a8b58b4499570520b91af20982b880/PyYAML-3.13-cp35-cp35m-win_amd64.whl"
},
{
"comment_text": "",
"digests": {
"md5": "8f62197b853b5b387ff588df05cee7a6",
"sha256": "40c71b8e076d0550b2e6380bada1f1cd1017b882f7e16f09a65be98e017f211a"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp36-cp36m-win32.whl",
"has_sig": false,
"md5_digest": "8f62197b853b5b387ff588df05cee7a6",
"packagetype": "bdist_wheel",
"python_version": "cp36",
"requires_python": null,
"size": 188186,
"upload_time": "2018-07-05T22:53:25",
"url": "https://files.pythonhosted.org/packages/fb/51/0c49c6caafe8d9a27ad9b0ca9f91adda5a5072b9efbbe7585fb97a4c71c4/PyYAML-3.13-cp36-cp36m-win32.whl"
},
{
"comment_text": "",
"digests": {
"md5": "ff7280dd032d202b417871d39febadec",
"sha256": "3d7da3009c0f3e783b2c873687652d83b1bbfd5c88e9813fb7e5b03c0dd3108b"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp36-cp36m-win_amd64.whl",
"has_sig": false,
"md5_digest": "ff7280dd032d202b417871d39febadec",
"packagetype": "bdist_wheel",
"python_version": "cp36",
"requires_python": null,
"size": 206277,
"upload_time": "2018-07-05T22:53:27",
"url": "https://files.pythonhosted.org/packages/4f/ca/5fad249c5032270540c24d2189b0ddf1396aac49b0bdc548162edcf14131/PyYAML-3.13-cp36-cp36m-win_amd64.whl"
},
{
"comment_text": "",
"digests": {
"md5": "03ac720a2dcb18f2f1a3d026d281d778",
"sha256": "e170a9e6fcfd19021dd29845af83bb79236068bf5fd4df3327c1be18182b2531"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp37-cp37m-win32.whl",
"has_sig": false,
"md5_digest": "03ac720a2dcb18f2f1a3d026d281d778",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": null,
"size": 188313,
"upload_time": "2018-07-05T22:53:28",
"url": "https://files.pythonhosted.org/packages/5c/ed/d6557f70daaaab6ee5cd2f8ccf7bedd63081e522e38679c03840e1acc114/PyYAML-3.13-cp37-cp37m-win32.whl"
},
{
"comment_text": "",
"digests": {
"md5": "02ab28701247a80e059daa6efe11e67d",
"sha256": "aa7dd4a6a427aed7df6fb7f08a580d68d9b118d90310374716ae90b710280af1"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp37-cp37m-win_amd64.whl",
"has_sig": false,
"md5_digest": "02ab28701247a80e059daa6efe11e67d",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": null,
"size": 206614,
"upload_time": "2018-07-05T22:53:30",
"url": "https://files.pythonhosted.org/packages/bf/96/d02ef8e1f3073e07ffdc240444e5041f403f29c0775f9f1653f18221082f/PyYAML-3.13-cp37-cp37m-win_amd64.whl"
},
{
"comment_text": "",
"digests": {
"md5": "b78b96636d68ac581c0e2f38158c224f",
"sha256": "3ef3092145e9b70e3ddd2c7ad59bdd0252a94dfe3949721633e41344de00a6bf"
},
"downloads": -1,
"filename": "PyYAML-3.13.tar.gz",
"has_sig": false,
"md5_digest": "b78b96636d68ac581c0e2f38158c224f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 270607,
"upload_time": "2018-07-05T22:52:16",
"url": "https://files.pythonhosted.org/packages/9e/a3/1d13970c3f36777c583f136c136f804d70f500168edc1edea6daa7200769/PyYAML-3.13.tar.gz"
}
],
"4.2b4": [
{
"comment_text": "",
"digests": {
"md5": "76e2c2e8adea20377d9a7e6b6713c952",
"sha256": "8d6d96001aa7f0a6a4a95e8143225b5d06e41b1131044913fecb8f85a125714b"
},
"downloads": -1,
"filename": "PyYAML-4.2b4-cp27-cp27m-win32.whl",
"has_sig": false,
"md5_digest": "76e2c2e8adea20377d9a7e6b6713c952",
"packagetype": "bdist_wheel",
"python_version": "cp27",
"requires_python": null,
"size": 104988,
"upload_time": "2018-07-02T03:17:55",
"url": "https://files.pythonhosted.org/packages/12/9b/efdbaa3c9694b6315a4410e0d494ad50c5ade22ce33f4b482bfaea3930fd/PyYAML-4.2b4-cp27-cp27m-win32.whl"
},
{
"comment_text": "",
"digests": {
"md5": "2ab351c6736b4e98721b37b14fd88002",
"sha256": "c8a88edd93ee29ede719080b2be6cb2333dfee1dccba213b422a9c8e97f2967b"
},
"downloads": -1,
"filename": "PyYAML-4.2b4-cp27-cp27m-win_amd64.whl",
"has_sig": false,
"md5_digest": "2ab351c6736b4e98721b37b14fd88002",
"packagetype": "bdist_wheel",
"python_version": "cp27",
"requires_python": null,
"size": 115361,
"upload_time": "2018-07-02T03:18:06",
"url": "https://files.pythonhosted.org/packages/da/81/4ecefcc907b4ba1d181eb031a6da45b79e7b6db8b2376aa3040c4a2d01ea/PyYAML-4.2b4-cp27-cp27m-win_amd64.whl"
},
{
"comment_text": "",
"digests": {
"md5": "cae07819a730ec7a811b3a20b31e0103",
"sha256": "3108529b78577327d15eec243f0ff348a0640b0c3478d67ad7f5648f93bac3e2"
},
"downloads": -1,
"filename": "PyYAML-4.2b4-cp34-cp34m-win32.whl",
"has_sig": false,
"md5_digest": "cae07819a730ec7a811b3a20b31e0103",
"packagetype": "bdist_wheel",
"python_version": "cp34",
"requires_python": null,
"size": 104095,
"upload_time": "2018-07-02T03:18:13",
"url": "https://files.pythonhosted.org/packages/41/63/9a082d3be6e53452959b66389646b56ecef2c6e4f205a52ff8196ce49eef/PyYAML-4.2b4-cp34-cp34m-win32.whl"
},
{
"comment_text": "",
"digests": {
"md5": "d0e6d73234c356003022281f2e61748a",
"sha256": "254bf6fda2b7c651837acb2c718e213df29d531eebf00edb54743d10bcb694eb"
},
"downloads": -1,
"filename": "PyYAML-4.2b4-cp34-cp34m-win_amd64.whl",
"has_sig": false,
"md5_digest": "d0e6d73234c356003022281f2e61748a",
"packagetype": "bdist_wheel",
"python_version": "cp34",
"requires_python": null,
"size": 113201,
"upload_time": "2018-07-02T03:18:16",
"url": "https://files.pythonhosted.org/packages/96/2b/8c2841d7ea6a319acc62537ad59910d545008ccd87d84b6a7813fb8d724d/PyYAML-4.2b4-cp34-cp34m-win_amd64.whl"
},
{
"comment_text": "",
"digests": {
"md5": "a842bc7391e145bbe4e7fd0d32da1132",
"sha256": "3c17fb92c8ba2f525e4b5f7941d850e7a48c3a59b32d331e2502a3cdc6648e76"
},
"downloads": -1,
"filename": "PyYAML-4.2b4.tar.gz",
"has_sig": false,
"md5_digest": "a842bc7391e145bbe4e7fd0d32da1132",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 262628,
"upload_time": "2018-07-02T03:18:24",
"url": "https://files.pythonhosted.org/packages/a8/c6/a8d1555e795dbd0375c3c93b576ca13bbf139db51ea604afa19a2c35fc03/PyYAML-4.2b4.tar.gz"
},
{
"comment_text": "",
"digests": {
"md5": "e8b64f1f531762b4f7a7ee1c32d6819d",
"sha256": "1cbc199009e78f92d9edf554be4fe40fb7b0bef71ba688602a00e97a51909110"
},
"downloads": -1,
"filename": "PyYAML-4.2b4.win32-py2.7.exe",
"has_sig": false,
"md5_digest": "e8b64f1f531762b4f7a7ee1c32d6819d",
"packagetype": "bdist_wininst",
"python_version": "2.7",
"requires_python": null,
"size": 301122,
"upload_time": "2018-07-02T03:18:50",
"url": "https://files.pythonhosted.org/packages/16/06/6157cf397464f883e7d5e22b3c6b8c86025291f62304ccba75285e3cf25b/PyYAML-4.2b4.win32-py2.7.exe"
},
{
"comment_text": "",
"digests": {
"md5": "5dc5a4b389eab8de7492429ac9f190a7",
"sha256": "6f89b5c95e93945b597776163403d47af72d243f366bf4622ff08bdfd1c950b7"
},
"downloads": -1,
"filename": "PyYAML-4.2b4.win32-py3.4.exe",
"has_sig": false,
"md5_digest": "5dc5a4b389eab8de7492429ac9f190a7",
"packagetype": "bdist_wininst",
"python_version": "3.4",
"requires_python": null,
"size": 295125,
"upload_time": "2018-07-02T03:18:57",
"url": "https://files.pythonhosted.org/packages/47/83/7f39055bd68e0918dde8308fd57f0bf75d1579e2695e8b9a127d0c401a03/PyYAML-4.2b4.win32-py3.4.exe"
},
{
"comment_text": "",
"digests": {
"md5": "e56fcfe6196a5858fbc4ab69c9c5c21f",
"sha256": "be622cc81696e24d0836ba71f6272a2b5767669b0d79fdcf0295d51ac2e156c8"
},
"downloads": -1,
"filename": "PyYAML-4.2b4.win-amd64-py2.7.exe",
"has_sig": false,
"md5_digest": "e56fcfe6196a5858fbc4ab69c9c5c21f",
"packagetype": "bdist_wininst",
"python_version": "2.7",
"requires_python": null,
"size": 339138,
"upload_time": "2018-07-02T03:18:31",
"url": "https://files.pythonhosted.org/packages/bc/51/36675a109c0cf585c1cb3c89f50f2014f4c228dc69572178c5b01de5aa96/PyYAML-4.2b4.win-amd64-py2.7.exe"
},
{
"comment_text": "",
"digests": {
"md5": "0c60ac15877e9f50f72c52eb45cb85c6",
"sha256": "f39411e380e2182ad33be039e8ee5770a5d9efe01a2bfb7ae58d9ba31c4a2a9d"
},
"downloads": -1,
"filename": "PyYAML-4.2b4.win-amd64-py3.4.exe",
"has_sig": false,
"md5_digest": "0c60ac15877e9f50f72c52eb45cb85c6",
"packagetype": "bdist_wininst",
"python_version": "3.4",
"requires_python": null,
"size": 335462,
"upload_time": "2018-07-02T03:18:40",
"url": "https://files.pythonhosted.org/packages/f2/62/415e37aa4296599a0db50dbdb6d9dd480ad4571008db855cf3c4dfdccea6/PyYAML-4.2b4.win-amd64-py3.4.exe"
}
]
},
"urls": [
{
"comment_text": "",
"digests": {
"md5": "a83441aa7004e474bed6f6daeb61f27a",
"sha256": "d5eef459e30b09f5a098b9cea68bebfeb268697f78d647bd255a085371ac7f3f"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp27-cp27m-win32.whl",
"has_sig": false,
"md5_digest": "a83441aa7004e474bed6f6daeb61f27a",
"packagetype": "bdist_wheel",
"python_version": "cp27",
"requires_python": null,
"size": 191712,
"upload_time": "2018-07-05T22:53:15",
"url": "https://files.pythonhosted.org/packages/b8/2e/9c2285870c9de070a1fa5ede702ab5fb329901b3cc4028c24f44eda27c5f/PyYAML-3.13-cp27-cp27m-win32.whl"
},
{
"comment_text": "",
"digests": {
"md5": "dd05ba2d6cb042452a3849dea13b94f0",
"sha256": "e01d3203230e1786cd91ccfdc8f8454c8069c91bee3962ad93b87a4b2860f537"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp27-cp27m-win_amd64.whl",
"has_sig": false,
"md5_digest": "dd05ba2d6cb042452a3849dea13b94f0",
"packagetype": "bdist_wheel",
"python_version": "cp27",
"requires_python": null,
"size": 209872,
"upload_time": "2018-07-05T22:53:16",
"url": "https://files.pythonhosted.org/packages/df/4d/1ef8d60464a171112401e17a3a3e88fdb1d5b44af7606e8652b2f39ee9ce/PyYAML-3.13-cp27-cp27m-win_amd64.whl"
},
{
"comment_text": "",
"digests": {
"md5": "49365caa070d53e30deceae118e4fea8",
"sha256": "558dd60b890ba8fd982e05941927a3911dc409a63dcb8b634feaa0cda69330d3"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp34-cp34m-win32.whl",
"has_sig": false,
"md5_digest": "49365caa070d53e30deceae118e4fea8",
"packagetype": "bdist_wheel",
"python_version": "cp34",
"requires_python": null,
"size": 192898,
"upload_time": "2018-07-05T22:53:19",
"url": "https://files.pythonhosted.org/packages/35/f0/cf0363b5c431c3a828284903aeacc6bdbba342fd4d7871dda9a3b0b00d15/PyYAML-3.13-cp34-cp34m-win32.whl"
},
{
"comment_text": "",
"digests": {
"md5": "0c486a54c19dd18b9e65a559886935c4",
"sha256": "d46d7982b62e0729ad0175a9bc7e10a566fc07b224d2c79fafb5e032727eaa04"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp34-cp34m-win_amd64.whl",
"has_sig": false,
"md5_digest": "0c486a54c19dd18b9e65a559886935c4",
"packagetype": "bdist_wheel",
"python_version": "cp34",
"requires_python": null,
"size": 206242,
"upload_time": "2018-07-05T22:53:20",
"url": "https://files.pythonhosted.org/packages/8c/bc/8950092a86259dc511e02a4c3a517ed4b28a254e4da134e3c04e5264e5a3/PyYAML-3.13-cp34-cp34m-win_amd64.whl"
},
{
"comment_text": "",
"digests": {
"md5": "53ce2b9f6b741fb2f070d12839b5789e",
"sha256": "a7c28b45d9f99102fa092bb213aa12e0aaf9a6a1f5e395d36166639c1f96c3a1"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp35-cp35m-win32.whl",
"has_sig": false,
"md5_digest": "53ce2b9f6b741fb2f070d12839b5789e",
"packagetype": "bdist_wheel",
"python_version": "cp35",
"requires_python": null,
"size": 187499,
"upload_time": "2018-07-05T22:53:22",
"url": "https://files.pythonhosted.org/packages/29/33/8bbcd3740d9e96cfb57427b8db7a12093402a3a83f2054887e027b2849de/PyYAML-3.13-cp35-cp35m-win32.whl"
},
{
"comment_text": "",
"digests": {
"md5": "1b70e7ced4c82364bda4ac9094d6e259",
"sha256": "bc558586e6045763782014934bfaf39d48b8ae85a2713117d16c39864085c613"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp35-cp35m-win_amd64.whl",
"has_sig": false,
"md5_digest": "1b70e7ced4c82364bda4ac9094d6e259",
"packagetype": "bdist_wheel",
"python_version": "cp35",
"requires_python": null,
"size": 205387,
"upload_time": "2018-07-05T22:53:24",
"url": "https://files.pythonhosted.org/packages/ad/d4/d895fb7ac1b0828151b829a32cefc8a8b58b4499570520b91af20982b880/PyYAML-3.13-cp35-cp35m-win_amd64.whl"
},
{
"comment_text": "",
"digests": {
"md5": "8f62197b853b5b387ff588df05cee7a6",
"sha256": "40c71b8e076d0550b2e6380bada1f1cd1017b882f7e16f09a65be98e017f211a"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp36-cp36m-win32.whl",
"has_sig": false,
"md5_digest": "8f62197b853b5b387ff588df05cee7a6",
"packagetype": "bdist_wheel",
"python_version": "cp36",
"requires_python": null,
"size": 188186,
"upload_time": "2018-07-05T22:53:25",
"url": "https://files.pythonhosted.org/packages/fb/51/0c49c6caafe8d9a27ad9b0ca9f91adda5a5072b9efbbe7585fb97a4c71c4/PyYAML-3.13-cp36-cp36m-win32.whl"
},
{
"comment_text": "",
"digests": {
"md5": "ff7280dd032d202b417871d39febadec",
"sha256": "3d7da3009c0f3e783b2c873687652d83b1bbfd5c88e9813fb7e5b03c0dd3108b"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp36-cp36m-win_amd64.whl",
"has_sig": false,
"md5_digest": "ff7280dd032d202b417871d39febadec",
"packagetype": "bdist_wheel",
"python_version": "cp36",
"requires_python": null,
"size": 206277,
"upload_time": "2018-07-05T22:53:27",
"url": "https://files.pythonhosted.org/packages/4f/ca/5fad249c5032270540c24d2189b0ddf1396aac49b0bdc548162edcf14131/PyYAML-3.13-cp36-cp36m-win_amd64.whl"
},
{
"comment_text": "",
"digests": {
"md5": "03ac720a2dcb18f2f1a3d026d281d778",
"sha256": "e170a9e6fcfd19021dd29845af83bb79236068bf5fd4df3327c1be18182b2531"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp37-cp37m-win32.whl",
"has_sig": false,
"md5_digest": "03ac720a2dcb18f2f1a3d026d281d778",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": null,
"size": 188313,
"upload_time": "2018-07-05T22:53:28",
"url": "https://files.pythonhosted.org/packages/5c/ed/d6557f70daaaab6ee5cd2f8ccf7bedd63081e522e38679c03840e1acc114/PyYAML-3.13-cp37-cp37m-win32.whl"
},
{
"comment_text": "",
"digests": {
"md5": "02ab28701247a80e059daa6efe11e67d",
"sha256": "aa7dd4a6a427aed7df6fb7f08a580d68d9b118d90310374716ae90b710280af1"
},
"downloads": -1,
"filename": "PyYAML-3.13-cp37-cp37m-win_amd64.whl",
"has_sig": false,
"md5_digest": "02ab28701247a80e059daa6efe11e67d",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": null,
"size": 206614,
"upload_time": "2018-07-05T22:53:30",
"url": "https://files.pythonhosted.org/packages/bf/96/d02ef8e1f3073e07ffdc240444e5041f403f29c0775f9f1653f18221082f/PyYAML-3.13-cp37-cp37m-win_amd64.whl"
},
{
"comment_text": "",
"digests": {
"md5": "b78b96636d68ac581c0e2f38158c224f",
"sha256": "3ef3092145e9b70e3ddd2c7ad59bdd0252a94dfe3949721633e41344de00a6bf"
},
"downloads": -1,
"filename": "PyYAML-3.13.tar.gz",
"has_sig": false,
"md5_digest": "b78b96636d68ac581c0e2f38158c224f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 270607,
"upload_time": "2018-07-05T22:52:16",
"url": "https://files.pythonhosted.org/packages/9e/a3/1d13970c3f36777c583f136c136f804d70f500168edc1edea6daa7200769/PyYAML-3.13.tar.gz"
}
]
}
import base64
from requests import Request
from poetry.repositories.auth import Auth
from poetry.utils._compat import decode
from poetry.utils._compat import encode
def test_auth_with_request_on_the_same_host():
auth = Auth("https://poetry.eustace.io", "foo", "bar")
request = Request("GET", "https://poetry.eustace.io/docs/")
assert "Authorization" not in request.headers
request = auth(request)
assert "Authorization" in request.headers
assert request.headers["Authorization"] == "Basic {}".format(
decode(base64.b64encode(encode(":".join(("foo", "bar")))))
)
def test_auth_with_request_on_different_hosts():
auth = Auth("https://poetry.eustace.io", "foo", "bar")
request = Request("GET", "https://pendulum.eustace.io/docs/")
assert "Authorization" not in request.headers
request = auth(request)
assert "Authorization" not in request.headers
...@@ -128,3 +128,44 @@ def test_get_package_information_skips_dependencies_with_invalid_constraints(): ...@@ -128,3 +128,44 @@ def test_get_package_information_skips_dependencies_with_invalid_constraints():
Dependency("pyflakes", ">=1.6.0"), Dependency("pyflakes", ">=1.6.0"),
Dependency("yapf", "*"), Dependency("yapf", "*"),
] ]
def test_find_packages_no_prereleases():
repo = MockRepository()
packages = repo.find_packages("pyyaml")
assert len(packages) == 1
def test_get_package_information_chooses_correct_distribution():
repo = MockRepository()
package = repo.package("isort", "4.3.4")
assert package.name == "isort"
assert package.version.text == "4.3.4"
assert package.requires == [Dependency("futures", "*")]
futures_dep = package.requires[0]
assert futures_dep.python_versions == "~2.7"
def test_get_package_information_includes_python_requires():
repo = MockRepository()
package = repo.package("futures", "3.2.0")
assert package.name == "futures"
assert package.version.text == "3.2.0"
assert package.python_versions == ">=2.6, <3"
def test_get_package_information_sets_appropriate_python_versions_if_wheels_only():
repo = MockRepository()
package = repo.package("futures", "3.2.0")
assert package.name == "futures"
assert package.version.text == "3.2.0"
assert package.python_versions == ">=2.6, <3"
...@@ -58,6 +58,13 @@ def test_find_packages_with_prereleases(): ...@@ -58,6 +58,13 @@ def test_find_packages_with_prereleases():
assert len(packages) == 7 assert len(packages) == 7
def test_find_packages_does_not_select_prereleases_if_not_allowed():
repo = MockRepository()
packages = repo.find_packages("pyyaml")
assert len(packages) == 1
def test_package(): def test_package():
repo = MockRepository() repo = MockRepository()
......
import os
from poetry.utils._compat import Path
from poetry.utils.env import Env
from poetry.utils.env import VirtualEnv
def test_virtualenvs_with_spaces_in_their_path_work_as_expected(tmp_dir):
venv_path = Path(tmp_dir) / "Virtual Env"
Env.build_venv(str(venv_path))
venv = VirtualEnv(venv_path)
assert venv.run("python", "-V", shell=True).startswith("Python")
def test_env_get_in_project_venv(tmp_dir, environ):
if "VIRTUAL_ENV" in environ:
del environ["VIRTUAL_ENV"]
(Path(tmp_dir) / ".venv").mkdir()
venv = Env.get(cwd=Path(tmp_dir))
assert venv.path == Path(tmp_dir) / ".venv"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment