Commit cd28d5c2 by Sébastien Eustace

Merge branch 'master' into develop

parents 9c944b15 a1b97707
...@@ -31,6 +31,7 @@ MANIFEST.in ...@@ -31,6 +31,7 @@ MANIFEST.in
/docs/site/* /docs/site/*
pyproject.lock pyproject.lock
/tests/fixtures/simple_project/setup.py /tests/fixtures/simple_project/setup.py
/tests/fixtures/project_with_extras/setup.py
.mypy_cache .mypy_cache
.venv .venv
# Change Log # Change Log
## [0.11.4] - 2018-07-30
### Fixed
- Fixed wrong wheel being selected when resolving dependencies.
- Fixed an error when publishing.
- Fixed an error when building wheels with the `packages` property set.
- Fixed single value display in `config` command.
## [0.11.3] - 2018-07-26 ## [0.11.3] - 2018-07-26
### Changed ### Changed
...@@ -446,7 +456,8 @@ Initial release ...@@ -446,7 +456,8 @@ Initial release
[Unreleased]: https://github.com/sdispater/poetry/compare/0.11.3...master [Unreleased]: https://github.com/sdispater/poetry/compare/0.11.4...master
[0.11.4]: https://github.com/sdispater/poetry/releases/tag/0.11.4
[0.11.3]: https://github.com/sdispater/poetry/releases/tag/0.11.3 [0.11.3]: https://github.com/sdispater/poetry/releases/tag/0.11.3
[0.11.2]: https://github.com/sdispater/poetry/releases/tag/0.11.2 [0.11.2]: https://github.com/sdispater/poetry/releases/tag/0.11.2
[0.11.1]: https://github.com/sdispater/poetry/releases/tag/0.11.1 [0.11.1]: https://github.com/sdispater/poetry/releases/tag/0.11.1
......
...@@ -51,3 +51,15 @@ commands = ...@@ -51,3 +51,15 @@ commands =
poetry install -v poetry install -v
poetry run pytest tests/ poetry run pytest tests/
``` ```
## I don't want Poetry to manage my virtualenvs. Can I disable it?
While Poetry automatically creates virtualenvs to always work isolated
from the global Python installation, there are valid reasons why it's not necessary
and is an overhead, like when working with containers.
In this case, you can disable this feature by setting the `virtualenvs.create` setting to `false`:
```bash
poetry config settings.virtualenvs.create false
```
__version__ = "0.11.3" __version__ = "0.11.4"
...@@ -118,6 +118,17 @@ To remove a repository (repo is a short alias for repositories): ...@@ -118,6 +118,17 @@ To remove a repository (repo is a short alias for repositories):
value = repo value = repo
self.line(str(value)) self.line(str(value))
else:
values = self.unique_config_values
if setting_key not in values:
raise ValueError("There is no {} setting.".format(setting_key))
values = self._get_setting(
self._config.content, setting_key, default=values[setting_key][-1]
)
for value in values:
self.line(value[1])
return 0 return 0
...@@ -240,17 +251,22 @@ To remove a repository (repo is a short alias for repositories): ...@@ -240,17 +251,22 @@ To remove a repository (repo is a short alias for repositories):
self._list_setting(repositories, k="repositories.") self._list_setting(repositories, k="repositories.")
def _list_setting(self, contents, setting=None, k=None, default=None): def _list_setting(self, contents, setting=None, k=None, default=None):
values = self._get_setting(contents, setting, k, default)
for value in values:
self.line(
"<comment>{}</comment> = <info>{}</info>".format(value[0], value[1])
)
def _get_setting(self, contents, setting=None, k=None, default=None):
orig_k = k orig_k = k
if setting and setting.split(".")[0] not in contents: if setting and setting.split(".")[0] not in contents:
value = json.dumps(default) value = json.dumps(default)
self.line( return [((k or "") + setting, value)]
"<comment>{}</comment> = <info>{}</info>".format(
(k or "") + setting, value
)
)
else: else:
values = []
for key, value in contents.items(): for key, value in contents.items():
if k is None and key not in ["config", "repositories", "settings"]: if k is None and key not in ["config", "repositories", "settings"]:
continue continue
...@@ -266,7 +282,9 @@ To remove a repository (repo is a short alias for repositories): ...@@ -266,7 +282,9 @@ To remove a repository (repo is a short alias for repositories):
if setting and len(setting) > 1: if setting and len(setting) > 1:
setting = ".".join(setting.split(".")[1:]) setting = ".".join(setting.split(".")[1:])
self._list_setting(value, k=k, setting=setting, default=default) values += self._get_setting(
value, k=k, setting=setting, default=default
)
k = orig_k k = orig_k
continue continue
...@@ -281,11 +299,9 @@ To remove a repository (repo is a short alias for repositories): ...@@ -281,11 +299,9 @@ To remove a repository (repo is a short alias for repositories):
value = json.dumps(value) value = json.dumps(value)
self.line( values.append(((k or "") + key, value))
"<comment>{}</comment> = <info>{}</info>".format(
(k or "") + key, value return values
)
)
def _get_formatted_value(self, value): def _get_formatted_value(self, value):
if isinstance(value, list): if isinstance(value, list):
......
...@@ -52,7 +52,7 @@ class Publisher: ...@@ -52,7 +52,7 @@ class Publisher:
"Unable to get repository information" "Unable to get repository information"
) )
config = config_file.read(raw=True) config = config_file.read()
if ( if (
"repositories" not in config "repositories" not in config
......
...@@ -19,7 +19,7 @@ class Include(object): ...@@ -19,7 +19,7 @@ class Include(object):
def __init__(self, base, include): # type: (Path, str) -> None def __init__(self, base, include): # type: (Path, str) -> None
self._base = base self._base = base
self._include = include self._include = str(include)
self._elements = sorted(list(self._base.glob(str(self._include)))) self._elements = sorted(list(self._base.glob(str(self._include))))
......
...@@ -77,6 +77,7 @@ class DirectoryDependency(Dependency): ...@@ -77,6 +77,7 @@ class DirectoryDependency(Dependency):
self._package = Package(package.pretty_name, package.version) self._package = Package(package.pretty_name, package.version)
self._package.requires += package.requires self._package.requires += package.requires
self._package.dev_requires += package.dev_requires self._package.dev_requires += package.dev_requires
self._package.extras = package.extras
self._package.python_versions = package.python_versions self._package.python_versions = package.python_versions
self._package.platform = package.platform self._package.platform = package.platform
else: else:
......
...@@ -314,9 +314,10 @@ class Provider: ...@@ -314,9 +314,10 @@ class Provider:
] ]
def complete_package(self, package): # type: (str, Version) -> Package def complete_package(self, package): # type: (str, Version) -> Package
if package.is_root() or package.source_type in {"git", "file", "directory"}: if package.is_root() or package.source_type in {"git", "file"}:
return package return package
if package.source_type != "directory":
package = self._pool.package( package = self._pool.package(
package.name, package.version.text, extras=package.requires_extras package.name, package.version.text, extras=package.requires_extras
) )
......
import logging import logging
import os import os
import re
import tarfile import tarfile
import zipfile import zipfile
...@@ -288,16 +289,43 @@ class PyPiRepository(Repository): ...@@ -288,16 +289,43 @@ class PyPiRepository(Repository):
continue continue
# If bdist_wheel, check if it's universal # If bdist_wheel, check if it's universal
python_version = url["python_version"] filename = url["filename"]
if python_version not in ["py2.py3", "py3", "py2"]: if not re.search("-py2\.py3-none-any.whl", filename):
continue continue
parts = urlparse.urlparse(url["url"]) urls[dist_type] = url["url"]
filename = os.path.basename(parts.path)
if "-none-any" not in filename: if "sdist" in url and "bdist_wheel" not in urls:
# If can't found a universal wheel
# but we found an sdist, inspect the sdist first
info = self._get_info_from_urls(urls)
if info["requires_dist"]:
data["requires_dist"] = info["requires_dist"]
if not data["requires_python"]:
data["requires_python"] = info["requires_python"]
return data
else:
del urls["sdist"]
if not urls:
# If we don't have urls, we try to take the first one
# we find and go from there
if not json_data["urls"]:
return data
for url in json_data["urls"]:
# Only get sdist and universal wheels if they exist
dist_type = url["packagetype"]
if dist_type != "bdist_wheel":
continue continue
urls[url["packagetype"]] = url["url"]
break
if not urls or "bdist_wheel" not in urls: if not urls or "bdist_wheel" not in urls:
# If we don't have urls, we try to take the first one # If we don't have urls, we try to take the first one
# we find and go from there # we find and go from there
......
...@@ -6,7 +6,9 @@ MODIFIERS = ( ...@@ -6,7 +6,9 @@ MODIFIERS = (
"([+-]?([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?" "([+-]?([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?"
) )
_COMPLETE_VERSION = "v?(\d+)(?:\.(\d+))?(?:\.(\d+))?{}(?:\+[^\s]+)?".format(MODIFIERS) _COMPLETE_VERSION = "v?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:\.(\d+))?{}(?:\+[^\s]+)?".format(
MODIFIERS
)
COMPLETE_VERSION = re.compile("(?i)" + _COMPLETE_VERSION) COMPLETE_VERSION = re.compile("(?i)" + _COMPLETE_VERSION)
......
...@@ -20,6 +20,7 @@ class Version(VersionRange): ...@@ -20,6 +20,7 @@ class Version(VersionRange):
major, # type: int major, # type: int
minor=None, # type: Union[int, None] minor=None, # type: Union[int, None]
patch=None, # type: Union[int, None] patch=None, # type: Union[int, None]
rest=None, # type: Union[int, None]
pre=None, # type: Union[str, None] pre=None, # type: Union[str, None]
build=None, # type: Union[str, None] build=None, # type: Union[str, None]
text=None, # type: Union[str, None] text=None, # type: Union[str, None]
...@@ -44,10 +45,17 @@ class Version(VersionRange): ...@@ -44,10 +45,17 @@ class Version(VersionRange):
if self._precision is not None: if self._precision is not None:
self._precision += 1 self._precision += 1
if rest is None:
rest = 0
else:
if self._precision is not None:
self._precision += 1
if precision is not None: if precision is not None:
self._precision = precision self._precision = precision
self._patch = int(patch) self._patch = int(patch)
self._rest = int(rest)
if text is None: if text is None:
parts = [str(major)] parts = [str(major)]
...@@ -57,6 +65,9 @@ class Version(VersionRange): ...@@ -57,6 +65,9 @@ class Version(VersionRange):
if self._precision >= 3 or patch != 0: if self._precision >= 3 or patch != 0:
parts.append(str(patch)) parts.append(str(patch))
if self._precision >= 4 or rest != 0:
parts.append(str(rest))
text = ".".join(parts) text = ".".join(parts)
if pre: if pre:
text += "-{}".format(pre) text += "-{}".format(pre)
...@@ -94,6 +105,10 @@ class Version(VersionRange): ...@@ -94,6 +105,10 @@ class Version(VersionRange):
return self._patch return self._patch
@property @property
def rest(self): # type: () -> int
return self._rest
@property
def prerelease(self): # type: () -> List[str] def prerelease(self): # type: () -> List[str]
return self._prerelease return self._prerelease
...@@ -185,14 +200,15 @@ class Version(VersionRange): ...@@ -185,14 +200,15 @@ class Version(VersionRange):
major = int(match.group(1)) major = int(match.group(1))
minor = int(match.group(2)) if match.group(2) else None minor = int(match.group(2)) if match.group(2) else None
patch = int(match.group(3)) if match.group(3) 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(4) pre = match.group(5)
build = match.group(5) build = match.group(6)
if build: if build:
build = build.lstrip("+") build = build.lstrip("+")
return Version(major, minor, patch, pre, build, text) return Version(major, minor, patch, rest, pre, build, text)
def is_any(self): def is_any(self):
return False return False
...@@ -289,9 +305,6 @@ class Version(VersionRange): ...@@ -289,9 +305,6 @@ class Version(VersionRange):
if not build: if not build:
return return
if build == "0":
return
if build.startswith("post"): if build.startswith("post"):
build = build.lstrip("post") build = build.lstrip("post")
...@@ -339,6 +352,9 @@ class Version(VersionRange): ...@@ -339,6 +352,9 @@ class Version(VersionRange):
if self.patch != other.patch: if self.patch != other.patch:
return self._cmp_parts(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. # Pre-releases always come before no pre-release string.
if not self.is_prerelease() and other.is_prerelease(): if not self.is_prerelease() and other.is_prerelease():
return 1 return 1
...@@ -380,7 +396,7 @@ class Version(VersionRange): ...@@ -380,7 +396,7 @@ class Version(VersionRange):
if a_part == b_part: if a_part == b_part:
continue continue
# Missing parts come before present ones. # Missing parts come after present ones.
if a_part is None: if a_part is None:
return -1 return -1
...@@ -408,6 +424,7 @@ class Version(VersionRange): ...@@ -408,6 +424,7 @@ class Version(VersionRange):
self._major == other.major self._major == other.major
and self._minor == other.minor and self._minor == other.minor
and self._patch == other.patch and self._patch == other.patch
and self._rest == other.rest
and self._prerelease == other.prerelease and self._prerelease == other.prerelease
and self._build == other.build and self._build == other.build
) )
......
[tool.poetry] [tool.poetry]
name = "poetry" name = "poetry"
version = "0.11.3" version = "0.11.4"
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>"
......
...@@ -64,3 +64,18 @@ repositories = {} ...@@ -64,3 +64,18 @@ repositories = {}
""" """
assert tester.get_display(True) == expected assert tester.get_display(True) == expected
def test_display_single_setting(app, config):
command = app.find("config")
command._config = Config(config.file)
tester = CommandTester(command)
tester.execute(
[("command", command.get_name()), ("key", "settings.virtualenvs.create")]
)
expected = """true
"""
assert tester.get_display(True) == expected
[tool.poetry]
name = "project-with-extras"
version = "1.2.3"
description = "This is a description"
authors = ["Your Name <you@example.com>"]
license = "MIT"
[tool.poetry.dependencies]
python = "*"
pendulum = { version = ">=1.4.4", optional = true }
cachy = { version = ">=0.2.0", optional = true }
[tool.poetry.extras]
extras_a = [ "pendulum" ]
extras_b = [ "cachy" ]
[tool.poetry.dev-dependencies]
[[package]]
description = ""
category = "main"
name = "pendulum"
optional = false
platform = "*"
python-versions = "*"
version = "1.4.4"
[[package]]
category = "main"
description = ""
name = "project-with-extras"
optional = false
platform = "*"
python-versions = "*"
version = "1.2.3"
[package.dependencies]
pendulum = ">=1.4.4"
[package.source]
reference = ""
type = "directory"
url = "tests/fixtures/project_with_extras"
[metadata]
content-hash = "123456789"
platform = "*"
python-versions = "*"
[metadata.hashes]
project-with-extras = []
pendulum = []
...@@ -609,7 +609,26 @@ def test_run_installs_with_local_file(installer, locker, repo, package): ...@@ -609,7 +609,26 @@ def test_run_installs_with_local_file(installer, locker, repo, package):
assert len(installer.installer.installs) == 2 assert len(installer.installer.installs) == 2
def test_run_installs_with_local_directory(installer, locker, repo, package): def test_run_installs_with_local_poetry_directory_and_extras(
installer, locker, repo, package, tmpdir
):
file_path = Path("tests/fixtures/project_with_extras/")
package.add_dependency("demo", {"path": str(file_path), "extras": ["extras_a"]})
repo.add_package(get_package("pendulum", "1.4.4"))
installer.run()
expected = fixture("with-directory-dependency-poetry")
assert locker.written_data == expected
assert len(installer.installer.installs) == 2
def test_run_installs_with_local_setuptools_directory(
installer, locker, repo, package, tmpdir
):
file_path = Path("tests/fixtures/project_with_setup/") file_path = Path("tests/fixtures/project_with_setup/")
package.add_dependency("demo", {"path": str(file_path)}) package.add_dependency("demo", {"path": str(file_path)})
...@@ -618,7 +637,7 @@ def test_run_installs_with_local_directory(installer, locker, repo, package): ...@@ -618,7 +637,7 @@ def test_run_installs_with_local_directory(installer, locker, repo, package):
installer.run() installer.run()
expected = fixture("with-directory-dependency") expected = fixture("with-directory-dependency-setuptools")
assert locker.written_data == expected assert locker.written_data == expected
......
...@@ -47,8 +47,7 @@ def test_wheel_c_extension(): ...@@ -47,8 +47,7 @@ def test_wheel_c_extension():
assert sdist.exists() assert sdist.exists()
tar = tarfile.open(str(sdist), "r") with tarfile.open(str(sdist), "r") as tar:
assert "extended-0.1/build.py" in tar.getnames() assert "extended-0.1/build.py" in tar.getnames()
assert "extended-0.1/extended/extended.c" in tar.getnames() assert "extended-0.1/extended/extended.c" in tar.getnames()
...@@ -167,8 +166,7 @@ def test_module_src(): ...@@ -167,8 +166,7 @@ def test_module_src():
assert sdist.exists() assert sdist.exists()
tar = tarfile.open(str(sdist), "r") with tarfile.open(str(sdist), "r") as tar:
assert "module-src-0.1/src/module_src.py" in tar.getnames() 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" whl = module_path / "dist" / "module_src-0.1-py2.py3-none-any.whl"
...@@ -192,8 +190,7 @@ def test_package_src(): ...@@ -192,8 +190,7 @@ def test_package_src():
assert sdist.exists() assert sdist.exists()
tar = tarfile.open(str(sdist), "r") with tarfile.open(str(sdist), "r") as tar:
assert "package-src-0.1/src/package_src/module.py" in tar.getnames() 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" whl = module_path / "dist" / "package_src-0.1-py2.py3-none-any.whl"
......
...@@ -239,8 +239,7 @@ def test_package(): ...@@ -239,8 +239,7 @@ def test_package():
assert sdist.exists() assert sdist.exists()
tar = tarfile.open(str(sdist), "r") with tarfile.open(str(sdist), "r") as tar:
assert "my-package-1.2.3/LICENSE" in tar.getnames() assert "my-package-1.2.3/LICENSE" in tar.getnames()
...@@ -254,8 +253,7 @@ def test_module(): ...@@ -254,8 +253,7 @@ def test_module():
assert sdist.exists() assert sdist.exists()
tar = tarfile.open(str(sdist), "r") with tarfile.open(str(sdist), "r") as tar:
assert "module1-0.1/module1.py" in tar.getnames() assert "module1-0.1/module1.py" in tar.getnames()
...@@ -280,8 +278,7 @@ def test_with_c_extensions(): ...@@ -280,8 +278,7 @@ def test_with_c_extensions():
assert sdist.exists() assert sdist.exists()
tar = tarfile.open(str(sdist), "r") with tarfile.open(str(sdist), "r") as tar:
assert "extended-0.1/build.py" in tar.getnames() assert "extended-0.1/build.py" in tar.getnames()
assert "extended-0.1/extended/extended.c" in tar.getnames() assert "extended-0.1/extended/extended.c" in tar.getnames()
...@@ -307,8 +304,7 @@ def test_with_src_module_file(): ...@@ -307,8 +304,7 @@ def test_with_src_module_file():
assert sdist.exists() assert sdist.exists()
tar = tarfile.open(str(sdist), "r") with tarfile.open(str(sdist), "r") as tar:
assert "module-src-0.1/src/module_src.py" in tar.getnames() assert "module-src-0.1/src/module_src.py" in tar.getnames()
...@@ -333,8 +329,7 @@ def test_with_src_module_dir(): ...@@ -333,8 +329,7 @@ def test_with_src_module_dir():
assert sdist.exists() assert sdist.exists()
tar = tarfile.open(str(sdist), "r") 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/__init__.py" in tar.getnames()
assert "package-src-0.1/src/package_src/module.py" in tar.getnames() assert "package-src-0.1/src/package_src/module.py" in tar.getnames()
...@@ -380,8 +375,7 @@ def test_package_with_include(mocker): ...@@ -380,8 +375,7 @@ def test_package_with_include(mocker):
assert sdist.exists() assert sdist.exists()
tar = tarfile.open(str(sdist), "r") with tarfile.open(str(sdist), "r") as tar:
names = tar.getnames() names = tar.getnames()
assert "with-include-1.2.3/LICENSE" in 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/README.rst" in names
......
...@@ -35,8 +35,7 @@ def test_wheel_module(): ...@@ -35,8 +35,7 @@ def test_wheel_module():
assert whl.exists() assert whl.exists()
z = zipfile.ZipFile(str(whl)) with zipfile.ZipFile(str(whl)) as z:
assert "module1.py" in z.namelist() assert "module1.py" in z.namelist()
...@@ -48,8 +47,7 @@ def test_wheel_package(): ...@@ -48,8 +47,7 @@ def test_wheel_package():
assert whl.exists() assert whl.exists()
z = zipfile.ZipFile(str(whl)) with zipfile.ZipFile(str(whl)) as z:
assert "my_package/sub_pkg1/__init__.py" in z.namelist() assert "my_package/sub_pkg1/__init__.py" in z.namelist()
...@@ -70,8 +68,7 @@ def test_wheel_package_src(): ...@@ -70,8 +68,7 @@ def test_wheel_package_src():
assert whl.exists() assert whl.exists()
z = zipfile.ZipFile(str(whl)) with zipfile.ZipFile(str(whl)) as z:
assert "package_src/__init__.py" in z.namelist() assert "package_src/__init__.py" in z.namelist()
assert "package_src/module.py" in z.namelist() assert "package_src/module.py" in z.namelist()
...@@ -84,6 +81,44 @@ def test_wheel_module_src(): ...@@ -84,6 +81,44 @@ def test_wheel_module_src():
assert whl.exists() assert whl.exists()
z = zipfile.ZipFile(str(whl)) with zipfile.ZipFile(str(whl)) as z:
assert "module_src.py" in z.namelist() assert "module_src.py" in z.namelist()
def test_package_with_include(mocker):
# 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"
),
]
module_path = fixtures_dir / "with-include"
WheelBuilder.make(Poetry.create(str(module_path)), NullVenv(), NullIO())
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 "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 "my_module.py" in names
assert "notes.txt" in names
assert "package_with_include/__init__.py" in names
{
"info": {
"author": "Timothy Crosley",
"author_email": "timothy.crosley@gmail.com",
"bugtrack_url": null,
"classifiers": [
"Development Status :: 6 - Mature",
"Environment :: Console",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Natural Language :: English",
"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",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Software Development :: Libraries",
"Topic :: Utilities"
],
"description": "",
"description_content_type": null,
"docs_url": null,
"download_url": "",
"downloads": {
"last_day": -1,
"last_month": -1,
"last_week": -1
},
"home_page": "https://github.com/timothycrosley/isort",
"keywords": "Refactor",
"license": "MIT",
"maintainer": "",
"maintainer_email": "",
"name": "isort",
"package_url": "https://pypi.org/project/isort/",
"platform": "",
"project_url": "https://pypi.org/project/isort/",
"project_urls": {
"Homepage": "https://github.com/timothycrosley/isort"
},
"release_url": "https://pypi.org/project/isort/4.3.4/",
"requires_dist": null,
"requires_python": "",
"summary": "A Python utility / library to sort Python imports.",
"version": "4.3.4"
},
"last_serial": 3575149,
"releases": {
"4.3.4": [
{
"comment_text": "",
"digests": {
"md5": "f0ad7704b6dc947073398ba290c3517f",
"sha256": "ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497"
},
"downloads": -1,
"filename": "isort-4.3.4-py2-none-any.whl",
"has_sig": false,
"md5_digest": "f0ad7704b6dc947073398ba290c3517f",
"packagetype": "bdist_wheel",
"python_version": "2.7",
"requires_python": null,
"size": 45393,
"upload_time": "2018-02-12T15:06:38",
"url": "https://files.pythonhosted.org/packages/41/d8/a945da414f2adc1d9e2f7d6e7445b27f2be42766879062a2e63616ad4199/isort-4.3.4-py2-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "fbaac4cd669ac21ea9e21ab1ea3180db",
"sha256": "1153601da39a25b14ddc54955dbbacbb6b2d19135386699e2ad58517953b34af"
},
"downloads": -1,
"filename": "isort-4.3.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "fbaac4cd669ac21ea9e21ab1ea3180db",
"packagetype": "bdist_wheel",
"python_version": "3.6",
"requires_python": null,
"size": 45352,
"upload_time": "2018-02-12T15:06:20",
"url": "https://files.pythonhosted.org/packages/1f/2c/22eee714d7199ae0464beda6ad5fedec8fee6a2f7ffd1e8f1840928fe318/isort-4.3.4-py3-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "fb554e9c8f9aa76e333a03d470a5cf52",
"sha256": "b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8"
},
"downloads": -1,
"filename": "isort-4.3.4.tar.gz",
"has_sig": false,
"md5_digest": "fb554e9c8f9aa76e333a03d470a5cf52",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 56070,
"upload_time": "2018-02-12T15:06:16",
"url": "https://files.pythonhosted.org/packages/b1/de/a628d16fdba0d38cafb3d7e34d4830f2c9cb3881384ce5c08c44762e1846/isort-4.3.4.tar.gz"
}
]
},
"urls": [
{
"comment_text": "",
"digests": {
"md5": "f0ad7704b6dc947073398ba290c3517f",
"sha256": "ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497"
},
"downloads": -1,
"filename": "isort-4.3.4-py2-none-any.whl",
"has_sig": false,
"md5_digest": "f0ad7704b6dc947073398ba290c3517f",
"packagetype": "bdist_wheel",
"python_version": "2.7",
"requires_python": null,
"size": 45393,
"upload_time": "2018-02-12T15:06:38",
"url": "https://files.pythonhosted.org/packages/41/d8/a945da414f2adc1d9e2f7d6e7445b27f2be42766879062a2e63616ad4199/isort-4.3.4-py2-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "fbaac4cd669ac21ea9e21ab1ea3180db",
"sha256": "1153601da39a25b14ddc54955dbbacbb6b2d19135386699e2ad58517953b34af"
},
"downloads": -1,
"filename": "isort-4.3.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "fbaac4cd669ac21ea9e21ab1ea3180db",
"packagetype": "bdist_wheel",
"python_version": "3.6",
"requires_python": null,
"size": 45352,
"upload_time": "2018-02-12T15:06:20",
"url": "https://files.pythonhosted.org/packages/1f/2c/22eee714d7199ae0464beda6ad5fedec8fee6a2f7ffd1e8f1840928fe318/isort-4.3.4-py3-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "fb554e9c8f9aa76e333a03d470a5cf52",
"sha256": "b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8"
},
"downloads": -1,
"filename": "isort-4.3.4.tar.gz",
"has_sig": false,
"md5_digest": "fb554e9c8f9aa76e333a03d470a5cf52",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 56070,
"upload_time": "2018-02-12T15:06:16",
"url": "https://files.pythonhosted.org/packages/b1/de/a628d16fdba0d38cafb3d7e34d4830f2c9cb3881384ce5c08c44762e1846/isort-4.3.4.tar.gz"
}
]
}
{
"info": {
"author": "Jupyter Development Team",
"author_email": "jupyter@googlegroups.org",
"bugtrack_url": null,
"classifiers": [
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
"Intended Audience :: System Administrators",
"License :: OSI Approved :: BSD License",
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4"
],
"description": "Install the Jupyter system, including the notebook, qtconsole, and the IPython kernel.",
"description_content_type": null,
"docs_url": null,
"download_url": "UNKNOWN",
"downloads": {
"last_day": -1,
"last_month": -1,
"last_week": -1
},
"home_page": "http://jupyter.org",
"keywords": null,
"license": "BSD",
"maintainer": null,
"maintainer_email": null,
"name": "jupyter",
"package_url": "https://pypi.org/project/jupyter/",
"platform": "UNKNOWN",
"project_url": "https://pypi.org/project/jupyter/",
"project_urls": {
"Download": "UNKNOWN",
"Homepage": "http://jupyter.org"
},
"release_url": "https://pypi.org/project/jupyter/1.0.0/",
"requires_dist": null,
"requires_python": null,
"summary": "Jupyter metapackage. Install all the Jupyter components in one go.",
"version": "1.0.0"
},
"last_serial": 1673841,
"releases": {
"0.0.0": [],
"1.0.0": [
{
"comment_text": "",
"digests": {
"md5": "f81d039e084c2c0c4da9e4a86446b863",
"sha256": "5b290f93b98ffbc21c0c7e749f054b3267782166d72fa5e3ed1ed4eaf34a2b78"
},
"downloads": -1,
"filename": "jupyter-1.0.0-py2.py3-none-any.whl",
"has_sig": false,
"md5_digest": "f81d039e084c2c0c4da9e4a86446b863",
"packagetype": "bdist_wheel",
"python_version": "3.4",
"requires_python": null,
"size": 2736,
"upload_time": "2015-08-12T00:42:58",
"url": "https://files.pythonhosted.org/packages/83/df/0f5dd132200728a86190397e1ea87cd76244e42d39ec5e88efd25b2abd7e/jupyter-1.0.0-py2.py3-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "c6030444c7eb6c05a4d7b1768c72aed7",
"sha256": "d9dc4b3318f310e34c82951ea5d6683f67bed7def4b259fafbfe4f1beb1d8e5f"
},
"downloads": -1,
"filename": "jupyter-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "c6030444c7eb6c05a4d7b1768c72aed7",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 12916,
"upload_time": "2015-08-12T00:43:08",
"url": "https://files.pythonhosted.org/packages/c9/a9/371d0b8fe37dd231cf4b2cff0a9f0f25e98f3a73c3771742444be27f2944/jupyter-1.0.0.tar.gz"
},
{
"comment_text": "",
"digests": {
"md5": "25142b08e2ad7142b6f920bc8cc8dfeb",
"sha256": "3e1f86076bbb7c8c207829390305a2b1fe836d471ed54be66a3b8c41e7f46cc7"
},
"downloads": -1,
"filename": "jupyter-1.0.0.zip",
"has_sig": false,
"md5_digest": "25142b08e2ad7142b6f920bc8cc8dfeb",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 16690,
"upload_time": "2015-08-12T00:43:12",
"url": "https://files.pythonhosted.org/packages/fc/21/a372b73e3a498b41b92ed915ada7de2ad5e16631546329c03e484c3bf4e9/jupyter-1.0.0.zip"
}
]
},
"urls": [
{
"comment_text": "",
"digests": {
"md5": "f81d039e084c2c0c4da9e4a86446b863",
"sha256": "5b290f93b98ffbc21c0c7e749f054b3267782166d72fa5e3ed1ed4eaf34a2b78"
},
"downloads": -1,
"filename": "jupyter-1.0.0-py2.py3-none-any.whl",
"has_sig": false,
"md5_digest": "f81d039e084c2c0c4da9e4a86446b863",
"packagetype": "bdist_wheel",
"python_version": "3.4",
"requires_python": null,
"size": 2736,
"upload_time": "2015-08-12T00:42:58",
"url": "https://files.pythonhosted.org/packages/83/df/0f5dd132200728a86190397e1ea87cd76244e42d39ec5e88efd25b2abd7e/jupyter-1.0.0-py2.py3-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "c6030444c7eb6c05a4d7b1768c72aed7",
"sha256": "d9dc4b3318f310e34c82951ea5d6683f67bed7def4b259fafbfe4f1beb1d8e5f"
},
"downloads": -1,
"filename": "jupyter-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "c6030444c7eb6c05a4d7b1768c72aed7",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 12916,
"upload_time": "2015-08-12T00:43:08",
"url": "https://files.pythonhosted.org/packages/c9/a9/371d0b8fe37dd231cf4b2cff0a9f0f25e98f3a73c3771742444be27f2944/jupyter-1.0.0.tar.gz"
},
{
"comment_text": "",
"digests": {
"md5": "25142b08e2ad7142b6f920bc8cc8dfeb",
"sha256": "3e1f86076bbb7c8c207829390305a2b1fe836d471ed54be66a3b8c41e7f46cc7"
},
"downloads": -1,
"filename": "jupyter-1.0.0.zip",
"has_sig": false,
"md5_digest": "25142b08e2ad7142b6f920bc8cc8dfeb",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 16690,
"upload_time": "2015-08-12T00:43:12",
"url": "https://files.pythonhosted.org/packages/fc/21/a372b73e3a498b41b92ed915ada7de2ad5e16631546329c03e484c3bf4e9/jupyter-1.0.0.zip"
}
]
}
import json import json
import shutil
from poetry.repositories.pypi_repository import PyPiRepository from poetry.repositories.pypi_repository import PyPiRepository
from poetry.utils._compat import Path from poetry.utils._compat import Path
...@@ -6,11 +7,12 @@ from poetry.utils._compat import Path ...@@ -6,11 +7,12 @@ from poetry.utils._compat import Path
class MockRepository(PyPiRepository): class MockRepository(PyPiRepository):
FIXTURES = Path(__file__).parent / "fixtures" / "pypi.org" / "json" JSON_FIXTURES = Path(__file__).parent / "fixtures" / "pypi.org" / "json"
DIST_FIXTURES = Path(__file__).parent / "fixtures" / "pypi.org" / "dists"
def __init__(self): def __init__(self, fallback=False):
super(MockRepository, self).__init__( super(MockRepository, self).__init__(
url="http://foo.bar", disable_cache=True, fallback=False url="http://foo.bar", disable_cache=True, fallback=fallback
) )
def _get(self, url): def _get(self, url):
...@@ -22,15 +24,22 @@ class MockRepository(PyPiRepository): ...@@ -22,15 +24,22 @@ class MockRepository(PyPiRepository):
version = None version = None
if not version: if not version:
fixture = self.FIXTURES / (name + ".json") fixture = self.JSON_FIXTURES / (name + ".json")
else: else:
fixture = self.FIXTURES / name / (version + ".json") fixture = self.JSON_FIXTURES / name / (version + ".json")
if not fixture.exists(): if not fixture.exists():
fixture = self.FIXTURES / (name + ".json") fixture = self.JSON_FIXTURES / (name + ".json")
with fixture.open() as f: with fixture.open() as f:
return json.loads(f.read()) return json.loads(f.read())
def _download(self, url, dest):
filename = url.split("/")[-1]
fixture = self.DIST_FIXTURES / filename
shutil.copyfile(str(fixture), dest)
def test_find_packages(): def test_find_packages():
repo = MockRepository() repo = MockRepository()
...@@ -60,3 +69,35 @@ def test_package(): ...@@ -60,3 +69,35 @@ def test_package():
assert win_inet.name == "win-inet-pton" assert win_inet.name == "win-inet-pton"
assert win_inet.python_versions == "~2.7 || ~2.6" assert win_inet.python_versions == "~2.7 || ~2.6"
assert win_inet.platform == "win32" assert win_inet.platform == "win32"
def test_fallback_on_downloading_packages():
repo = MockRepository(fallback=True)
package = repo.package("jupyter", "1.0.0")
assert package.name == "jupyter"
assert len(package.requires) == 6
dependency_names = sorted([dep.name for dep in package.requires])
assert dependency_names == [
"ipykernel",
"ipywidgets",
"jupyter-console",
"nbconvert",
"notebook",
"qtconsole",
]
def test_fallback_inspects_sdist_first_if_no_matching_wheels_can_be_found():
repo = MockRepository(fallback=True)
package = repo.package("isort", "4.3.4")
assert package.name == "isort"
assert len(package.requires) == 1
dep = package.requires[0]
assert dep.name == "futures"
assert dep.python_versions == "~2.7"
...@@ -22,7 +22,7 @@ from poetry.semver import VersionUnion ...@@ -22,7 +22,7 @@ from poetry.semver import VersionUnion
("=1.2.3", Version(1, 2, 3)), ("=1.2.3", Version(1, 2, 3)),
("1.2.3", Version(1, 2, 3)), ("1.2.3", Version(1, 2, 3)),
("=1.0", Version(1, 0, 0)), ("=1.0", Version(1, 0, 0)),
("1.2.3b5", Version(1, 2, 3, "b5")), ("1.2.3b5", Version(1, 2, 3, pre="b5")),
(">= 1.2.3", VersionRange(min=Version(1, 2, 3), include_min=True)), (">= 1.2.3", VersionRange(min=Version(1, 2, 3), include_min=True)),
(">dev", VersionRange(min=Version(0, 0, pre="dev"))), # Issue 206 (">dev", VersionRange(min=Version(0, 0, pre="dev"))), # Issue 206
], ],
...@@ -59,8 +59,11 @@ def test_parse_constraint_wildcard(input, constraint): ...@@ -59,8 +59,11 @@ def test_parse_constraint_wildcard(input, constraint):
("~1.0.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", 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.3", VersionRange(Version(1, 2, 3), Version(1, 3, 0), True)),
("~1.2-beta", VersionRange(Version(1, 2, 0, "beta"), Version(1, 3, 0), True)), (
("~1.2-b2", VersionRange(Version(1, 2, 0, "b2"), 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)), ("~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(3, 6, 0), True)),
("~=3.5", VersionRange(Version(3, 5, 0), Version(4, 0, 0), True)), # PEP 440 ("~=3.5", VersionRange(Version(3, 5, 0), Version(4, 0, 0), True)), # PEP 440
...@@ -80,7 +83,7 @@ def test_parse_constraint_tilde(input, constraint): ...@@ -80,7 +83,7 @@ def test_parse_constraint_tilde(input, constraint):
("^1.2", VersionRange(Version(1, 2, 0), Version(2, 0, 0), True)), ("^1.2", VersionRange(Version(1, 2, 0), Version(2, 0, 0), True)),
( (
"^1.2.3-beta.2", "^1.2.3-beta.2",
VersionRange(Version(1, 2, 3, "beta.2"), Version(2, 0, 0), True), 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)), ("^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.3", VersionRange(Version(0, 2, 3), Version(0, 3, 0), True)),
...@@ -173,3 +176,21 @@ def test_parse_constraints_negative_wildcard(input, constraint): ...@@ -173,3 +176,21 @@ def test_parse_constraints_negative_wildcard(input, constraint):
) )
def test_constraints_keep_version_precision(input, expected): def test_constraints_keep_version_precision(input, expected):
assert str(parse_constraint(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_
...@@ -11,18 +11,18 @@ from poetry.semver import VersionRange ...@@ -11,18 +11,18 @@ from poetry.semver import VersionRange
("1.0.0", Version(1, 0, 0)), ("1.0.0", Version(1, 0, 0)),
("1", Version(1, 0, 0)), ("1", Version(1, 0, 0)),
("1.0", Version(1, 0, 0)), ("1.0", Version(1, 0, 0)),
("1b1", Version(1, 0, 0, "beta1")), ("1b1", Version(1, 0, 0, pre="beta1")),
("1.0b1", Version(1, 0, 0, "beta1")), ("1.0b1", Version(1, 0, 0, pre="beta1")),
("1.0.0b1", Version(1, 0, 0, "beta1")), ("1.0.0b1", Version(1, 0, 0, pre="beta1")),
("1.0.0-b1", Version(1, 0, 0, "beta1")), ("1.0.0-b1", Version(1, 0, 0, pre="beta1")),
("1.0.0-beta.1", Version(1, 0, 0, "beta1")), ("1.0.0-beta.1", Version(1, 0, 0, pre="beta1")),
("1.0.0+1", Version(1, 0, 0, None, "1")), ("1.0.0+1", Version(1, 0, 0, build="1")),
("1.0.0-1", Version(1, 0, 0, None, "1")), ("1.0.0-1", Version(1, 0, 0, build="1")),
("1.0.0.0", Version(1, 0, 0)), ("1.0.0.0", Version(1, 0, 0)),
("1.0.0-post", Version(1, 0, 0)), ("1.0.0-post", Version(1, 0, 0)),
("1.0.0-post1", Version(1, 0, 0, None, "1")), ("1.0.0-post1", Version(1, 0, 0, build="1")),
("0.6c", Version(0, 6, 0, "rc0")), ("0.6c", Version(0, 6, 0, pre="rc0")),
("0.6pre", Version(0, 6, 0, "rc0")), ("0.6pre", Version(0, 6, 0, pre="rc0")),
], ],
) )
def test_parse_valid(input, version): def test_parse_valid(input, version):
......
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