Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle deprecations #8544

Merged
merged 1 commit into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 9 additions & 20 deletions src/poetry/inspection/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import glob
import logging
import os
import tarfile
import zipfile

from pathlib import Path
from typing import TYPE_CHECKING
Expand All @@ -25,13 +23,12 @@
from poetry.pyproject.toml import PyProjectTOML
from poetry.utils.env import EnvCommandError
from poetry.utils.env import ephemeral_environment
from poetry.utils.helpers import extractall
from poetry.utils.setup_reader import SetupReader


if TYPE_CHECKING:
from collections.abc import Callable
from collections.abc import Iterator
from contextlib import AbstractContextManager

from poetry.core.packages.project_package import ProjectPackage

Expand Down Expand Up @@ -291,26 +288,18 @@ def _from_sdist_file(cls, path: Path) -> PackageInfo:
# Still not dependencies found
# So, we unpack and introspect
suffix = path.suffix
zip = suffix == ".zip"

context: Callable[
[str], AbstractContextManager[zipfile.ZipFile | tarfile.TarFile]
]
if suffix == ".zip":
context = zipfile.ZipFile
else:
if suffix == ".bz2":
suffixes = path.suffixes
if len(suffixes) > 1 and suffixes[-2] == ".tar":
suffix = ".tar.bz2"
else:
suffix = ".tar.gz"

context = tarfile.open
if suffix == ".bz2":
suffixes = path.suffixes
if len(suffixes) > 1 and suffixes[-2] == ".tar":
suffix = ".tar.bz2"
elif not zip:
suffix = ".tar.gz"

with temporary_directory() as tmp_str:
tmp = Path(tmp_str)
with context(path.as_posix()) as archive:
archive.extractall(tmp.as_posix())
extractall(source=path, dest=tmp, zip=zip)

# a little bit of guess work to determine the directory we care about
elements = list(tmp.glob("*"))
Expand Down
17 changes: 3 additions & 14 deletions src/poetry/installation/chef.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
from __future__ import annotations

import os
import tarfile
import tempfile
import zipfile

from contextlib import redirect_stdout
from io import StringIO
Expand All @@ -18,12 +16,11 @@

from poetry.utils._compat import decode
from poetry.utils.env import ephemeral_environment
from poetry.utils.helpers import extractall


if TYPE_CHECKING:
from collections.abc import Callable
from collections.abc import Collection
from contextlib import AbstractContextManager

from poetry.repositories import RepositoryPool
from poetry.utils.cache import ArtifactCache
Expand Down Expand Up @@ -174,19 +171,11 @@ def _prepare_sdist(self, archive: Path, destination: Path | None = None) -> Path
from poetry.core.packages.utils.link import Link

suffix = archive.suffix
context: Callable[
[str], AbstractContextManager[zipfile.ZipFile | tarfile.TarFile]
]
if suffix == ".zip": # noqa: SIM108
context = zipfile.ZipFile
else:
context = tarfile.open
zip = suffix == ".zip"

with temporary_directory() as tmp_dir:
with context(archive.as_posix()) as archive_archive:
archive_archive.extractall(tmp_dir)

archive_dir = Path(tmp_dir)
extractall(source=archive, dest=archive_dir, zip=zip)

elements = list(archive_dir.glob("*"))

Expand Down
47 changes: 41 additions & 6 deletions src/poetry/utils/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
import shutil
import stat
import sys
import tarfile
import tempfile
import zipfile

from collections.abc import Mapping
from contextlib import contextmanager
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Any
from typing import overload

from requests.utils import atomic_open

Expand All @@ -22,6 +25,7 @@
if TYPE_CHECKING:
from collections.abc import Callable
from collections.abc import Iterator
from types import TracebackType

from poetry.core.packages.package import Package
from requests import Session
Expand All @@ -39,17 +43,31 @@ def directory(path: Path) -> Iterator[Path]:
os.chdir(cwd)


def _on_rm_error(func: Callable[[str], None], path: str, exc_info: Exception) -> None:
# Correct type signature when used as `shutil.rmtree(..., onexc=_on_rm_error)`.
@overload
def _on_rm_error(
func: Callable[[str], None], path: str, exc_info: Exception
) -> None: ...


# Correct type signature when used as `shutil.rmtree(..., onerror=_on_rm_error)`.
@overload
def _on_rm_error(
func: Callable[[str], None],
path: str,
exc_info: tuple[type[BaseException], BaseException, TracebackType],
) -> None: ...


def _on_rm_error(func: Callable[[str], None], path: str, exc_info: Any) -> None:
if not os.path.exists(path):
return

os.chmod(path, stat.S_IWRITE)
func(path)


def remove_directory(
path: Path, *args: Any, force: bool = False, **kwargs: Any
) -> None:
def remove_directory(path: Path, force: bool = False) -> None:
"""
Helper function handle safe removal, and optionally forces stubborn file removal.
This is particularly useful when dist files are read-only or git writes read-only
Expand All @@ -60,8 +78,12 @@ def remove_directory(
if path.is_symlink():
return os.unlink(path)

kwargs["onerror"] = kwargs.pop("onerror", _on_rm_error if force else None)
shutil.rmtree(path, *args, **kwargs)
kwargs: dict[str, Any] = {}
if force:
onexc = "onexc" if sys.version_info >= (3, 12) else "onerror"
kwargs[onexc] = _on_rm_error

shutil.rmtree(path, **kwargs)


def merge_dicts(d1: dict[str, Any], d2: dict[str, Any]) -> None:
Expand Down Expand Up @@ -246,3 +268,16 @@ def get_file_hash(path: Path, hash_name: str = "sha256") -> str:
h.update(content)

return h.hexdigest()


def extractall(source: Path, dest: Path, zip: bool) -> None:
"""Extract all members from either a zip or tar archive."""
if zip:
with zipfile.ZipFile(source) as archive:
archive.extractall(dest)
else:
with tarfile.open(source) as archive:
if hasattr(tarfile, "data_filter"):
archive.extractall(dest, filter="data")
else:
archive.extractall(dest)