From 26509f99135f04f7dad171fee6edda1cf4b037d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Eustace?= Date: Thu, 4 Feb 2021 22:34:06 +0100 Subject: [PATCH] Reorganize imports to improve performance --- poetry/core/factory.py | 23 +- poetry/core/json/__init__.py | 4 +- poetry/core/masonry/__init__.py | 2 - poetry/core/masonry/builder.py | 22 +- poetry/core/masonry/builders/__init__.py | 2 - poetry/core/masonry/builders/builder.py | 13 +- poetry/core/masonry/builders/sdist.py | 9 +- poetry/core/masonry/builders/wheel.py | 2 +- poetry/core/masonry/metadata.py | 8 +- poetry/core/masonry/utils/module.py | 10 +- poetry/core/packages/__init__.py | 227 --------------- poetry/core/packages/dependency.py | 262 ++++++++++++++++-- poetry/core/packages/directory_dependency.py | 4 +- poetry/core/packages/package.py | 52 ++-- poetry/core/packages/project_package.py | 30 +- poetry/core/packages/specification.py | 4 +- poetry/core/packages/types.py | 14 + poetry/core/packages/utils/link.py | 16 +- poetry/core/packages/utils/utils.py | 52 ++-- poetry/core/packages/vcs_dependency.py | 4 +- poetry/core/poetry.py | 7 +- poetry/core/pyproject/__init__.py | 6 - poetry/core/pyproject/tables.py | 8 +- poetry/core/pyproject/toml.py | 43 ++- poetry/core/semver/__init__.py | 151 ---------- poetry/core/semver/helpers.py | 162 +++++++++++ poetry/core/semver/version_constraint.py | 2 +- poetry/core/spdx/__init__.py | 57 ---- poetry/core/spdx/helpers.py | 66 +++++ poetry/core/toml/file.py | 7 +- poetry/core/version/grammars/parser.py | 26 ++ poetry/core/version/helpers.py | 8 +- poetry/core/version/markers.py | 23 +- poetry/core/version/requirements.py | 29 +- tests/masonry/builders/test_complete.py | 2 +- tests/masonry/builders/test_sdist.py | 2 +- tests/packages/test_dependency.py | 9 +- tests/packages/test_directory_dependency.py | 6 +- tests/packages/test_file_dependency.py | 11 +- tests/packages/test_main.py | 46 +-- tests/packages/test_package.py | 2 +- tests/packages/test_url_dependency.py | 2 +- tests/packages/utils/test_utils.py | 2 +- tests/packages/utils/test_utils_link.py | 2 +- tests/packages/utils/test_utils_urls.py | 6 +- tests/pyproject/test_pyproject_toml.py | 4 +- .../semver/{test_main.py => test_helpers.py} | 8 +- tests/semver/test_parse_constraint.py | 8 +- tests/semver/test_version.py | 6 +- tests/semver/test_version_range.py | 6 +- tests/spdx/{test_main.py => test_helpers.py} | 2 +- tests/spdx/test_license.py | 2 +- tests/version/test_requirements.py | 2 +- 53 files changed, 763 insertions(+), 720 deletions(-) create mode 100644 poetry/core/packages/types.py create mode 100644 poetry/core/semver/helpers.py create mode 100644 poetry/core/spdx/helpers.py create mode 100644 poetry/core/version/grammars/parser.py rename tests/semver/{test_main.py => test_helpers.py} (96%) rename tests/spdx/{test_main.py => test_helpers.py} (96%) diff --git a/poetry/core/factory.py b/poetry/core/factory.py index 59d95a1c3..e670bdad9 100644 --- a/poetry/core/factory.py +++ b/poetry/core/factory.py @@ -4,6 +4,7 @@ import logging from pathlib import Path +from typing import TYPE_CHECKING from typing import Any from typing import Dict from typing import List @@ -11,13 +12,10 @@ from typing import Union from warnings import warn -from .json import validate_object -from .packages.dependency import Dependency -from .packages.project_package import ProjectPackage -from .poetry import Poetry -from .pyproject import PyProjectTOML -from .spdx import license_by_id +if TYPE_CHECKING: + from .packages.types import DependencyTypes + from .poetry import Poetry logger = logging.getLogger(__name__) @@ -29,7 +27,13 @@ class Factory(object): def create_poetry( self, cwd: Optional[Path] = None, with_dev: bool = True - ) -> Poetry: + ) -> "Poetry": + from .packages.dependency import Dependency + from .packages.project_package import ProjectPackage + from .poetry import Poetry + from .pyproject.toml import PyProjectTOML + from .spdx.helpers import license_by_id + poetry_file = self.locate(cwd) local_config = PyProjectTOML(path=poetry_file).poetry_config @@ -168,8 +172,9 @@ def create_dependency( constraint: Union[str, Dict[str, Any]], category: str = "main", root_dir: Optional[Path] = None, - ) -> Dependency: + ) -> "DependencyTypes": from .packages.constraints import parse_constraint as parse_generic_constraint + from .packages.dependency import Dependency from .packages.directory_dependency import DirectoryDependency from .packages.file_dependency import FileDependency from .packages.url_dependency import URLDependency @@ -307,6 +312,8 @@ def validate(cls, config: dict, strict: bool = False) -> Dict[str, List[str]]: """ Checks the validity of a configuration """ + from .json import validate_object + result = {"errors": [], "warnings": []} # Schema validation errors validation_errors = validate_object(config, "poetry-schema") diff --git a/poetry/core/json/__init__.py b/poetry/core/json/__init__.py index 53b240f00..b01bfe95e 100644 --- a/poetry/core/json/__init__.py +++ b/poetry/core/json/__init__.py @@ -4,8 +4,6 @@ from io import open from typing import List -from jsonschema import Draft7Validator - SCHEMA_DIR = os.path.join(os.path.dirname(__file__), "schemas") @@ -24,6 +22,8 @@ def validate_object(obj: dict, schema_name: str) -> List[str]: with open(schema, encoding="utf-8") as f: schema = json.loads(f.read()) + from jsonschema import Draft7Validator + validator = Draft7Validator(schema) validation_errors = sorted(validator.iter_errors(obj), key=lambda e: e.path) diff --git a/poetry/core/masonry/__init__.py b/poetry/core/masonry/__init__.py index ddd3a14f1..943204ad1 100644 --- a/poetry/core/masonry/__init__.py +++ b/poetry/core/masonry/__init__.py @@ -6,5 +6,3 @@ `flit `__ and adapted to work with the poetry codebase, so kudos to them for showing the way. """ - -from .builder import Builder diff --git a/poetry/core/masonry/builder.py b/poetry/core/masonry/builder.py index c050548b0..d896e7bf7 100644 --- a/poetry/core/masonry/builder.py +++ b/poetry/core/masonry/builder.py @@ -3,28 +3,28 @@ from typing import Optional from typing import Union -from .builders.sdist import SdistBuilder -from .builders.wheel import WheelBuilder - if TYPE_CHECKING: from poetry.core.poetry import Poetry # noqa class Builder: - _FORMATS = { - "sdist": SdistBuilder, - "wheel": WheelBuilder, - } - def __init__(self, poetry: "Poetry") -> None: + from .builders.sdist import SdistBuilder + from .builders.wheel import WheelBuilder + self._poetry = poetry + self._formats = { + "sdist": SdistBuilder, + "wheel": WheelBuilder, + } + def build(self, fmt: str, executable: Optional[Union[str, Path]] = None) -> None: - if fmt in self._FORMATS: - builders = [self._FORMATS[fmt]] + if fmt in self._formats: + builders = [self._formats[fmt]] elif fmt == "all": - builders = self._FORMATS.values() + builders = self._formats.values() else: raise ValueError("Invalid format: {}".format(fmt)) diff --git a/poetry/core/masonry/builders/__init__.py b/poetry/core/masonry/builders/__init__.py index 20d725b77..e69de29bb 100644 --- a/poetry/core/masonry/builders/__init__.py +++ b/poetry/core/masonry/builders/__init__.py @@ -1,2 +0,0 @@ -from .sdist import SdistBuilder -from .wheel import WheelBuilder diff --git a/poetry/core/masonry/builders/builder.py b/poetry/core/masonry/builders/builder.py index c50b5a157..04f12252c 100644 --- a/poetry/core/masonry/builders/builder.py +++ b/poetry/core/masonry/builders/builder.py @@ -16,12 +16,6 @@ from typing import Set from typing import Union -from poetry.core.vcs import get_vcs - -from ..metadata import Metadata -from ..utils.module import Module -from ..utils.package_include import PackageInclude - if TYPE_CHECKING: from poetry.core.poetry import Poetry # noqa @@ -48,6 +42,9 @@ def __init__( ignore_packages_formats: bool = False, executable: Optional[Union[Path, str]] = None, ) -> None: + from poetry.core.masonry.metadata import Metadata + from poetry.core.masonry.utils.module import Module + self._poetry = poetry self._package = poetry.package self._path = poetry.file.parent @@ -102,6 +99,8 @@ def build(self) -> None: def find_excluded_files(self) -> Set[str]: if self._excluded_files is None: + from poetry.core.vcs import get_vcs + # Checking VCS vcs = get_vcs(self._path) if not vcs: @@ -154,6 +153,8 @@ def find_files_to_add(self, exclude_build: bool = True) -> Set["BuildIncludeFile """ Finds all files to add to the tarball """ + from poetry.core.masonry.utils.package_include import PackageInclude + to_add = set() for include in self._module.includes: diff --git a/poetry/core/masonry/builders/sdist.py b/poetry/core/masonry/builders/sdist.py index ac8f6624a..add8dcd27 100644 --- a/poetry/core/masonry/builders/sdist.py +++ b/poetry/core/masonry/builders/sdist.py @@ -21,13 +21,12 @@ from typing import Set from typing import Tuple -from ..utils.helpers import normalize_file_permissions -from ..utils.package_include import PackageInclude from .builder import Builder from .builder import BuildIncludeFile if TYPE_CHECKING: + from poetry.core.masonry.utils.package_include import PackageInclude # noqa from poetry.core.packages import Dependency # noqa from poetry.core.packages import ProjectPackage # noqa @@ -115,6 +114,8 @@ def build(self, target_dir: Optional[Path] = None) -> Path: return target def build_setup(self) -> bytes: + from poetry.core.masonry.utils.package_include import PackageInclude + before, extra, after = [], [], [] package_dir = {} @@ -225,7 +226,7 @@ def setup_py(self) -> ContextManager[Path]: def build_pkg_info(self) -> bytes: return self.get_metadata_content().encode() - def find_packages(self, include: PackageInclude) -> Tuple[str, List[str], dict]: + def find_packages(self, include: "PackageInclude") -> Tuple[str, List[str], dict]: """ Discover subpackages and data. @@ -396,6 +397,8 @@ def clean_tarinfo(cls, tar_info: TarInfo) -> TarInfo: - Normalise permissions to 644 or 755 - Set mtime if not None """ + from poetry.core.masonry.utils.helpers import normalize_file_permissions + ti = copy(tar_info) ti.uid = 0 ti.gid = 0 diff --git a/poetry/core/masonry/builders/wheel.py b/poetry/core/masonry/builders/wheel.py index ba1456fff..1f4c4af87 100644 --- a/poetry/core/masonry/builders/wheel.py +++ b/poetry/core/masonry/builders/wheel.py @@ -23,7 +23,7 @@ from packaging.tags import sys_tags from poetry.core import __version__ -from poetry.core.semver import parse_constraint +from poetry.core.semver.helpers import parse_constraint from ..utils.helpers import escape_name from ..utils.helpers import escape_version diff --git a/poetry/core/masonry/metadata.py b/poetry/core/masonry/metadata.py index 31a3428e8..ebdf93f43 100644 --- a/poetry/core/masonry/metadata.py +++ b/poetry/core/masonry/metadata.py @@ -1,9 +1,5 @@ from typing import TYPE_CHECKING -from poetry.core.utils.helpers import canonicalize_name -from poetry.core.utils.helpers import normalize_version -from poetry.core.version.helpers import format_python_constraint - if TYPE_CHECKING: from poetry.core.packages import Package # noqa @@ -46,6 +42,10 @@ class Metadata: @classmethod def from_package(cls, package: "Package") -> "Metadata": + from poetry.core.utils.helpers import canonicalize_name + from poetry.core.utils.helpers import normalize_version + from poetry.core.version.helpers import format_python_constraint + meta = cls() meta.name = canonicalize_name(package.name) diff --git a/poetry/core/masonry/utils/module.py b/poetry/core/masonry/utils/module.py index c9bf08b6c..13d7dfd38 100644 --- a/poetry/core/masonry/utils/module.py +++ b/poetry/core/masonry/utils/module.py @@ -4,11 +4,6 @@ from typing import List from typing import Optional -from poetry.core.utils.helpers import module_name - -from .include import Include -from .package_include import PackageInclude - class ModuleOrPackageNotFound(ValueError): @@ -23,6 +18,11 @@ def __init__( packages: Optional[List[Dict[str, Any]]] = None, includes: Optional[List[Dict[str, Any]]] = None, ) -> None: + from poetry.core.utils.helpers import module_name + + from .include import Include + from .package_include import PackageInclude + self._name = module_name(name) self._in_src = False self._is_package = False diff --git a/poetry/core/packages/__init__.py b/poetry/core/packages/__init__.py index 89a93913c..e69de29bb 100644 --- a/poetry/core/packages/__init__.py +++ b/poetry/core/packages/__init__.py @@ -1,227 +0,0 @@ -import os -import re - -from pathlib import Path -from typing import List -from typing import Optional -from typing import Union - -from poetry.core.semver import Version -from poetry.core.semver import parse_constraint -from poetry.core.utils.patterns import wheel_file_re -from poetry.core.version.requirements import Requirement - -from .dependency import Dependency -from .directory_dependency import DirectoryDependency -from .file_dependency import FileDependency -from .package import Package -from .project_package import ProjectPackage -from .url_dependency import URLDependency -from .utils.link import Link -from .utils.utils import convert_markers -from .utils.utils import group_markers -from .utils.utils import is_archive_file -from .utils.utils import is_installable_dir -from .utils.utils import is_url -from .utils.utils import path_to_url -from .utils.utils import strip_extras -from .utils.utils import url_to_path -from .vcs_dependency import VCSDependency - - -def _make_file_or_dir_dep( - name: str, - path: Path, - base: Optional[Path] = None, - extras: Optional[List[str]] = None, -) -> Optional[Union[FileDependency, DirectoryDependency]]: - """ - Helper function to create a file or directoru dependency with the given arguments. If - path is not a file or directory that exists, `None` is returned. - """ - _path = path - if not path.is_absolute() and base: - # a base path was specified, so we should respect that - _path = Path(base) / path - - if _path.is_file(): - return FileDependency(name, path, base=base, extras=extras) - elif _path.is_dir(): - return DirectoryDependency(name, path, base=base, extras=extras) - - return None - - -def dependency_from_pep_508( - name: str, relative_to: Optional[Path] = None -) -> Dependency: - """ - Resolve a PEP-508 requirement string to a `Dependency` instance. If a `relative_to` - path is specified, this is used as the base directory if the identified dependency is - of file or directory type. - """ - from poetry.core.vcs.git import ParsedUrl - - # Removing comments - parts = name.split("#", 1) - name = parts[0].strip() - if len(parts) > 1: - rest = parts[1] - if " ;" in rest: - name += " ;" + rest.split(" ;", 1)[1] - - req = Requirement(name) - - if req.marker: - markers = convert_markers(req.marker) - else: - markers = {} - - name = req.name - path = os.path.normpath(os.path.abspath(name)) - link = None - - if is_url(name): - link = Link(name) - elif req.url: - link = Link(req.url) - else: - p, extras = strip_extras(path) - if os.path.isdir(p) and (os.path.sep in name or name.startswith(".")): - - if not is_installable_dir(p): - raise ValueError( - "Directory {!r} is not installable. File 'setup.py' " - "not found.".format(name) - ) - link = Link(path_to_url(p)) - elif is_archive_file(p): - link = Link(path_to_url(p)) - - # it's a local file, dir, or url - if link: - is_file_uri = link.scheme == "file" - is_relative_uri = is_file_uri and re.search(r"\.\./", link.url) - - # Handle relative file URLs - if is_file_uri and is_relative_uri: - path = Path(link.path) - if relative_to: - path = relative_to / path - link = Link(path_to_url(path)) - - # wheel file - version = None - if link.is_wheel: - m = wheel_file_re.match(link.filename) - if not m: - raise ValueError("Invalid wheel name: {}".format(link.filename)) - name = m.group("name") - version = m.group("ver") - - name = req.name or link.egg_fragment - dep = None - - if link.scheme.startswith("git+"): - url = ParsedUrl.parse(link.url) - dep = VCSDependency(name, "git", url.url, rev=url.rev, extras=req.extras) - elif link.scheme == "git": - dep = VCSDependency( - name, "git", link.url_without_fragment, extras=req.extras - ) - elif link.scheme in ["http", "https"]: - dep = URLDependency(name, link.url) - elif is_file_uri: - # handle RFC 8089 references - path = url_to_path(req.url) - dep = _make_file_or_dir_dep( - name=name, path=path, base=relative_to, extras=req.extras - ) - else: - try: - # this is a local path not using the file URI scheme - dep = _make_file_or_dir_dep( - name=name, - path=Path(req.url), - base=relative_to, - extras=req.extras, - ) - except ValueError: - pass - - if dep is None: - dep = Dependency(name, version or "*", extras=req.extras) - - if version: - dep._constraint = parse_constraint(version) - else: - if req.pretty_constraint: - constraint = req.constraint - else: - constraint = "*" - - dep = Dependency(name, constraint, extras=req.extras) - - if "extra" in markers: - # If we have extras, the dependency is optional - dep.deactivate() - - for or_ in markers["extra"]: - for _, extra in or_: - dep.in_extras.append(extra) - - if "python_version" in markers: - ors = [] - for or_ in markers["python_version"]: - ands = [] - for op, version in or_: - # Expand python version - if op == "==" and "*" not in version: - version = "~" + version - op = "" - elif op == "!=": - version += ".*" - elif op in ("<=", ">"): - parsed_version = Version.parse(version) - if parsed_version.precision == 1: - if op == "<=": - op = "<" - version = parsed_version.next_major.text - elif op == ">": - op = ">=" - version = parsed_version.next_major.text - elif parsed_version.precision == 2: - if op == "<=": - op = "<" - version = parsed_version.next_minor.text - elif op == ">": - op = ">=" - version = parsed_version.next_minor.text - elif op in ("in", "not in"): - versions = [] - for v in re.split("[ ,]+", version): - split = v.split(".") - if len(split) in [1, 2]: - split.append("*") - op_ = "" if op == "in" else "!=" - else: - op_ = "==" if op == "in" else "!=" - - versions.append(op_ + ".".join(split)) - - glue = " || " if op == "in" else ", " - if versions: - ands.append(glue.join(versions)) - - continue - - ands.append("{}{}".format(op, version)) - - ors.append(" ".join(ands)) - - dep.python_versions = " || ".join(ors) - - if req.marker: - dep.marker = req.marker - - return dep diff --git a/poetry/core/packages/dependency.py b/poetry/core/packages/dependency.py index 7f81c57dd..75a89da16 100644 --- a/poetry/core/packages/dependency.py +++ b/poetry/core/packages/dependency.py @@ -1,3 +1,7 @@ +import os +import re + +from pathlib import Path from typing import TYPE_CHECKING from typing import Any from typing import FrozenSet @@ -5,35 +9,29 @@ from typing import Optional from typing import Union -from poetry.core.semver import Version -from poetry.core.semver import VersionConstraint -from poetry.core.semver import VersionRange -from poetry.core.semver import VersionUnion -from poetry.core.semver import parse_constraint -from poetry.core.version.markers import AnyMarker +from poetry.core.semver.helpers import parse_constraint from poetry.core.version.markers import parse_marker from .constraints import parse_constraint as parse_generic_constraint -from .constraints.constraint import Constraint -from .constraints.multi_constraint import MultiConstraint -from .constraints.union_constraint import UnionConstraint from .specification import PackageSpecification -from .utils.utils import convert_markers if TYPE_CHECKING: + from poetry.core.semver.helpers import VersionTypes # noqa from poetry.core.version.markers import BaseMarker # noqa - from poetry.core.version.markers import VersionTypes # noqa from .constraints import BaseConstraint # noqa + from .directory_dependency import DirectoryDependency # noqa + from .file_dependency import FileDependency # noqa from .package import Package + from .types import DependencyTypes class Dependency(PackageSpecification): def __init__( self, name: str, - constraint: Union[str, VersionConstraint], + constraint: Union[str, "VersionTypes"], optional: bool = False, category: str = "main", allows_prereleases: bool = False, @@ -43,6 +41,9 @@ def __init__( source_reference: Optional[str] = None, source_resolved_reference: Optional[str] = None, ): + from poetry.core.semver.version_range import VersionRange + from poetry.core.version.markers import AnyMarker + super(Dependency, self).__init__( name, source_type=source_type, @@ -90,6 +91,8 @@ def constraint(self) -> "VersionTypes": return self._constraint def set_constraint(self, constraint: Union[str, "VersionTypes"]) -> None: + from poetry.core.semver.version_constraint import VersionConstraint + try: if not isinstance(constraint, VersionConstraint): self._constraint = parse_constraint(constraint) @@ -171,6 +174,9 @@ def in_extras(self) -> List[str]: @property def base_pep_508_name(self) -> str: + from poetry.core.semver.version import Version + from poetry.core.semver.version_union import VersionUnion + requirement = self.pretty_name if self.extras: @@ -223,6 +229,8 @@ def accepts(self, package: "Package") -> bool: ) def to_pep_508(self, with_extras: bool = True) -> str: + from .utils.utils import convert_markers + requirement = self.base_pep_508_name markers = [] @@ -266,8 +274,15 @@ def to_pep_508(self, with_extras: bool = True) -> str: return requirement def _create_nested_marker( - self, name: str, constraint: Union["BaseConstraint", Version, VersionConstraint] + self, name: str, constraint: Union["BaseConstraint", "VersionTypes"] ) -> str: + from poetry.core.semver.version import Version + from poetry.core.semver.version_union import VersionUnion + + from .constraints.constraint import Constraint + from .constraints.multi_constraint import MultiConstraint + from .constraints.union_constraint import UnionConstraint + if isinstance(constraint, (MultiConstraint, UnionConstraint)): parts = [] for c in constraint.constraints: @@ -364,9 +379,7 @@ def deactivate(self) -> None: self._activated = False - def with_constraint( - self, constraint: Union[str, VersionConstraint] - ) -> "Dependency": + def with_constraint(self, constraint: Union[str, "VersionTypes"]) -> "Dependency": new = Dependency( self.pretty_name, constraint, @@ -387,6 +400,197 @@ def with_constraint( return new + @classmethod + def create_from_pep_508( + cls, name: str, relative_to: Optional[Path] = None + ) -> "DependencyTypes": + """ + Resolve a PEP-508 requirement string to a `Dependency` instance. If a `relative_to` + path is specified, this is used as the base directory if the identified dependency is + of file or directory type. + """ + from poetry.core.semver.version import Version + from poetry.core.utils.patterns import wheel_file_re + from poetry.core.vcs.git import ParsedUrl + from poetry.core.version.requirements import Requirement + + from .url_dependency import URLDependency + from .utils.link import Link + from .utils.utils import convert_markers + from .utils.utils import is_archive_file + from .utils.utils import is_installable_dir + from .utils.utils import is_url + from .utils.utils import path_to_url + from .utils.utils import strip_extras + from .utils.utils import url_to_path + from .vcs_dependency import VCSDependency + + # Removing comments + parts = name.split("#", 1) + name = parts[0].strip() + if len(parts) > 1: + rest = parts[1] + if " ;" in rest: + name += " ;" + rest.split(" ;", 1)[1] + + req = Requirement(name) + + if req.marker: + markers = convert_markers(req.marker) + else: + markers = {} + + name = req.name + path = os.path.normpath(os.path.abspath(name)) + link = None + + if is_url(name): + link = Link(name) + elif req.url: + link = Link(req.url) + else: + p, extras = strip_extras(path) + if os.path.isdir(p) and (os.path.sep in name or name.startswith(".")): + + if not is_installable_dir(p): + raise ValueError( + "Directory {!r} is not installable. File 'setup.py' " + "not found.".format(name) + ) + link = Link(path_to_url(p)) + elif is_archive_file(p): + link = Link(path_to_url(p)) + + # it's a local file, dir, or url + if link: + is_file_uri = link.scheme == "file" + is_relative_uri = is_file_uri and re.search(r"\.\./", link.url) + + # Handle relative file URLs + if is_file_uri and is_relative_uri: + path = Path(link.path) + if relative_to: + path = relative_to / path + link = Link(path_to_url(path)) + + # wheel file + version = None + if link.is_wheel: + m = wheel_file_re.match(link.filename) + if not m: + raise ValueError("Invalid wheel name: {}".format(link.filename)) + name = m.group("name") + version = m.group("ver") + + name = req.name or link.egg_fragment + dep = None + + if link.scheme.startswith("git+"): + url = ParsedUrl.parse(link.url) + dep = VCSDependency( + name, "git", url.url, rev=url.rev, extras=req.extras + ) + elif link.scheme == "git": + dep = VCSDependency( + name, "git", link.url_without_fragment, extras=req.extras + ) + elif link.scheme in ["http", "https"]: + dep = URLDependency(name, link.url) + elif is_file_uri: + # handle RFC 8089 references + path = url_to_path(req.url) + dep = _make_file_or_dir_dep( + name=name, path=path, base=relative_to, extras=req.extras + ) + else: + try: + # this is a local path not using the file URI scheme + dep = _make_file_or_dir_dep( + name=name, + path=Path(req.url), + base=relative_to, + extras=req.extras, + ) + except ValueError: + pass + + if dep is None: + dep = Dependency(name, version or "*", extras=req.extras) + + if version: + dep._constraint = parse_constraint(version) + else: + if req.pretty_constraint: + constraint = req.constraint + else: + constraint = "*" + + dep = Dependency(name, constraint, extras=req.extras) + + if "extra" in markers: + # If we have extras, the dependency is optional + dep.deactivate() + + for or_ in markers["extra"]: + for _, extra in or_: + dep.in_extras.append(extra) + + if "python_version" in markers: + ors = [] + for or_ in markers["python_version"]: + ands = [] + for op, version in or_: + # Expand python version + if op == "==" and "*" not in version: + version = "~" + version + op = "" + elif op == "!=": + version += ".*" + elif op in ("<=", ">"): + parsed_version = Version.parse(version) + if parsed_version.precision == 1: + if op == "<=": + op = "<" + version = parsed_version.next_major.text + elif op == ">": + op = ">=" + version = parsed_version.next_major.text + elif parsed_version.precision == 2: + if op == "<=": + op = "<" + version = parsed_version.next_minor.text + elif op == ">": + op = ">=" + version = parsed_version.next_minor.text + elif op in ("in", "not in"): + versions = [] + for v in re.split("[ ,]+", version): + split = v.split(".") + if len(split) in [1, 2]: + split.append("*") + op_ = "" if op == "in" else "!=" + else: + op_ = "==" if op == "in" else "!=" + + versions.append(op_ + ".".join(split)) + + glue = " || " if op == "in" else ", " + if versions: + ands.append(glue.join(versions)) + + continue + + ands.append("{}{}".format(op, version)) + + ors.append(" ".join(ands)) + + dep.python_versions = " || ".join(ors) + + if req.marker: + dep.marker = req.marker + + return dep + def __eq__(self, other: Any) -> bool: if not isinstance(other, Dependency): return NotImplemented @@ -414,3 +618,29 @@ def __str__(self) -> str: def __repr__(self) -> str: return "<{} {}>".format(self.__class__.__name__, str(self)) + + +def _make_file_or_dir_dep( + name: str, + path: Path, + base: Optional[Path] = None, + extras: Optional[List[str]] = None, +) -> Optional[Union["FileDependency", "DirectoryDependency"]]: + """ + Helper function to create a file or directoru dependency with the given arguments. If + path is not a file or directory that exists, `None` is returned. + """ + from .directory_dependency import DirectoryDependency + from .file_dependency import FileDependency + + _path = path + if not path.is_absolute() and base: + # a base path was specified, so we should respect that + _path = Path(base) / path + + if _path.is_file(): + return FileDependency(name, path, base=base, extras=extras) + elif _path.is_dir(): + return DirectoryDependency(name, path, base=base, extras=extras) + + return None diff --git a/poetry/core/packages/directory_dependency.py b/poetry/core/packages/directory_dependency.py index c3c59f80f..d0cbf2523 100644 --- a/poetry/core/packages/directory_dependency.py +++ b/poetry/core/packages/directory_dependency.py @@ -5,8 +5,6 @@ from typing import Optional from typing import Union -from poetry.core.pyproject import PyProjectTOML - if TYPE_CHECKING: from .constraints import BaseConstraint # noqa @@ -25,6 +23,8 @@ def __init__( develop: bool = False, extras: Optional[Union[List[str], FrozenSet[str]]] = None, ) -> None: + from poetry.core.pyproject.toml import PyProjectTOML + self._path = path self._base = base or Path.cwd() self._full_path = path diff --git a/poetry/core/packages/package.py b/poetry/core/packages/package.py index a57f3412d..cf972dae5 100644 --- a/poetry/core/packages/package.py +++ b/poetry/core/packages/package.py @@ -8,11 +8,7 @@ from typing import Optional from typing import Union -from poetry.core.semver import Version -from poetry.core.semver import parse_constraint -from poetry.core.spdx import License -from poetry.core.spdx import license_by_id -from poetry.core.version.markers import AnyMarker +from poetry.core.semver.helpers import parse_constraint from poetry.core.version.markers import parse_marker from .specification import PackageSpecification @@ -20,14 +16,12 @@ if TYPE_CHECKING: - from poetry.core.semver import VersionTypes # noqa + from poetry.core.semver.helpers import VersionTypes # noqa + from poetry.core.semver.version import Version # noqa + from poetry.core.spdx.license import License # noqa from poetry.core.version.markers import BaseMarker # noqa - from .dependency import Dependency - from .directory_dependency import DirectoryDependency - from .file_dependency import FileDependency - from .url_dependency import URLDependency - from .vcs_dependency import VCSDependency + from .types import DependencyTypes AUTHOR_REGEX = re.compile(r"(?u)^(?P[- .,\w\d'’\"()&]+)(?: <(?P.+?)>)?$") @@ -49,7 +43,7 @@ class Package(PackageSpecification): def __init__( self, name: str, - version: Union[str, Version], + version: Union[str, "Version"], pretty_version: Optional[str] = None, source_type: Optional[str] = None, source_url: Optional[str] = None, @@ -60,6 +54,9 @@ def __init__( """ Creates a new in memory package. """ + from poetry.core.semver.version import Version + from poetry.core.version.markers import AnyMarker + super(Package, self).__init__( name, source_type=source_type, @@ -187,15 +184,7 @@ def maintainer_email(self) -> str: @property def all_requires( self, - ) -> List[ - Union[ - "DirectoryDependency", - "FileDependency", - "URLDependency", - "VCSDependency", - "Dependency", - ] - ]: + ) -> List[Union["DependencyTypes"]]: return self.requires + self.dev_requires def _get_author(self) -> Dict[str, Optional[str]]: @@ -253,11 +242,14 @@ def python_marker(self) -> "BaseMarker": return self._python_marker @property - def license(self) -> License: + def license(self) -> "License": return self._license @license.setter - def license(self, value: Optional[Union[str, License]]) -> None: + def license(self, value: Optional[Union[str, "License"]]) -> None: + from poetry.core.spdx.helpers import license_by_id + from poetry.core.spdx.license import License # noqa + if value is None: self._license = value elif isinstance(value, License): @@ -267,6 +259,8 @@ def license(self, value: Optional[Union[str, License]]) -> None: @property def all_classifiers(self) -> List[str]: + from poetry.core.semver.version import Version # noqa + classifiers = copy.copy(self.classifiers) # Automatically set python classifiers @@ -317,8 +311,8 @@ def is_root(self) -> bool: def add_dependency( self, - dependency: "Dependency", - ) -> "Dependency": + dependency: "DependencyTypes", + ) -> "DependencyTypes": if dependency.category == "dev": self.dev_requires.append(dependency) else: @@ -328,13 +322,7 @@ def add_dependency( def to_dependency( self, - ) -> Union[ - "Dependency", - "DirectoryDependency", - "FileDependency", - "URLDependency", - "VCSDependency", - ]: + ) -> Union["DependencyTypes"]: from pathlib import Path from .dependency import Dependency diff --git a/poetry/core/packages/project_package.py b/poetry/core/packages/project_package.py index 0ab0cdc67..a1600619e 100644 --- a/poetry/core/packages/project_package.py +++ b/poetry/core/packages/project_package.py @@ -4,19 +4,13 @@ from typing import Optional from typing import Union -from poetry.core.semver import VersionRange -from poetry.core.semver import parse_constraint +from poetry.core.semver.helpers import parse_constraint from poetry.core.version.markers import parse_marker if TYPE_CHECKING: - from . import ( - DirectoryDependency, - FileDependency, - URLDependency, - VCSDependency, - Dependency, - ) + from .types import DependencyTypes + from poetry.core.semver.helpers import VersionTypes from .package import Package from .utils.utils import create_nested_marker @@ -26,7 +20,7 @@ class ProjectPackage(Package): def __init__( self, name: str, - version: Union[str, VersionRange], + version: Union[str, "VersionTypes"], pretty_version: Optional[str] = None, ) -> None: super(ProjectPackage, self).__init__(name, version, pretty_version) @@ -47,15 +41,7 @@ def build_script(self) -> Optional[str]: def is_root(self) -> bool: return True - def to_dependency( - self, - ) -> Union[ - "DirectoryDependency", - "FileDependency", - "URLDependency", - "VCSDependency", - "Dependency", - ]: + def to_dependency(self) -> Union["DependencyTypes"]: dependency = super(ProjectPackage, self).to_dependency() dependency.is_root = True @@ -63,11 +49,13 @@ def to_dependency( return dependency @property - def python_versions(self) -> Union[str, VersionRange]: + def python_versions(self) -> Union[str, "VersionTypes"]: return self._python_versions @python_versions.setter - def python_versions(self, value: Union[str, VersionRange]) -> None: + def python_versions(self, value: Union[str, "VersionTypes"]) -> None: + from poetry.core.semver.version_range import VersionRange + self._python_versions = value if value == "*" or value == VersionRange(): diff --git a/poetry/core/packages/specification.py b/poetry/core/packages/specification.py index 814626e67..3137f7f51 100644 --- a/poetry/core/packages/specification.py +++ b/poetry/core/packages/specification.py @@ -2,8 +2,6 @@ from typing import List from typing import Optional -from poetry.core.utils.helpers import canonicalize_name - class PackageSpecification(object): def __init__( @@ -15,6 +13,8 @@ def __init__( source_resolved_reference: Optional[str] = None, features: Optional[List[str]] = None, ): + from poetry.core.utils.helpers import canonicalize_name + self._pretty_name = name self._name = canonicalize_name(name) self._source_type = source_type diff --git a/poetry/core/packages/types.py b/poetry/core/packages/types.py new file mode 100644 index 000000000..5fbafc793 --- /dev/null +++ b/poetry/core/packages/types.py @@ -0,0 +1,14 @@ +from typing import TYPE_CHECKING +from typing import Union + + +if TYPE_CHECKING: + from .dependency import Dependency + from .directory_dependency import DirectoryDependency + from .file_dependency import FileDependency + from .url_dependency import URLDependency + from .vcs_dependency import VCSDependency + + DependencyTypes = Union[ + Dependency, DirectoryDependency, FileDependency, URLDependency, VCSDependency + ] diff --git a/poetry/core/packages/utils/link.py b/poetry/core/packages/utils/link.py index 9bc6ad4be..ae1319ce8 100644 --- a/poetry/core/packages/utils/link.py +++ b/poetry/core/packages/utils/link.py @@ -1,30 +1,20 @@ import posixpath import re +import urllib.parse as urlparse -from typing import TYPE_CHECKING from typing import Any from typing import Optional from typing import Tuple - -if TYPE_CHECKING: - from pip._internal.index.collector import HTMLPage # noqa - from .utils import path_to_url from .utils import splitext -try: - import urllib.parse as urlparse -except ImportError: - import urlparse - - class Link: def __init__( self, url: str, - comes_from: Optional["HTMLPage"] = None, + comes_from: Optional[Any] = None, requires_python: Optional[str] = None, ) -> None: """ @@ -99,7 +89,7 @@ def filename(self) -> str: _, netloc, path, _, _ = urlparse.urlsplit(self.url) name = posixpath.basename(path.rstrip("/")) or netloc name = urlparse.unquote(name) - assert name, "URL %r produced no filename" % self.url + return name @property diff --git a/poetry/core/packages/utils/utils.py b/poetry/core/packages/utils/utils.py index 09b50bd73..f2514b1bf 100644 --- a/poetry/core/packages/utils/utils.py +++ b/poetry/core/packages/utils/utils.py @@ -9,29 +9,20 @@ from typing import List from typing import Tuple from typing import Union - -from six.moves.urllib.parse import unquote # noqa -from six.moves.urllib.parse import urlsplit # noqa -from six.moves.urllib.request import url2pathname # noqa - -from poetry.core.packages.constraints.constraint import Constraint -from poetry.core.packages.constraints.multi_constraint import MultiConstraint -from poetry.core.packages.constraints.union_constraint import UnionConstraint -from poetry.core.semver import EmptyConstraint -from poetry.core.semver import Version -from poetry.core.semver import VersionConstraint -from poetry.core.semver import VersionRange -from poetry.core.semver import VersionUnion -from poetry.core.semver import parse_constraint -from poetry.core.version.markers import BaseMarker -from poetry.core.version.markers import MarkerUnion -from poetry.core.version.markers import MultiMarker -from poetry.core.version.markers import SingleMarker +from urllib.parse import unquote +from urllib.parse import urlsplit +from urllib.request import url2pathname if TYPE_CHECKING: from poetry.core.packages.constraints import BaseConstraint # noqa - from poetry.core.semver import VersionTypes # noqa + from poetry.core.semver.helpers import VersionTypes # noqa + from poetry.core.semver.version import Version # noqa + from poetry.core.semver.version_constraint import VersionConstraint # noqa + from poetry.core.semver.version_range import VersionRange # noqa + from poetry.core.semver.version_union import VersionUnion # noqa + from poetry.core.version.markers import BaseMarker # noqa + BZ2_EXTENSIONS = (".tar.bz2", ".tbz") XZ_EXTENSIONS = (".tar.xz", ".txz", ".tlz", ".tar.lz", ".tar.lzma") @@ -150,8 +141,12 @@ def splitext(path: str) -> Tuple[str, str]: def group_markers( - markers: List[BaseMarker], or_: bool = False + markers: List["BaseMarker"], or_: bool = False ) -> List[Union[Tuple[str, str, str], List[Tuple[str, str, str]]]]: + from poetry.core.version.markers import MarkerUnion + from poetry.core.version.markers import MultiMarker + from poetry.core.version.markers import SingleMarker + groups = [[]] for marker in markers: @@ -170,7 +165,7 @@ def group_markers( return groups -def convert_markers(marker: BaseMarker) -> Dict[str, List[Tuple[str, str]]]: +def convert_markers(marker: "BaseMarker") -> Dict[str, List[Tuple[str, str]]]: groups = group_markers([marker]) requirements = {} @@ -212,8 +207,14 @@ def _group( def create_nested_marker( name: str, - constraint: Union["BaseConstraint", VersionUnion, Version, VersionConstraint], + constraint: Union["BaseConstraint", "VersionUnion", "Version", "VersionConstraint"], ) -> str: + from poetry.core.packages.constraints.constraint import Constraint + from poetry.core.packages.constraints.multi_constraint import MultiConstraint + from poetry.core.packages.constraints.union_constraint import UnionConstraint + from poetry.core.semver.version import Version + from poetry.core.semver.version_union import VersionUnion + if constraint.is_any(): return "" @@ -281,8 +282,13 @@ def create_nested_marker( def get_python_constraint_from_marker( - marker: BaseMarker, + marker: "BaseMarker", ) -> "VersionTypes": + from poetry.core.semver.empty_constraint import EmptyConstraint + from poetry.core.semver.helpers import parse_constraint + from poetry.core.semver.version import Version + from poetry.core.semver.version_range import VersionRange # noqa + python_marker = marker.only("python_version", "python_full_version") if python_marker.is_any(): return VersionRange() diff --git a/poetry/core/packages/vcs_dependency.py b/poetry/core/packages/vcs_dependency.py index a2f87d67f..932338c16 100644 --- a/poetry/core/packages/vcs_dependency.py +++ b/poetry/core/packages/vcs_dependency.py @@ -4,8 +4,6 @@ from typing import Optional from typing import Union -from poetry.core.vcs import git - from .dependency import Dependency @@ -101,6 +99,8 @@ def pretty_constraint(self) -> str: @property def base_pep_508_name(self) -> str: + from poetry.core.vcs import git + requirement = self.pretty_name parsed_url = git.ParsedUrl.parse(self._source) diff --git a/poetry/core/poetry.py b/poetry/core/poetry.py index 372f5c2e4..ed10c25d5 100644 --- a/poetry/core/poetry.py +++ b/poetry/core/poetry.py @@ -4,13 +4,12 @@ from typing import TYPE_CHECKING from typing import Any -from poetry.core.pyproject import PyProjectTOML - if TYPE_CHECKING: from pathlib import Path from poetry.core.packages import ProjectPackage # noqa + from poetry.core.pyproject.toml import PyProjectTOML # noqa from poetry.core.pyproject.toml import PyProjectTOMLFile # noqa @@ -21,12 +20,14 @@ def __init__( local_config: dict, package: "ProjectPackage", ) -> None: + from poetry.core.pyproject.toml import PyProjectTOML # noqa + self._pyproject = PyProjectTOML(file) self._package = package self._local_config = local_config @property - def pyproject(self) -> PyProjectTOML: + def pyproject(self) -> "PyProjectTOML": return self._pyproject @property diff --git a/poetry/core/pyproject/__init__.py b/poetry/core/pyproject/__init__.py index 9f760fbe2..e69de29bb 100644 --- a/poetry/core/pyproject/__init__.py +++ b/poetry/core/pyproject/__init__.py @@ -1,6 +0,0 @@ -from poetry.core.pyproject.exceptions import PyProjectException -from poetry.core.pyproject.tables import BuildSystem -from poetry.core.pyproject.toml import PyProjectTOML - - -__all__ = [clazz.__name__ for clazz in {BuildSystem, PyProjectException, PyProjectTOML}] diff --git a/poetry/core/pyproject/tables.py b/poetry/core/pyproject/tables.py index 032295737..f8339c04f 100644 --- a/poetry/core/pyproject/tables.py +++ b/poetry/core/pyproject/tables.py @@ -27,15 +27,15 @@ def __init__( def dependencies(self) -> List["Dependency"]: if self._dependencies is None: # avoid circular dependency when loading DirectoryDependency - from poetry.core.packages import DirectoryDependency - from poetry.core.packages import FileDependency - from poetry.core.packages import dependency_from_pep_508 + from poetry.core.packages.dependency import Dependency + from poetry.core.packages.directory_dependency import DirectoryDependency + from poetry.core.packages.file_dependency import FileDependency self._dependencies = [] for requirement in self.requires: dependency = None try: - dependency = dependency_from_pep_508(requirement) + dependency = Dependency.create_from_pep_508(requirement) except ValueError: # PEP 517 requires can be path if not PEP 508 path = Path(requirement) diff --git a/poetry/core/pyproject/toml.py b/poetry/core/pyproject/toml.py index 177ca5a08..cb6dddcf0 100644 --- a/poetry/core/pyproject/toml.py +++ b/poetry/core/pyproject/toml.py @@ -1,38 +1,47 @@ from pathlib import Path +from typing import TYPE_CHECKING from typing import Any from typing import Optional from typing import Union -from tomlkit.container import Container -from tomlkit.toml_document import TOMLDocument -from poetry.core.pyproject.exceptions import PyProjectException -from poetry.core.pyproject.tables import BuildSystem -from poetry.core.toml import TOMLFile +if TYPE_CHECKING: + from tomlkit.toml_document import TOMLDocument + + from poetry.core.toml import TOMLFile + + from .tables import BuildSystem class PyProjectTOML: def __init__(self, path: Union[str, Path]) -> None: + from poetry.core.toml import TOMLFile + self._file = TOMLFile(path=path) - self._data: Optional[TOMLDocument] = None - self._build_system: Optional[BuildSystem] = None - self._poetry_config: Optional[TOMLDocument] = None + self._data: Optional["TOMLDocument"] = None + self._build_system: Optional["BuildSystem"] = None + self._poetry_config: Optional["TOMLDocument"] = None @property - def file(self) -> TOMLFile: + def file(self) -> "TOMLFile": return self._file @property - def data(self) -> TOMLDocument: + def data(self) -> "TOMLDocument": + from tomlkit.toml_document import TOMLDocument + if self._data is None: if not self._file.exists(): self._data = TOMLDocument() else: self._data = self._file.read() + return self._data @property - def build_system(self) -> BuildSystem: + def build_system(self) -> "BuildSystem": + from .tables import BuildSystem + if self._build_system is None: build_backend = None requires = None @@ -46,31 +55,40 @@ def build_system(self) -> BuildSystem: build_backend=container.get("build-backend", build_backend), requires=container.get("requires", requires), ) + return self._build_system @property - def poetry_config(self) -> Optional[TOMLDocument]: + def poetry_config(self) -> Optional["TOMLDocument"]: + from .exceptions import PyProjectException + if self._poetry_config is None: self._poetry_config = self.data.get("tool", {}).get("poetry") if self._poetry_config is None: raise PyProjectException( "[tool.poetry] section not found in {}".format(self._file) ) + return self._poetry_config def is_poetry_project(self) -> bool: + from .exceptions import PyProjectException + if self.file.exists(): try: _ = self.poetry_config return True except PyProjectException: pass + return False def __getattr__(self, item: str) -> Any: return getattr(self.data, item) def save(self) -> None: + from tomlkit.container import Container + data = self.data if self._poetry_config is not None: @@ -79,6 +97,7 @@ def save(self) -> None: if self._build_system is not None: if "build-system" not in data: data["build-system"] = Container() + data["build-system"]["requires"] = self._build_system.requires data["build-system"]["build-backend"] = self._build_system.build_backend diff --git a/poetry/core/semver/__init__.py b/poetry/core/semver/__init__.py index 8416fb647..e69de29bb 100644 --- a/poetry/core/semver/__init__.py +++ b/poetry/core/semver/__init__.py @@ -1,151 +0,0 @@ -import re - -from typing import Union - -from .empty_constraint import EmptyConstraint -from .exceptions import ParseConstraintError -from .patterns import BASIC_CONSTRAINT -from .patterns import CARET_CONSTRAINT -from .patterns import TILDE_CONSTRAINT -from .patterns import TILDE_PEP440_CONSTRAINT -from .patterns import X_CONSTRAINT -from .version import Version -from .version_constraint import VersionConstraint -from .version_range import VersionRange -from .version_union import VersionUnion - - -VersionTypes = Union[Version, VersionRange, VersionUnion, EmptyConstraint] - - -def parse_constraint(constraints: str) -> VersionTypes: - if constraints == "*": - return VersionRange() - - or_constraints = re.split(r"\s*\|\|?\s*", constraints.strip()) - or_groups = [] - for constraints in or_constraints: - and_constraints = re.split( - "(?< ,]) *(? 1: - for constraint in and_constraints: - constraint_objects.append(parse_single_constraint(constraint)) - else: - constraint_objects.append(parse_single_constraint(and_constraints[0])) - - if len(constraint_objects) == 1: - constraint = constraint_objects[0] - else: - constraint = constraint_objects[0] - for next_constraint in constraint_objects[1:]: - constraint = constraint.intersect(next_constraint) - - or_groups.append(constraint) - - if len(or_groups) == 1: - return or_groups[0] - else: - return VersionUnion.of(*or_groups) - - -def parse_single_constraint(constraint: str) -> VersionTypes: - m = re.match(r"(?i)^v?[xX*](\.[xX*])*$", constraint) - if m: - return VersionRange() - - # Tilde range - m = TILDE_CONSTRAINT.match(constraint) - if m: - version = Version.parse(m.group(1)) - - high = version.stable.next_minor - if len(m.group(1).split(".")) == 1: - high = version.stable.next_major - - return VersionRange(version, high, include_min=True) - - # PEP 440 Tilde range (~=) - m = TILDE_PEP440_CONSTRAINT.match(constraint) - if m: - precision = 1 - if m.group(3): - precision += 1 - - if m.group(4): - precision += 1 - - version = Version.parse(m.group(1)) - - if precision == 2: - high = version.stable.next_major - else: - high = version.stable.next_minor - - return VersionRange(version, high, include_min=True) - - # Caret range - m = CARET_CONSTRAINT.match(constraint) - if m: - version = Version.parse(m.group(1)) - - return VersionRange(version, version.next_breaking, include_min=True) - - # X Range - m = X_CONSTRAINT.match(constraint) - if m: - op = m.group(1) - major = int(m.group(2)) - minor = m.group(3) - - if minor is not None: - version = Version(major, int(minor), 0) - - result = VersionRange(version, version.next_minor, include_min=True) - else: - if major == 0: - result = VersionRange(max=Version(1, 0, 0)) - else: - version = Version(major, 0, 0) - - result = VersionRange(version, version.next_major, include_min=True) - - if op == "!=": - result = VersionRange().difference(result) - - return result - - # Basic comparator - m = BASIC_CONSTRAINT.match(constraint) - if m: - op = m.group(1) - version = m.group(2) - - if version == "dev": - version = "0.0-dev" - - try: - version = Version.parse(version) - except ValueError: - raise ValueError( - "Could not parse version constraint: {}".format(constraint) - ) - - if op == "<": - return VersionRange(max=version) - elif op == "<=": - return VersionRange(max=version, include_max=True) - elif op == ">": - return VersionRange(min=version) - elif op == ">=": - return VersionRange(min=version, include_min=True) - elif op == "!=": - return VersionUnion(VersionRange(max=version), VersionRange(min=version)) - else: - return version - - raise ParseConstraintError( - "Could not parse version constraint: {}".format(constraint) - ) diff --git a/poetry/core/semver/helpers.py b/poetry/core/semver/helpers.py new file mode 100644 index 000000000..e20008f2e --- /dev/null +++ b/poetry/core/semver/helpers.py @@ -0,0 +1,162 @@ +import re + +from typing import TYPE_CHECKING +from typing import Union + + +if TYPE_CHECKING: + from .empty_constraint import EmptyConstraint # noqa + from .version import Version # noqa + from .version_range import VersionRange # noqa + from .version_union import VersionUnion # noqa + + +VersionTypes = Union["Version", "VersionRange", "VersionUnion", "EmptyConstraint"] + + +def parse_constraint(constraints: str) -> VersionTypes: + if constraints == "*": + from .version_range import VersionRange + + return VersionRange() + + or_constraints = re.split(r"\s*\|\|?\s*", constraints.strip()) + or_groups = [] + for constraints in or_constraints: + and_constraints = re.split( + "(?< ,]) *(? 1: + for constraint in and_constraints: + constraint_objects.append(parse_single_constraint(constraint)) + else: + constraint_objects.append(parse_single_constraint(and_constraints[0])) + + if len(constraint_objects) == 1: + constraint = constraint_objects[0] + else: + constraint = constraint_objects[0] + for next_constraint in constraint_objects[1:]: + constraint = constraint.intersect(next_constraint) + + or_groups.append(constraint) + + if len(or_groups) == 1: + return or_groups[0] + else: + from .version_union import VersionUnion + + return VersionUnion.of(*or_groups) + + +def parse_single_constraint(constraint: str) -> VersionTypes: + from .patterns import BASIC_CONSTRAINT + from .patterns import CARET_CONSTRAINT + from .patterns import TILDE_CONSTRAINT + from .patterns import TILDE_PEP440_CONSTRAINT + from .patterns import X_CONSTRAINT + from .version import Version + from .version_range import VersionRange + from .version_union import VersionUnion + + m = re.match(r"(?i)^v?[xX*](\.[xX*])*$", constraint) + if m: + return VersionRange() + + # Tilde range + m = TILDE_CONSTRAINT.match(constraint) + if m: + version = Version.parse(m.group(1)) + + high = version.stable.next_minor + if len(m.group(1).split(".")) == 1: + high = version.stable.next_major + + return VersionRange(version, high, include_min=True) + + # PEP 440 Tilde range (~=) + m = TILDE_PEP440_CONSTRAINT.match(constraint) + if m: + precision = 1 + if m.group(3): + precision += 1 + + if m.group(4): + precision += 1 + + version = Version.parse(m.group(1)) + + if precision == 2: + high = version.stable.next_major + else: + high = version.stable.next_minor + + return VersionRange(version, high, include_min=True) + + # Caret range + m = CARET_CONSTRAINT.match(constraint) + if m: + version = Version.parse(m.group(1)) + + return VersionRange(version, version.next_breaking, include_min=True) + + # X Range + m = X_CONSTRAINT.match(constraint) + if m: + op = m.group(1) + major = int(m.group(2)) + minor = m.group(3) + + if minor is not None: + version = Version(major, int(minor), 0) + + result = VersionRange(version, version.next_minor, include_min=True) + else: + if major == 0: + result = VersionRange(max=Version(1, 0, 0)) + else: + version = Version(major, 0, 0) + + result = VersionRange(version, version.next_major, include_min=True) + + if op == "!=": + result = VersionRange().difference(result) + + return result + + # Basic comparator + m = BASIC_CONSTRAINT.match(constraint) + if m: + op = m.group(1) + version = m.group(2) + + if version == "dev": + version = "0.0-dev" + + try: + version = Version.parse(version) + except ValueError: + raise ValueError( + "Could not parse version constraint: {}".format(constraint) + ) + + if op == "<": + return VersionRange(max=version) + elif op == "<=": + return VersionRange(max=version, include_max=True) + elif op == ">": + return VersionRange(min=version) + elif op == ">=": + return VersionRange(min=version, include_min=True) + elif op == "!=": + return VersionUnion(VersionRange(max=version), VersionRange(min=version)) + else: + return version + + from .exceptions import ParseConstraintError + + raise ParseConstraintError( + "Could not parse version constraint: {}".format(constraint) + ) diff --git a/poetry/core/semver/version_constraint.py b/poetry/core/semver/version_constraint.py index 6e2cf95d6..127878779 100644 --- a/poetry/core/semver/version_constraint.py +++ b/poetry/core/semver/version_constraint.py @@ -2,7 +2,7 @@ if TYPE_CHECKING: - from poetry.core.semver import Version # noqa + from poetry.core.semver.version import Version # noqa class VersionConstraint: diff --git a/poetry/core/spdx/__init__.py b/poetry/core/spdx/__init__.py index b4c805178..e69de29bb 100644 --- a/poetry/core/spdx/__init__.py +++ b/poetry/core/spdx/__init__.py @@ -1,57 +0,0 @@ -import json -import os - -from io import open -from typing import Dict -from typing import Optional - -from .license import License -from .updater import Updater - - -_licenses: Optional[Dict[str, License]] = None - - -def license_by_id(identifier: str) -> License: - if _licenses is None: - load_licenses() - - id = identifier.lower() - - if id not in _licenses: - if not identifier: - raise ValueError("A license identifier is required") - return License(identifier, identifier, False, False) - - return _licenses[id] - - -def load_licenses() -> None: - global _licenses - - _licenses = {} - - licenses_file = os.path.join(os.path.dirname(__file__), "data", "licenses.json") - - with open(licenses_file, encoding="utf-8") as f: - data = json.loads(f.read()) - - for name, license_info in data.items(): - license = License(name, license_info[0], license_info[1], license_info[2]) - _licenses[name.lower()] = license - - full_name = license_info[0].lower() - if full_name in _licenses: - existing_license = _licenses[full_name] - if not existing_license.is_deprecated: - continue - - _licenses[full_name] = license - - # Add a Proprietary license for non-standard licenses - _licenses["proprietary"] = License("Proprietary", "Proprietary", False, False) - - -if __name__ == "__main__": - updater = Updater() - updater.dump() diff --git a/poetry/core/spdx/helpers.py b/poetry/core/spdx/helpers.py new file mode 100644 index 000000000..a1a1d73c8 --- /dev/null +++ b/poetry/core/spdx/helpers.py @@ -0,0 +1,66 @@ +import json +import os + +from io import open +from typing import TYPE_CHECKING +from typing import Dict +from typing import Optional + + +if TYPE_CHECKING: + from .license import License # noqa + + +_licenses: Optional[Dict[str, "License"]] = None + + +def license_by_id(identifier: str) -> "License": + from .license import License # noqa + + if _licenses is None: + load_licenses() + + id = identifier.lower() + + if id not in _licenses: + if not identifier: + raise ValueError("A license identifier is required") + + return License(identifier, identifier, False, False) + + return _licenses[id] + + +def load_licenses() -> None: + from .license import License # noqa + + global _licenses + + _licenses = {} + + licenses_file = os.path.join(os.path.dirname(__file__), "data", "licenses.json") + + with open(licenses_file, encoding="utf-8") as f: + data = json.loads(f.read()) + + for name, license_info in data.items(): + license = License(name, license_info[0], license_info[1], license_info[2]) + _licenses[name.lower()] = license + + full_name = license_info[0].lower() + if full_name in _licenses: + existing_license = _licenses[full_name] + if not existing_license.is_deprecated: + continue + + _licenses[full_name] = license + + # Add a Proprietary license for non-standard licenses + _licenses["proprietary"] = License("Proprietary", "Proprietary", False, False) + + +if __name__ == "__main__": + from .updater import Updater + + updater = Updater() + updater.dump() diff --git a/poetry/core/toml/file.py b/poetry/core/toml/file.py index 9678bb5b0..ca90b71d1 100644 --- a/poetry/core/toml/file.py +++ b/poetry/core/toml/file.py @@ -3,11 +3,8 @@ from typing import Any from typing import Union -from tomlkit.exceptions import TOMLKitError from tomlkit.toml_file import TOMLFile as BaseTOMLFile -from poetry.core.toml import TOMLError - if TYPE_CHECKING: from tomlkit.toml_document import TOMLDocument # noqa @@ -28,6 +25,10 @@ def exists(self) -> bool: return self.__path.exists() def read(self) -> "TOMLDocument": + from tomlkit.exceptions import TOMLKitError + + from poetry.core.toml import TOMLError + try: return super(TOMLFile, self).read() except (ValueError, TOMLKitError) as e: diff --git a/poetry/core/version/grammars/parser.py b/poetry/core/version/grammars/parser.py new file mode 100644 index 000000000..13b8d76e3 --- /dev/null +++ b/poetry/core/version/grammars/parser.py @@ -0,0 +1,26 @@ +import os + +from typing import TYPE_CHECKING +from typing import Optional + + +if TYPE_CHECKING: + from lark import Lark # noqa + from lark import Tree # noqa + + +class Parser: + def __init__(self, grammar: str) -> None: + self._grammar = grammar + self._parser: Optional["Lark"] = None + + def parse(self, string: str) -> "Tree": + from lark import Lark + + if self._parser is None: + self._parser = Lark.open( + os.path.join(os.path.dirname(__file__), f"{self._grammar}.lark"), + parser="lalr", + ) + + return self._parser.parse(string) diff --git a/poetry/core/version/helpers.py b/poetry/core/version/helpers.py index 5725d0a27..df64b8e0f 100644 --- a/poetry/core/version/helpers.py +++ b/poetry/core/version/helpers.py @@ -1,13 +1,13 @@ from typing import TYPE_CHECKING from typing import Union -from poetry.core.semver import Version -from poetry.core.semver import VersionUnion -from poetry.core.semver import parse_constraint +from poetry.core.semver.helpers import parse_constraint +from poetry.core.semver.version import Version +from poetry.core.semver.version_union import VersionUnion if TYPE_CHECKING: - from poetry.core.semver import VersionConstraint # noqa + from poetry.core.semver.version_constraint import VersionConstraint # noqa PYTHON_VERSION = [ "2.7.*", diff --git a/poetry/core/version/markers.py b/poetry/core/version/markers.py index 69fc742f9..af7d86e46 100644 --- a/poetry/core/version/markers.py +++ b/poetry/core/version/markers.py @@ -1,4 +1,3 @@ -import os import re from typing import TYPE_CHECKING @@ -8,13 +7,13 @@ from typing import List from typing import Union -from lark import Lark -from lark import Token -from lark import Tree +from .grammars.parser import Parser if TYPE_CHECKING: - from poetry.core.semver import VersionTypes # noqa + from lark import Tree # noqa + + from poetry.core.semver.helpers import VersionTypes # noqa MarkerTypes = Union[ "AnyMarker", "EmptyMarker", "SingleMarker", "MultiMarker", "MarkerUnion" @@ -48,9 +47,9 @@ class UndefinedEnvironmentName(ValueError): "platform.python_implementation": "platform_python_implementation", "python_implementation": "platform_python_implementation", } -_parser = Lark.open( - os.path.join(os.path.dirname(__file__), "grammars", "markers.lark"), parser="lalr" -) + + +_parser = Parser("markers") class BaseMarker(object): @@ -186,7 +185,7 @@ def __init__(self, name: str, constraint: Union[str, "VersionTypes"]) -> None: from poetry.core.packages.constraints import ( parse_constraint as parse_generic_constraint, ) - from poetry.core.semver import parse_constraint + from poetry.core.semver.helpers import parse_constraint self._name = ALIASES.get(name, name) self._constraint_string = str(constraint) @@ -324,7 +323,7 @@ def invert(self) -> MarkerTypes: # This one is more tricky to handle # since it's technically a multi marker # so the inverse will be a union of inverse - from poetry.core.semver import VersionRange + from poetry.core.semver.version_range import VersionRange if not isinstance(self._constraint, VersionRange): # The constraint must be a version range, otherwise @@ -697,7 +696,9 @@ def parse_marker(marker: str) -> MarkerTypes: return markers -def _compact_markers(tree_elements: Tree, tree_prefix: str = "") -> MarkerTypes: +def _compact_markers(tree_elements: "Tree", tree_prefix: str = "") -> MarkerTypes: + from lark import Token + groups = [MultiMarker()] for token in tree_elements: if isinstance(token, Token): diff --git a/poetry/core/version/requirements.py b/poetry/core/version/requirements.py index adb5dd5e2..1016bf612 100644 --- a/poetry/core/version/requirements.py +++ b/poetry/core/version/requirements.py @@ -1,37 +1,19 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function +import urllib.parse as urlparse -import os - -from lark import Lark -from lark import UnexpectedCharacters -from lark import UnexpectedToken - -from poetry.core.semver import parse_constraint from poetry.core.semver.exceptions import ParseConstraintError +from poetry.core.semver.helpers import parse_constraint +from .grammars.parser import Parser from .markers import _compact_markers -try: - import urllib.parse as urlparse -except ImportError: - import urlparse - - class InvalidRequirement(ValueError): """ An invalid requirement was found, users should refer to PEP 508. """ -_parser = Lark.open( - os.path.join(os.path.dirname(__file__), "grammars", "pep508.lark"), parser="lalr" -) +_parser = Parser("pep508") class Requirement(object): @@ -44,6 +26,9 @@ class Requirement(object): """ def __init__(self, requirement_string: str) -> None: + from lark import UnexpectedCharacters + from lark import UnexpectedToken + try: parsed = _parser.parse(requirement_string) except (UnexpectedCharacters, UnexpectedToken) as e: diff --git a/tests/masonry/builders/test_complete.py b/tests/masonry/builders/test_complete.py index 0ababb89d..01a8c114a 100644 --- a/tests/masonry/builders/test_complete.py +++ b/tests/masonry/builders/test_complete.py @@ -16,7 +16,7 @@ from poetry.core import __version__ from poetry.core.factory import Factory -from poetry.core.masonry import Builder +from poetry.core.masonry.builder import Builder fixtures_dir = Path(__file__).parent / "fixtures" diff --git a/tests/masonry/builders/test_sdist.py b/tests/masonry/builders/test_sdist.py index 6f22fd18b..3cb2a3b12 100644 --- a/tests/masonry/builders/test_sdist.py +++ b/tests/masonry/builders/test_sdist.py @@ -11,8 +11,8 @@ from poetry.core.factory import Factory from poetry.core.masonry.builders.sdist import SdistBuilder from poetry.core.masonry.utils.package_include import PackageInclude -from poetry.core.packages import Package from poetry.core.packages.dependency import Dependency +from poetry.core.packages.package import Package from poetry.core.packages.vcs_dependency import VCSDependency diff --git a/tests/packages/test_dependency.py b/tests/packages/test_dependency.py index 116c50880..94ac58775 100644 --- a/tests/packages/test_dependency.py +++ b/tests/packages/test_dependency.py @@ -1,8 +1,7 @@ import pytest -from poetry.core.packages import Dependency -from poetry.core.packages import Package -from poetry.core.packages import dependency_from_pep_508 +from poetry.core.packages.dependency import Dependency +from poetry.core.packages.package import Package def test_accepts(): @@ -118,7 +117,9 @@ def test_to_pep_508_in_extras(): def test_to_pep_508_in_extras_parsed(): - dependency = dependency_from_pep_508('foo[bar] (>=1.23,<2.0) ; extra == "baz"') + dependency = Dependency.create_from_pep_508( + 'foo[bar] (>=1.23,<2.0) ; extra == "baz"' + ) result = dependency.to_pep_508() assert result == 'foo[bar] (>=1.23,<2.0); extra == "baz"' diff --git a/tests/packages/test_directory_dependency.py b/tests/packages/test_directory_dependency.py index 407d508bf..a69364532 100644 --- a/tests/packages/test_directory_dependency.py +++ b/tests/packages/test_directory_dependency.py @@ -2,7 +2,7 @@ import pytest -from poetry.core.packages import dependency_from_pep_508 +from poetry.core.packages.dependency import Dependency from poetry.core.packages.directory_dependency import DirectoryDependency @@ -15,7 +15,9 @@ def test_directory_dependency_must_exist(): def _test_directory_dependency_pep_508(name, path, pep_508_input, pep_508_output=None): - dep = dependency_from_pep_508(pep_508_input, relative_to=Path(__file__).parent) + dep = Dependency.create_from_pep_508( + pep_508_input, relative_to=Path(__file__).parent + ) assert dep.is_directory() assert dep.name == name diff --git a/tests/packages/test_file_dependency.py b/tests/packages/test_file_dependency.py index bee19b334..3abe20f88 100644 --- a/tests/packages/test_file_dependency.py +++ b/tests/packages/test_file_dependency.py @@ -2,9 +2,8 @@ import pytest -from poetry.core.packages import FileDependency -from poetry.core.packages import dependency_from_pep_508 -from poetry.core.utils._compat import PY36 +from poetry.core.packages.dependency import Dependency +from poetry.core.packages.file_dependency import FileDependency DIST_PATH = Path(__file__).parent.parent / "fixtures" / "distributions" @@ -25,10 +24,10 @@ def _test_file_dependency_pep_508( ): mocker.patch.object(Path, "exists").return_value = True mocker.patch.object(Path, "is_file").return_value = True - if not PY36: - mocker.patch.object(Path, "resolve").return_value = path - dep = dependency_from_pep_508(pep_508_input, relative_to=Path(__file__).parent) + dep = Dependency.create_from_pep_508( + pep_508_input, relative_to=Path(__file__).parent + ) assert dep.is_file() assert dep.name == name diff --git a/tests/packages/test_main.py b/tests/packages/test_main.py index a6e6e2ea9..d9cba1ac6 100644 --- a/tests/packages/test_main.py +++ b/tests/packages/test_main.py @@ -1,9 +1,9 @@ -from poetry.core.packages import dependency_from_pep_508 +from poetry.core.packages.dependency import Dependency def test_dependency_from_pep_508(): name = "requests" - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert dep.name == name assert str(dep.constraint) == "*" @@ -11,7 +11,7 @@ def test_dependency_from_pep_508(): def test_dependency_from_pep_508_with_version(): name = "requests==2.18.0" - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" @@ -19,7 +19,7 @@ def test_dependency_from_pep_508_with_version(): def test_dependency_from_pep_508_with_parens(): name = "requests (==2.18.0)" - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" @@ -27,7 +27,7 @@ def test_dependency_from_pep_508_with_parens(): def test_dependency_from_pep_508_with_constraint(): name = "requests>=2.12.0,!=2.17.*,<3.0" - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == ">=2.12.0,<2.17.0 || >=2.18.0,<3.0" @@ -35,7 +35,7 @@ def test_dependency_from_pep_508_with_constraint(): def test_dependency_from_pep_508_with_extras(): name = 'requests==2.18.0; extra == "foo" or extra == "bar"' - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" @@ -45,7 +45,7 @@ def test_dependency_from_pep_508_with_extras(): def test_dependency_from_pep_508_with_python_version(): name = 'requests (==2.18.0); python_version == "2.7" or python_version == "2.6"' - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" @@ -56,7 +56,7 @@ def test_dependency_from_pep_508_with_python_version(): def test_dependency_from_pep_508_with_single_python_version(): name = 'requests (==2.18.0); python_version == "2.7"' - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" @@ -67,7 +67,7 @@ def test_dependency_from_pep_508_with_single_python_version(): def test_dependency_from_pep_508_with_platform(): name = 'requests (==2.18.0); sys_platform == "win32" or sys_platform == "darwin"' - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" @@ -83,7 +83,7 @@ def test_dependency_from_pep_508_complex(): 'and (sys_platform == "win32" or sys_platform == "darwin") ' 'and extra == "foo"' ) - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" @@ -98,7 +98,7 @@ def test_dependency_from_pep_508_complex(): def test_dependency_python_version_in(): name = "requests (==2.18.0); python_version in '3.3 3.4 3.5'" - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" @@ -108,7 +108,7 @@ def test_dependency_python_version_in(): def test_dependency_python_version_in_comma(): name = "requests (==2.18.0); python_version in '3.3, 3.4, 3.5'" - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" @@ -118,7 +118,7 @@ def test_dependency_python_version_in_comma(): def test_dependency_platform_in(): name = "requests (==2.18.0); sys_platform in 'win32 darwin'" - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" @@ -127,7 +127,7 @@ def test_dependency_platform_in(): def test_dependency_with_extra(): name = "requests[security] (==2.18.0)" - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" @@ -142,7 +142,7 @@ def test_dependency_from_pep_508_with_python_version_union_of_multi(): '(python_version >= "2.7" and python_version < "2.8") ' 'or (python_version >= "3.4" and python_version < "3.5")' ) - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" @@ -160,7 +160,7 @@ def test_dependency_from_pep_508_with_not_in_op_marker(): '; python_version not in "3.0,3.1,3.2" and extra == "export"' ) - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert dep.name == "jinja2" assert str(dep.constraint) == ">=2.7,<2.8" @@ -174,7 +174,7 @@ def test_dependency_from_pep_508_with_not_in_op_marker(): def test_dependency_from_pep_508_with_git_url(): name = "django-utils @ git+ssh://git@corp-gitlab.com/corp-utils.git@1.2" - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert "django-utils" == dep.name assert dep.is_vcs() @@ -189,7 +189,7 @@ def test_dependency_from_pep_508_with_git_url_and_comment_and_extra(): ' ; extra == "foo;"' ) - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert "poetry" == dep.name assert dep.is_vcs() @@ -202,7 +202,7 @@ def test_dependency_from_pep_508_with_git_url_and_comment_and_extra(): def test_dependency_from_pep_508_with_url(): name = "django-utils @ https://example.com/django-utils-1.0.0.tar.gz" - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert "django-utils" == dep.name assert dep.is_url() @@ -214,7 +214,7 @@ def test_dependency_from_pep_508_with_wheel_url(): "example_wheel @ https://example.com/example_wheel-14.0.2-py2.py3-none-any.whl" ) - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert "example-wheel" == dep.name assert str(dep.constraint) == "14.0.2" @@ -226,7 +226,7 @@ def test_dependency_from_pep_508_with_python_full_version(): '(python_version >= "2.7" and python_version < "2.8") ' 'or (python_full_version >= "3.4" and python_full_version < "3.5.4")' ) - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" @@ -240,7 +240,7 @@ def test_dependency_from_pep_508_with_python_full_version(): def test_dependency_from_pep_508_with_python_full_version_pep440_compatible_release_astrix(): name = 'pathlib2 ; python_version == "3.4.*" or python_version < "3"' - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert dep.name == "pathlib2" assert str(dep.constraint) == "*" @@ -249,7 +249,7 @@ def test_dependency_from_pep_508_with_python_full_version_pep440_compatible_rele def test_dependency_from_pep_508_with_python_full_version_pep440_compatible_release_tilde(): name = 'pathlib2 ; python_version ~= "3.4" or python_version < "3"' - dep = dependency_from_pep_508(name) + dep = Dependency.create_from_pep_508(name) assert dep.name == "pathlib2" assert str(dep.constraint) == "*" diff --git a/tests/packages/test_package.py b/tests/packages/test_package.py index a64d50421..41bf98398 100644 --- a/tests/packages/test_package.py +++ b/tests/packages/test_package.py @@ -4,7 +4,7 @@ import pytest -from poetry.core.packages import Package +from poetry.core.packages.package import Package def test_package_authors(): diff --git a/tests/packages/test_url_dependency.py b/tests/packages/test_url_dependency.py index 93423d940..88ab2adce 100644 --- a/tests/packages/test_url_dependency.py +++ b/tests/packages/test_url_dependency.py @@ -1,4 +1,4 @@ -from poetry.core.packages import URLDependency +from poetry.core.packages.url_dependency import URLDependency from poetry.core.version.markers import SingleMarker diff --git a/tests/packages/utils/test_utils.py b/tests/packages/utils/test_utils.py index 7250e5f5d..7f8cfcd7e 100644 --- a/tests/packages/utils/test_utils.py +++ b/tests/packages/utils/test_utils.py @@ -2,7 +2,7 @@ from poetry.core.packages.utils.utils import convert_markers from poetry.core.packages.utils.utils import get_python_constraint_from_marker -from poetry.core.semver import parse_constraint +from poetry.core.semver.helpers import parse_constraint from poetry.core.version.markers import parse_marker diff --git a/tests/packages/utils/test_utils_link.py b/tests/packages/utils/test_utils_link.py index fb39f93f6..5751ed59a 100644 --- a/tests/packages/utils/test_utils_link.py +++ b/tests/packages/utils/test_utils_link.py @@ -2,7 +2,7 @@ from hashlib import sha256 -from poetry.core.packages import Link +from poetry.core.packages.utils.link import Link def make_url(ext): diff --git a/tests/packages/utils/test_utils_urls.py b/tests/packages/utils/test_utils_urls.py index a793c5aea..bbbb610bc 100644 --- a/tests/packages/utils/test_utils_urls.py +++ b/tests/packages/utils/test_utils_urls.py @@ -7,10 +7,8 @@ import pytest -from six.moves.urllib.request import pathname2url # noqa - -from poetry.core.packages import path_to_url -from poetry.core.packages import url_to_path +from poetry.core.packages.utils.utils import path_to_url +from poetry.core.packages.utils.utils import url_to_path @pytest.mark.skipif("sys.platform == 'win32'") diff --git a/tests/pyproject/test_pyproject_toml.py b/tests/pyproject/test_pyproject_toml.py index 3b14cbaec..7ca621ad8 100644 --- a/tests/pyproject/test_pyproject_toml.py +++ b/tests/pyproject/test_pyproject_toml.py @@ -7,8 +7,8 @@ from tomlkit.toml_document import TOMLDocument from tomlkit.toml_file import TOMLFile -from poetry.core.pyproject import PyProjectException -from poetry.core.pyproject import PyProjectTOML +from poetry.core.pyproject.exceptions import PyProjectException +from poetry.core.pyproject.toml import PyProjectTOML def test_pyproject_toml_simple(pyproject_toml, build_system_section, poetry_section): diff --git a/tests/semver/test_main.py b/tests/semver/test_helpers.py similarity index 96% rename from tests/semver/test_main.py rename to tests/semver/test_helpers.py index 85a46b3f5..a9f193b1a 100644 --- a/tests/semver/test_main.py +++ b/tests/semver/test_helpers.py @@ -1,9 +1,9 @@ import pytest -from poetry.core.semver import Version -from poetry.core.semver import VersionRange -from poetry.core.semver import VersionUnion -from poetry.core.semver import parse_constraint +from poetry.core.semver.helpers import parse_constraint +from poetry.core.semver.version import Version +from poetry.core.semver.version_range import VersionRange +from poetry.core.semver.version_union import VersionUnion @pytest.mark.parametrize( diff --git a/tests/semver/test_parse_constraint.py b/tests/semver/test_parse_constraint.py index f70c5741e..97e80dd1d 100644 --- a/tests/semver/test_parse_constraint.py +++ b/tests/semver/test_parse_constraint.py @@ -1,9 +1,9 @@ import pytest -from poetry.core.semver import Version -from poetry.core.semver import VersionRange -from poetry.core.semver import VersionUnion -from poetry.core.semver import parse_constraint +from poetry.core.semver.helpers import parse_constraint +from poetry.core.semver.version import Version +from poetry.core.semver.version_range import VersionRange +from poetry.core.semver.version_union import VersionUnion @pytest.mark.parametrize( diff --git a/tests/semver/test_version.py b/tests/semver/test_version.py index 9f26d4eb8..69bb6a6c1 100644 --- a/tests/semver/test_version.py +++ b/tests/semver/test_version.py @@ -1,9 +1,9 @@ import pytest -from poetry.core.semver import EmptyConstraint -from poetry.core.semver import Version -from poetry.core.semver import VersionRange +from poetry.core.semver.empty_constraint import EmptyConstraint from poetry.core.semver.exceptions import ParseVersionError +from poetry.core.semver.version import Version +from poetry.core.semver.version_range import VersionRange @pytest.mark.parametrize( diff --git a/tests/semver/test_version_range.py b/tests/semver/test_version_range.py index 3667a465f..e6e21e34c 100644 --- a/tests/semver/test_version_range.py +++ b/tests/semver/test_version_range.py @@ -1,8 +1,8 @@ import pytest -from poetry.core.semver import EmptyConstraint -from poetry.core.semver import Version -from poetry.core.semver import VersionRange +from poetry.core.semver.empty_constraint import EmptyConstraint +from poetry.core.semver.version import Version +from poetry.core.semver.version_range import VersionRange @pytest.fixture() diff --git a/tests/spdx/test_main.py b/tests/spdx/test_helpers.py similarity index 96% rename from tests/spdx/test_main.py rename to tests/spdx/test_helpers.py index 62448e353..bea44acd4 100644 --- a/tests/spdx/test_main.py +++ b/tests/spdx/test_helpers.py @@ -1,6 +1,6 @@ import pytest -from poetry.core.spdx import license_by_id +from poetry.core.spdx.helpers import license_by_id def test_license_by_id(): diff --git a/tests/spdx/test_license.py b/tests/spdx/test_license.py index 431dbacc0..55d0e8a16 100644 --- a/tests/spdx/test_license.py +++ b/tests/spdx/test_license.py @@ -1,4 +1,4 @@ -from poetry.core.spdx import license_by_id +from poetry.core.spdx.helpers import license_by_id def test_classifier_name(): diff --git a/tests/version/test_requirements.py b/tests/version/test_requirements.py index 29c1d962b..375294641 100644 --- a/tests/version/test_requirements.py +++ b/tests/version/test_requirements.py @@ -2,7 +2,7 @@ import pytest -from poetry.core.semver import parse_constraint +from poetry.core.semver.helpers import parse_constraint from poetry.core.version.requirements import InvalidRequirement from poetry.core.version.requirements import Requirement