diff --git a/pyproject.toml b/pyproject.toml index e6a726420..7e34178bd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -99,9 +99,6 @@ module = [ 'poetry.core.masonry.builders.builder', 'poetry.core.masonry.builders.sdist', 'poetry.core.masonry.builders.wheel', - 'poetry.core.packages.utils.utils', - 'poetry.core.packages.dependency', - 'poetry.core.packages.package', 'poetry.core.semver.version_union', 'poetry.core.toml.exceptions', 'poetry.core.toml.file', diff --git a/src/poetry/core/packages/dependency.py b/src/poetry/core/packages/dependency.py index 1beac6cdc..0ccd20302 100644 --- a/src/poetry/core/packages/dependency.py +++ b/src/poetry/core/packages/dependency.py @@ -8,6 +8,7 @@ from typing import TYPE_CHECKING from typing import Any from typing import Iterable +from typing import cast from poetry.core.packages.constraints import ( parse_constraint as parse_generic_constraint, @@ -55,8 +56,8 @@ def __init__( features=extras, ) - self._constraint: str | VersionConstraint | None = None - self._pretty_constraint: str | None = None + self._constraint: VersionConstraint + self._pretty_constraint: str self.set_constraint(constraint=constraint) self._optional = optional @@ -78,17 +79,17 @@ def __init__( self._python_versions = "*" self._python_constraint = parse_constraint("*") - self._transitive_python_versions = None + self._transitive_python_versions: str | None = None self._transitive_python_constraint: VersionConstraint | None = None - self._transitive_marker = None + self._transitive_marker: BaseMarker | None = None self._extras = frozenset(extras or []) - self._in_extras = [] + self._in_extras: list[str] = [] self._activated = not self._optional self.is_root = False - self._marker = AnyMarker() + self._marker: BaseMarker = AnyMarker() self.source_name = None @property @@ -263,9 +264,9 @@ def base_pep_508_name(self) -> str: if constraint.excludes_single_version(): requirement += f" ({str(constraint)})" else: - constraints = self.pretty_constraint.split(",") - constraints = [parse_constraint(c) for c in constraints] - constraints = ",".join(str(c) for c in constraints) + constraints = ",".join( + str(parse_constraint(c)) for c in self.pretty_constraint.split(",") + ) requirement += f" ({constraints})" elif isinstance(constraint, Version): requirement += f" (=={constraint.text})" @@ -343,8 +344,8 @@ def to_pep_508(self, with_extras: bool = True) -> str: requirement += " " if len(markers) > 1: - markers = " and ".join(f"({m})" for m in markers) - requirement += f"; {markers}" + marker_str = " and ".join(f"({m})" for m in markers) + requirement += f"; {marker_str}" else: requirement += f"; {markers[0]}" @@ -360,29 +361,23 @@ def _create_nested_marker( from poetry.core.semver.version_union import VersionUnion if isinstance(constraint, (MultiConstraint, UnionConstraint)): - parts = [] + multi_parts = [] for c in constraint.constraints: - multi = False - if isinstance(c, (MultiConstraint, UnionConstraint)): - multi = True - - parts.append((multi, self._create_nested_marker(name, c))) + multi = isinstance(c, (MultiConstraint, UnionConstraint)) + multi_parts.append((multi, self._create_nested_marker(name, c))) glue = " and " if isinstance(constraint, UnionConstraint): - parts = [f"({part[1]})" if part[0] else part[1] for part in parts] + parts = [f"({part[1]})" if part[0] else part[1] for part in multi_parts] glue = " or " else: - parts = [part[1] for part in parts] + parts = [part[1] for part in multi_parts] marker = glue.join(parts) elif isinstance(constraint, Constraint): marker = f'{name} {constraint.operator} "{constraint.version}"' elif isinstance(constraint, VersionUnion): - parts = [] - for c in constraint.ranges: - parts.append(self._create_nested_marker(name, c)) - + parts = [self._create_nested_marker(name, c) for c in constraint.ranges] glue = " or " parts = [f"({part})" for part in parts] @@ -406,7 +401,7 @@ def _create_nested_marker( if not constraint.include_min: op = ">" - version = constraint.min.text + version: Version | str = constraint.min.text if constraint.max is not None: max_name = name if constraint.max.precision >= 3 and name == "python_version": @@ -511,7 +506,6 @@ def create_from_pep_508( req = Requirement(name) name = req.name - path = os.path.normpath(os.path.abspath(name)) link = None if is_url(name): @@ -519,7 +513,8 @@ def create_from_pep_508( elif req.url: link = Link(req.url) else: - p, extras = strip_extras(path) + path_str = os.path.normpath(os.path.abspath(name)) + p, extras = strip_extras(path_str) if os.path.isdir(p) and (os.path.sep in name or name.startswith(".")): if not is_installable_dir(p): @@ -532,6 +527,7 @@ def create_from_pep_508( link = Link(path_to_url(p)) # it's a local file, dir, or url + dep: Dependency | None if link: is_file_uri = link.scheme == "file" is_relative_uri = is_file_uri and re.search(r"\.\./", link.url) @@ -552,7 +548,7 @@ def create_from_pep_508( name = m.group("name") version = m.group("ver") - name = req.name or link.egg_fragment + name = cast(str, req.name or link.egg_fragment) dep = None if link.scheme.startswith("git+"): @@ -593,11 +589,11 @@ def create_from_pep_508( if version: dep._constraint = parse_constraint(version) else: + constraint: VersionConstraint | str if req.pretty_constraint: constraint = req.constraint else: constraint = "*" - dep = Dependency(name, constraint, extras=req.extras) if req.marker: diff --git a/src/poetry/core/packages/directory_dependency.py b/src/poetry/core/packages/directory_dependency.py index 67824581b..16d7de821 100644 --- a/src/poetry/core/packages/directory_dependency.py +++ b/src/poetry/core/packages/directory_dependency.py @@ -101,9 +101,7 @@ def with_constraint( extras=list(self._extras), ) - new._constraint = constraint - new._pretty_constraint = str(constraint) - + new.set_constraint(constraint) new.is_root = self.is_root new.python_versions = self.python_versions new.marker = self.marker diff --git a/src/poetry/core/packages/file_dependency.py b/src/poetry/core/packages/file_dependency.py index 65e737f84..72780b974 100644 --- a/src/poetry/core/packages/file_dependency.py +++ b/src/poetry/core/packages/file_dependency.py @@ -85,9 +85,7 @@ def with_constraint(self, constraint: str | VersionConstraint) -> FileDependency extras=list(self._extras), ) - new._constraint = constraint - new._pretty_constraint = str(constraint) - + new.set_constraint(constraint) new.is_root = self.is_root new.python_versions = self.python_versions new.marker = self.marker diff --git a/src/poetry/core/packages/package.py b/src/poetry/core/packages/package.py index 002ccd22b..071632346 100644 --- a/src/poetry/core/packages/package.py +++ b/src/poetry/core/packages/package.py @@ -8,7 +8,9 @@ from typing import TYPE_CHECKING from typing import Collection from typing import Iterable +from typing import Iterator from typing import TypeVar +from typing import cast from poetry.core.packages.dependency_group import MAIN_GROUP from poetry.core.packages.specification import PackageSpecification @@ -83,18 +85,18 @@ def __init__( self.description = "" - self._authors = [] - self._maintainers = [] + self._authors: list[str] = [] + self._maintainers: list[str] = [] self.homepage: str | None = None self.repository_url: str | None = None self.documentation_url: str | None = None self.keywords: list[str] = [] - self._license = None + self._license: License | None = None self.readmes: tuple[Path, ...] = () - self.extras = {} - self.requires_extras = [] + self.extras: dict[str, list[str | Dependency]] = {} + self.requires_extras: list[str] = [] self._dependency_groups: dict[str, DependencyGroup] = {} @@ -103,7 +105,7 @@ def __init__( self.files: list[dict[str, str]] = [] self.optional = False - self.classifiers = [] + self.classifiers: list[str] = [] self._python_versions = "*" self._python_constraint = parse_constraint("*") @@ -151,12 +153,13 @@ def full_pretty_version(self) -> str: if self.source_type not in ["hg", "git"]: return self._pretty_version + ref: str | None if self.source_resolved_reference and len(self.source_resolved_reference) == 40: ref = self.source_resolved_reference[0:7] return f"{self._pretty_version} {ref}" # if source reference is a sha1 hash -- truncate - if len(self.source_reference) == 40: + if self.source_reference and len(self.source_reference) == 40: return f"{self._pretty_version} {self.source_reference[0:7]}" ref = self._source_resolved_reference or self._source_reference @@ -167,11 +170,11 @@ def authors(self) -> list[str]: return self._authors @property - def author_name(self) -> str: + def author_name(self) -> str | None: return self._get_author()["name"] @property - def author_email(self) -> str: + def author_email(self) -> str | None: return self._get_author()["email"] @property @@ -179,11 +182,11 @@ def maintainers(self) -> list[str]: return self._maintainers @property - def maintainer_name(self) -> str: + def maintainer_name(self) -> str | None: return self._get_maintainer()["name"] @property - def maintainer_email(self) -> str: + def maintainer_email(self) -> str | None: return self._get_maintainer()["email"] @property @@ -345,7 +348,7 @@ def urls(self) -> dict[str, str]: return urls @property - def readme(self) -> Path: + def readme(self) -> Path | None: import warnings warnings.warn( @@ -458,10 +461,11 @@ def to_dependency(self) -> Dependency: from poetry.core.packages.url_dependency import URLDependency from poetry.core.packages.vcs_dependency import VCSDependency + dep: Dependency if self.source_type == "directory": dep = DirectoryDependency( self._name, - Path(self._source_url), + Path(cast(str, self._source_url)), groups=list(self._dependency_groups.keys()), optional=self.optional, base=self.root_dir, @@ -471,7 +475,7 @@ def to_dependency(self) -> Dependency: elif self.source_type == "file": dep = FileDependency( self._name, - Path(self._source_url), + Path(cast(str, self._source_url)), groups=list(self._dependency_groups.keys()), optional=self.optional, base=self.root_dir, @@ -480,7 +484,7 @@ def to_dependency(self) -> Dependency: elif self.source_type == "url": dep = URLDependency( self._name, - self._source_url, + cast(str, self._source_url), groups=list(self._dependency_groups.keys()), optional=self.optional, extras=self.features, @@ -489,7 +493,7 @@ def to_dependency(self) -> Dependency: dep = VCSDependency( self._name, self.source_type, - self.source_url, + cast(str, self.source_url), rev=self.source_reference, resolved_rev=self.source_resolved_reference, directory=self.source_subdirectory, @@ -513,7 +517,7 @@ def to_dependency(self) -> Dependency: return dep.with_constraint(self._version) @contextmanager - def with_python_versions(self, python_versions: str) -> None: + def with_python_versions(self, python_versions: str) -> Iterator[None]: original_python_versions = self.python_versions self.python_versions = python_versions @@ -532,7 +536,7 @@ def with_features(self, features: Iterable[str]) -> Package: def without_features(self) -> Package: return self.with_features([]) - def clone(self) -> Package: + def clone(self: T) -> T: clone = self.__class__(self.pretty_name, self.version) clone.__dict__ = copy.deepcopy(self.__dict__) return clone @@ -540,7 +544,7 @@ def clone(self) -> Package: def __hash__(self) -> int: return super().__hash__() ^ hash(self._version) - def __eq__(self, other: Package) -> bool: + def __eq__(self, other: object) -> bool: if not isinstance(other, Package): return NotImplemented @@ -567,5 +571,5 @@ def __repr__(self) -> str: f"source_resolved_reference={repr(self._source_resolved_reference)}" ) - args = ", ".join(args) - return f"Package({args})" + args_str = ", ".join(args) + return f"Package({args_str})" diff --git a/src/poetry/core/packages/url_dependency.py b/src/poetry/core/packages/url_dependency.py index 20fe28ca2..13a710df5 100644 --- a/src/poetry/core/packages/url_dependency.py +++ b/src/poetry/core/packages/url_dependency.py @@ -65,9 +65,7 @@ def with_constraint(self, constraint: str | VersionConstraint) -> URLDependency: extras=list(self._extras), ) - new._constraint = constraint - new._pretty_constraint = str(constraint) - + new.set_constraint(constraint) new.is_root = self.is_root new.python_versions = self.python_versions new.marker = self.marker diff --git a/src/poetry/core/packages/utils/utils.py b/src/poetry/core/packages/utils/utils.py index 5ebae1fab..7b46c6b99 100644 --- a/src/poetry/core/packages/utils/utils.py +++ b/src/poetry/core/packages/utils/utils.py @@ -7,10 +7,14 @@ from pathlib import Path from typing import TYPE_CHECKING +from typing import Sequence +from typing import cast from urllib.parse import unquote from urllib.parse import urlsplit from urllib.request import url2pathname +from poetry.core.semver.version_range import VersionRange + if TYPE_CHECKING: from poetry.core.packages.constraints import BaseConstraint @@ -25,7 +29,7 @@ ZIP_EXTENSIONS = (".zip", ".whl") TAR_EXTENSIONS = (".tar.gz", ".tgz", ".tar") ARCHIVE_EXTENSIONS = ZIP_EXTENSIONS + BZ2_EXTENSIONS + TAR_EXTENSIONS + XZ_EXTENSIONS -SUPPORTED_EXTENSIONS = ZIP_EXTENSIONS + TAR_EXTENSIONS +SUPPORTED_EXTENSIONS: tuple[str, ...] = ZIP_EXTENSIONS + TAR_EXTENSIONS try: import bz2 # noqa: F401, TC002 @@ -97,7 +101,7 @@ def is_url(name: str) -> bool: ] -def strip_extras(path: str) -> tuple[str, str]: +def strip_extras(path: str) -> tuple[str, str | None]: m = re.match(r"^(.+)(\[[^\]]+\])$", path) extras = None if m: @@ -138,12 +142,12 @@ def splitext(path: str) -> tuple[str, str]: def group_markers( markers: list[BaseMarker], or_: bool = False -) -> list[tuple[str, str, str] | list[tuple[str, str, str]]]: +) -> list[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 = [[]] + groups: list[list[tuple[str, str, str]]] = [[]] for marker in markers: if or_: @@ -151,7 +155,7 @@ def group_markers( if isinstance(marker, (MultiMarker, MarkerUnion)): groups[-1].append( - group_markers(marker.markers, isinstance(marker, MarkerUnion)) + group_markers(marker.markers, isinstance(marker, MarkerUnion)) # type: ignore[arg-type] ) elif isinstance(marker, SingleMarker): lhs, op, rhs = marker.name, marker.operator, marker.value @@ -164,10 +168,10 @@ def group_markers( def convert_markers(marker: BaseMarker) -> dict[str, list[list[tuple[str, str]]]]: groups = group_markers([marker]) - requirements = {} + requirements: dict[str, list[list[tuple[str, str]]]] = {} def _group( - _groups: list[tuple[str, str, str] | list[tuple[str, str, str]]], + _groups: Sequence[tuple[str, str, str] | Sequence[tuple[str, str, str]]], or_: bool = False, ) -> None: ors = {} @@ -215,32 +219,25 @@ def create_nested_marker( return "" if isinstance(constraint, (MultiConstraint, UnionConstraint)): - parts = [] + multi_parts = [] for c in constraint.constraints: - multi = False - if isinstance(c, (MultiConstraint, UnionConstraint)): - multi = True - - parts.append((multi, create_nested_marker(name, c))) + multi = isinstance(c, (MultiConstraint, UnionConstraint)) + multi_parts.append((multi, create_nested_marker(name, c))) glue = " and " if isinstance(constraint, UnionConstraint): - parts = [f"({part[1]})" if part[0] else part[1] for part in parts] + parts = [f"({part[1]})" if part[0] else part[1] for part in multi_parts] glue = " or " else: - parts = [part[1] for part in parts] + parts = [part[1] for part in multi_parts] marker = glue.join(parts) elif isinstance(constraint, Constraint): marker = f'{name} {constraint.operator} "{constraint.version}"' elif isinstance(constraint, VersionUnion): - parts = [] - for c in constraint.ranges: - parts.append(create_nested_marker(name, c)) - + parts = [create_nested_marker(name, c) for c in constraint.ranges] glue = " or " parts = [f"({part})" for part in parts] - marker = glue.join(parts) elif isinstance(constraint, Version): if name == "python_version" and constraint.precision >= 3: @@ -248,6 +245,7 @@ def create_nested_marker( marker = f'{name} == "{constraint.text}"' else: + constraint = cast(VersionRange, constraint) if constraint.min is not None: op = ">=" if not constraint.include_min: diff --git a/src/poetry/core/packages/vcs_dependency.py b/src/poetry/core/packages/vcs_dependency.py index ab1d669cf..98a9a90c8 100644 --- a/src/poetry/core/packages/vcs_dependency.py +++ b/src/poetry/core/packages/vcs_dependency.py @@ -148,9 +148,7 @@ def with_constraint(self, constraint: str | VersionConstraint) -> VCSDependency: extras=list(self._extras), ) - new._constraint = constraint - new._pretty_constraint = str(constraint) - + new.set_constraint(constraint) new.is_root = self.is_root new.python_versions = self.python_versions new.marker = self.marker diff --git a/src/poetry/core/version/markers.py b/src/poetry/core/version/markers.py index 04d195d15..bc88f1902 100644 --- a/src/poetry/core/version/markers.py +++ b/src/poetry/core/version/markers.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING from typing import Any +from typing import Callable from typing import Iterable from poetry.core.semver.version_constraint import VersionConstraint @@ -193,13 +194,17 @@ def __init__( # Extract operator and value m = self._CONSTRAINT_RE.match(self._constraint_string) + if not m: + raise ValueError(f"Invalid constraint: {self._constraint_string}") self._operator = m.group(1) if self._operator is None: self._operator = "==" self._value = m.group(2) + self._parser: Callable[[str], BaseConstraint | VersionConstraint] self._parser = parse_generic_constraint + self._constraint: BaseConstraint | VersionConstraint if name in self._VERSION_LIKE_MARKER_NAME: self._parser = parse_constraint diff --git a/src/poetry/core/version/requirements.py b/src/poetry/core/version/requirements.py index 4ba110546..b20de2ffd 100644 --- a/src/poetry/core/version/requirements.py +++ b/src/poetry/core/version/requirements.py @@ -40,7 +40,7 @@ def __init__(self, requirement_string: str) -> None: f" {e.column}\n\n{e.get_context(requirement_string)}" ) - self.name = next(parsed.scan_values(lambda t: t.type == "NAME")).value + self.name: str = next(parsed.scan_values(lambda t: t.type == "NAME")).value url = next(parsed.scan_values(lambda t: t.type == "URI"), None) if url: