diff --git a/src/poetry/console/commands/config.py b/src/poetry/console/commands/config.py index 998af125755..281735a6f41 100644 --- a/src/poetry/console/commands/config.py +++ b/src/poetry/console/commands/config.py @@ -211,6 +211,7 @@ def handle(self) -> int: username = values[0] # Only username, so we prompt for password password = self.secret("Password:") + assert isinstance(password, str) elif len(values) != 2: raise ValueError( "Expected one or two arguments " diff --git a/src/poetry/console/commands/publish.py b/src/poetry/console/commands/publish.py index b98c58bfc73..a53df8208dd 100644 --- a/src/poetry/console/commands/publish.py +++ b/src/poetry/console/commands/publish.py @@ -44,7 +44,7 @@ class PublishCommand(Command): the config command. """ - loggers = ["poetry.masonry.publishing.publisher"] + loggers = ["poetry.publishing.publisher"] def handle(self) -> int: from poetry.publishing.publisher import Publisher diff --git a/src/poetry/inspection/info.py b/src/poetry/inspection/info.py index fe7ce6864e1..0e3fb4b4977 100644 --- a/src/poetry/inspection/info.py +++ b/src/poetry/inspection/info.py @@ -58,11 +58,11 @@ builder.metadata_path(dest) """ -PEP517_META_BUILD_DEPS = ["build==0.9.0", "pyproject_hooks==1.0.0"] +PEP517_META_BUILD_DEPS = ["build==0.10.0", "pyproject_hooks==1.0.0"] class PackageInfoError(ValueError): - def __init__(self, path: Path | str, *reasons: BaseException | str) -> None: + def __init__(self, path: Path, *reasons: BaseException | str) -> None: reasons = (f"Unable to determine package info for path: {path!s}",) + reasons super().__init__("\n\n".join(str(msg).strip() for msg in reasons if msg)) @@ -617,7 +617,7 @@ def get_pep517_metadata(path: Path) -> PackageInfo: ) cwd = Path.cwd() - os.chdir(path.as_posix()) + os.chdir(path) try: venv.run("python", "setup.py", "egg_info") info = PackageInfo.from_metadata(path) @@ -626,7 +626,7 @@ def get_pep517_metadata(path: Path) -> PackageInfo: path, "Fallback egg_info generation failed.", fbe ) finally: - os.chdir(cwd.as_posix()) + os.chdir(cwd) if info: logger.debug("Falling back to parsed setup.py file for %s", path) diff --git a/src/poetry/installation/executor.py b/src/poetry/installation/executor.py index ebbba0a4d6c..5d3f699d13c 100644 --- a/src/poetry/installation/executor.py +++ b/src/poetry/installation/executor.py @@ -650,7 +650,7 @@ def _install_directory_without_wheel_installer( if package.source_subdirectory: req /= package.source_subdirectory - pyproject = PyProjectTOML(os.path.join(req, "pyproject.toml")) + pyproject = PyProjectTOML(req / "pyproject.toml") package_poetry = None if pyproject.is_poetry_project(): diff --git a/src/poetry/installation/pip_installer.py b/src/poetry/installation/pip_installer.py index 60d672abc54..a528c24f215 100644 --- a/src/poetry/installation/pip_installer.py +++ b/src/poetry/installation/pip_installer.py @@ -221,7 +221,7 @@ def install_directory(self, package: Package) -> str | int: if package.source_subdirectory: req /= package.source_subdirectory - pyproject = PyProjectTOML(os.path.join(req, "pyproject.toml")) + pyproject = PyProjectTOML(req / "pyproject.toml") package_poetry = None if pyproject.is_poetry_project(): diff --git a/src/poetry/installation/wheel_installer.py b/src/poetry/installation/wheel_installer.py index ab2e0a82f3e..d81fe479cae 100644 --- a/src/poetry/installation/wheel_installer.py +++ b/src/poetry/installation/wheel_installer.py @@ -31,7 +31,7 @@ class WheelDestination(SchemeDictionaryDestination): def write_to_fs( self, scheme: Scheme, - path: Path | str, + path: str, stream: BinaryIO, is_executable: bool, ) -> RecordEntry: @@ -58,7 +58,7 @@ def write_to_fs( if is_executable: make_file_executable(target_path) - return RecordEntry(str(path), Hash(self.hash_algorithm, hash_), size) + return RecordEntry(path, Hash(self.hash_algorithm, hash_), size) def for_source(self, source: WheelFile) -> WheelDestination: scheme_dict = self.scheme_dict.copy() @@ -90,7 +90,7 @@ def __init__(self, env: Env) -> None: schemes["headers"] = schemes["include"] self._destination = WheelDestination( - schemes, interpreter=self._env.python, script_kind=script_kind + schemes, interpreter=str(self._env.python), script_kind=script_kind ) def enable_bytecode_compilation(self, enable: bool = True) -> None: diff --git a/src/poetry/packages/locker.py b/src/poetry/packages/locker.py index 2f4a2dcfda4..3d0206afb73 100644 --- a/src/poetry/packages/locker.py +++ b/src/poetry/packages/locker.py @@ -53,8 +53,8 @@ class Locker: _legacy_keys = ["dependencies", "source", "extras", "dev-dependencies"] _relevant_keys = [*_legacy_keys, "group"] - def __init__(self, lock: str | Path, local_config: dict[str, Any]) -> None: - self._lock = lock if isinstance(lock, Path) else Path(lock) + def __init__(self, lock: Path, local_config: dict[str, Any]) -> None: + self._lock = lock self._local_config = local_config self._lock_data: dict[str, Any] | None = None self._content_hash = self._get_content_hash() diff --git a/src/poetry/utils/cache.py b/src/poetry/utils/cache.py index facb380a0e5..d0d07fb113f 100644 --- a/src/poetry/utils/cache.py +++ b/src/poetry/utils/cache.py @@ -290,9 +290,8 @@ def _get_cached_archives_for_link(self, link: Link) -> list[Path]: cache_dir = self.get_cache_directory_for_link(link) archive_types = ["whl", "tar.gz", "tar.bz2", "bz2", "zip"] - paths = [] + paths: list[Path] = [] for archive_type in archive_types: - for archive in cache_dir.glob(f"*.{archive_type}"): - paths.append(Path(archive)) + paths += cache_dir.glob(f"*.{archive_type}") return paths diff --git a/src/poetry/utils/env.py b/src/poetry/utils/env.py index aa4d58bf223..734a7d64836 100644 --- a/src/poetry/utils/env.py +++ b/src/poetry/utils/env.py @@ -380,7 +380,7 @@ def remove_distribution_files(self, distribution_name: str) -> list[Path]: distribution_path: Path = distribution._path # type: ignore[attr-defined] if distribution_path.exists(): - remove_directory(str(distribution_path), force=True) + remove_directory(distribution_path, force=True) paths.append(distribution_path) @@ -388,16 +388,13 @@ def remove_distribution_files(self, distribution_name: str) -> list[Path]: def _path_method_wrapper( self, - path: str | Path, + path: Path, method: str, *args: Any, return_first: bool = True, writable_only: bool = False, **kwargs: Any, ) -> tuple[Path, Any] | list[tuple[Path, Any]]: - if isinstance(path, str): - path = Path(path) - candidates = self.make_candidates( path, writable_only=writable_only, strict=True ) @@ -419,17 +416,17 @@ def _path_method_wrapper( raise OSError(f"Unable to access any of {paths_csv(candidates)}") - def write_text(self, path: str | Path, *args: Any, **kwargs: Any) -> Path: + def write_text(self, path: Path, *args: Any, **kwargs: Any) -> Path: paths = self._path_method_wrapper(path, "write_text", *args, **kwargs) assert isinstance(paths, tuple) return paths[0] - def mkdir(self, path: str | Path, *args: Any, **kwargs: Any) -> Path: + def mkdir(self, path: Path, *args: Any, **kwargs: Any) -> Path: paths = self._path_method_wrapper(path, "mkdir", *args, **kwargs) assert isinstance(paths, tuple) return paths[0] - def exists(self, path: str | Path) -> bool: + def exists(self, path: Path) -> bool: return any( value[-1] for value in self._path_method_wrapper(path, "exists", return_first=False) @@ -437,7 +434,7 @@ def exists(self, path: str | Path) -> bool: def find( self, - path: str | Path, + path: Path, writable_only: bool = False, ) -> list[Path]: return [ @@ -520,7 +517,7 @@ def __init__(self, poetry: Poetry, io: None | IO = None) -> None: self._io = io or NullIO() @staticmethod - def _full_python_path(python: str) -> str: + def _full_python_path(python: str) -> Path: try: executable = decode( subprocess.check_output( @@ -530,10 +527,10 @@ def _full_python_path(python: str) -> str: except CalledProcessError as e: raise EnvCommandError(e) - return executable + return Path(executable) @staticmethod - def _detect_active_python(io: None | IO = None) -> str | None: + def _detect_active_python(io: None | IO = None) -> Path | None: io = io or NullIO() executable = None @@ -594,12 +591,12 @@ def activate(self, python: str) -> Env: # Executable in PATH or full executable path pass - python = self._full_python_path(python) + python_path = self._full_python_path(python) try: python_version_string = decode( subprocess.check_output( - [python, "-c", GET_PYTHON_VERSION_ONELINER], + [python_path, "-c", GET_PYTHON_VERSION_ONELINER], ) ) except CalledProcessError as e: @@ -624,7 +621,7 @@ def activate(self, python: str) -> Env: if patch != current_patch: create = True - self.create_venv(executable=python, force=create) + self.create_venv(executable=python_path, force=create) return self.get(reload=True) @@ -658,7 +655,7 @@ def activate(self, python: str) -> Env: if patch != current_patch: create = True - self.create_venv(executable=python, force=create) + self.create_venv(executable=python_path, force=create) # Activate envs[base_env_name] = {"minor": minor, "patch": patch} @@ -759,9 +756,7 @@ def list(self, name: str | None = None) -> list[VirtualEnv]: venv_name = self.generate_env_name(name, str(self._poetry.file.parent)) venv_path = self._poetry.config.virtualenvs_path - env_list = [ - VirtualEnv(Path(p)) for p in sorted(venv_path.glob(f"{venv_name}-py*")) - ] + env_list = [VirtualEnv(p) for p in sorted(venv_path.glob(f"{venv_name}-py*"))] venv = self._poetry.file.parent / ".venv" if ( @@ -837,7 +832,7 @@ def remove(self, python: str) -> Env: else: venv_path = self._poetry.config.virtualenvs_path # Get all the poetry envs, even for other projects - env_names = [Path(p).name for p in sorted(venv_path.glob("*-*-py*"))] + env_names = [p.name for p in sorted(venv_path.glob("*-*-py*"))] if python in env_names: raise IncorrectEnvError(python) @@ -885,7 +880,7 @@ def remove(self, python: str) -> Env: def create_venv( self, name: str | None = None, - executable: str | None = None, + executable: Path | None = None, force: bool = False, ) -> Env: if self._env is not None and not force: @@ -918,7 +913,9 @@ def create_venv( if not executable and prefer_active_python: executable = self._detect_active_python() - venv_path = cwd / ".venv" if root_venv else self._poetry.config.virtualenvs_path + venv_path: Path = ( + cwd / ".venv" if root_venv else self._poetry.config.virtualenvs_path + ) if not name: name = self._poetry.package.name assert name is not None @@ -1071,8 +1068,8 @@ def create_venv( @classmethod def build_venv( cls, - path: Path | str, - executable: str | Path | None = None, + path: Path, + executable: Path | None = None, flags: dict[str, bool] | None = None, with_pip: bool | None = None, with_wheel: bool | None = None, @@ -1103,14 +1100,13 @@ def build_venv( else flags.pop("no-wheel", flags["no-pip"]) ) - if isinstance(executable, Path): - executable = executable.resolve().as_posix() + executable_str = None if executable is None else executable.resolve().as_posix() args = [ "--no-download", "--no-periodic-update", "--python", - executable or sys.executable, + executable_str or sys.executable, ] if prompt is not None: @@ -1138,9 +1134,7 @@ def build_venv( return cli_result @classmethod - def remove_venv(cls, path: Path | str) -> None: - if isinstance(path, str): - path = Path(path) + def remove_venv(cls, path: Path) -> None: assert path.is_dir() try: remove_directory(path) @@ -1251,7 +1245,7 @@ def __init__(self, path: Path, base: Path | None = None) -> None: self._platlib: Path | None = None self._script_dirs: list[Path] | None = None - self._embedded_pip_path: str | None = None + self._embedded_pip_path: Path | None = None @property def path(self) -> Path: @@ -1271,7 +1265,7 @@ def python_implementation(self) -> str: return implementation @property - def python(self) -> str: + def python(self) -> Path: """ Path to current python executable """ @@ -1331,21 +1325,21 @@ def get_embedded_wheel(self, distribution: str) -> Path: return path @property - def pip_embedded(self) -> str: + def pip_embedded(self) -> Path: if self._embedded_pip_path is None: - self._embedded_pip_path = str(self.get_embedded_wheel("pip") / "pip") + self._embedded_pip_path = self.get_embedded_wheel("pip") / "pip" return self._embedded_pip_path @property - def pip(self) -> str: + def pip(self) -> Path: """ Path to current pip executable """ # we do not use as_posix() here due to issues with windows pathlib2 # implementation path = self._bin(self._pip_executable) - if not Path(path).exists(): - return str(self.pip_embedded) + if not path.exists(): + return self.pip_embedded return path @property @@ -1463,10 +1457,10 @@ def get_marker_env(self) -> dict[str, Any]: raise NotImplementedError() def get_pip_command(self, embedded: bool = False) -> list[str]: - if embedded or not Path(self._bin(self._pip_executable)).exists(): - return [self.python, self.pip_embedded] + if embedded or not self._bin(self._pip_executable).exists(): + return [str(self.python), str(self.pip_embedded)] # run as module so that pip can update itself on Windows - return [self.python, "-m", "pip"] + return [str(self.python), "-m", "pip"] def get_supported_tags(self) -> list[Tag]: raise NotImplementedError() @@ -1493,7 +1487,7 @@ def get_command_from_bin(self, bin: str) -> list[str]: # embedded pip when pip is not available in the environment return self.get_pip_command() - return [self._bin(bin)] + return [str(self._bin(bin))] def run(self, bin: str, *args: str, **kwargs: Any) -> str | int: cmd = self.get_command_from_bin(bin) + list(args) @@ -1572,7 +1566,7 @@ def script_dirs(self) -> list[Path]: self._script_dirs.append(self.userbase / self._script_dirs[0].name) return self._script_dirs - def _bin(self, bin: str) -> str: + def _bin(self, bin: str) -> Path: """ Return path to the given executable. """ @@ -1593,11 +1587,11 @@ def _bin(self, bin: str) -> str: bin_path = self._path / bin if bin_path.exists(): - return str(bin_path) + return bin_path - return bin + return Path(bin) - return str(bin_path) + return bin_path def __eq__(self, other: object) -> bool: if not isinstance(other, Env): @@ -1615,8 +1609,8 @@ class SystemEnv(Env): """ @property - def python(self) -> str: - return sys.executable + def python(self) -> Path: + return Path(sys.executable) @property def sys_path(self) -> list[str]: @@ -1942,20 +1936,20 @@ def execute(self, bin: str, *args: str, **kwargs: Any) -> int: return super().execute(bin, *args, **kwargs) return 0 - def _bin(self, bin: str) -> str: - return bin + def _bin(self, bin: str) -> Path: + return Path(bin) @contextmanager def ephemeral_environment( - executable: str | Path | None = None, + executable: Path | None = None, flags: dict[str, bool] | None = None, ) -> Iterator[VirtualEnv]: with temporary_directory() as tmp_dir: # TODO: cache PEP 517 build environment corresponding to each project venv venv_dir = Path(tmp_dir) / ".venv" EnvManager.build_venv( - path=venv_dir.as_posix(), + path=venv_dir, executable=executable, flags=flags, ) diff --git a/src/poetry/utils/helpers.py b/src/poetry/utils/helpers.py index 4d6ff50e28a..831203718fa 100644 --- a/src/poetry/utils/helpers.py +++ b/src/poetry/utils/helpers.py @@ -65,7 +65,7 @@ def _on_rm_error(func: Callable[[str], None], path: str, exc_info: Exception) -> def remove_directory( - path: Path | str, *args: Any, force: bool = False, **kwargs: Any + path: Path, *args: Any, force: bool = False, **kwargs: Any ) -> None: """ Helper function handle safe removal, and optionally forces stubborn file removal. @@ -74,8 +74,8 @@ def remove_directory( Internally, all arguments are passed to `shutil.rmtree`. """ - if Path(path).is_symlink(): - return os.unlink(str(path)) + 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) @@ -239,7 +239,7 @@ def get_win_folder(csidl_name: str) -> Path: raise RuntimeError("Method can only be called on Windows.") -def get_real_windows_path(path: str | Path) -> Path: +def get_real_windows_path(path: Path) -> Path: program_files = get_win_folder("CSIDL_PROGRAM_FILES") local_appdata = get_win_folder("CSIDL_LOCAL_APPDATA") diff --git a/src/poetry/utils/setup_reader.py b/src/poetry/utils/setup_reader.py index f0ecdde8220..ffb7d212509 100644 --- a/src/poetry/utils/setup_reader.py +++ b/src/poetry/utils/setup_reader.py @@ -3,12 +3,16 @@ import ast from configparser import ConfigParser -from pathlib import Path +from typing import TYPE_CHECKING from typing import Any from poetry.core.constraints.version import Version +if TYPE_CHECKING: + from pathlib import Path + + class SetupReader: """ Class that reads a setup.py file without executing it. @@ -25,10 +29,7 @@ class SetupReader: FILES = ["setup.py", "setup.cfg"] @classmethod - def read_from_directory(cls, directory: str | Path) -> dict[str, Any]: - if isinstance(directory, str): - directory = Path(directory) - + def read_from_directory(cls, directory: Path) -> dict[str, Any]: result = cls.DEFAULT.copy() for filename in cls.FILES: filepath = directory / filename @@ -44,10 +45,7 @@ def read_from_directory(cls, directory: str | Path) -> dict[str, Any]: return result - def read_setup_py(self, filepath: str | Path) -> dict[str, Any]: - if isinstance(filepath, str): - filepath = Path(filepath) - + def read_setup_py(self, filepath: Path) -> dict[str, Any]: with filepath.open(encoding="utf-8") as f: content = f.read() @@ -71,7 +69,7 @@ def read_setup_py(self, filepath: str | Path) -> dict[str, Any]: return result - def read_setup_cfg(self, filepath: str | Path) -> dict[str, Any]: + def read_setup_cfg(self, filepath: Path) -> dict[str, Any]: parser = ConfigParser() parser.read(str(filepath)) diff --git a/src/poetry/vcs/git/backend.py b/src/poetry/vcs/git/backend.py index 2e3032147f8..3d58850f468 100644 --- a/src/poetry/vcs/git/backend.py +++ b/src/poetry/vcs/git/backend.py @@ -137,11 +137,11 @@ def is_sha_short(self) -> bool: @dataclasses.dataclass class GitRepoLocalInfo: - repo: dataclasses.InitVar[Repo | Path | str] + repo: dataclasses.InitVar[Repo | Path] origin: str = dataclasses.field(init=False) revision: str = dataclasses.field(init=False) - def __post_init__(self, repo: Repo | Path | str) -> None: + def __post_init__(self, repo: Repo | Path) -> None: repo = Git.as_repo(repo=repo) if not isinstance(repo, Repo) else repo self.origin = Git.get_remote_url(repo=repo, remote="origin") self.revision = Git.get_revision(repo=repo) @@ -149,7 +149,7 @@ def __post_init__(self, repo: Repo | Path | str) -> None: class Git: @staticmethod - def as_repo(repo: Path | str) -> Repo: + def as_repo(repo: Path) -> Repo: return Repo(str(repo)) @staticmethod @@ -171,7 +171,7 @@ def get_revision(repo: Repo) -> str: return repo.head().decode("utf-8") @classmethod - def info(cls, repo: Repo | Path | str) -> GitRepoLocalInfo: + def info(cls, repo: Repo | Path) -> GitRepoLocalInfo: return GitRepoLocalInfo(repo=repo) @staticmethod @@ -302,7 +302,7 @@ def _clone(cls, url: str, refspec: GitRefSpec, target: Path) -> Repo: ), local.path, ) - remove_directory(local.path, force=True) + remove_directory(Path(local.path), force=True) if isinstance(e, AssertionError) and "Invalid object name" not in str(e): raise diff --git a/tests/conftest.py b/tests/conftest.py index 12f89a9f9b2..47c11049479 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -295,10 +295,11 @@ def _fixture_dir(name: str) -> Path: @pytest.fixture def tmp_dir() -> Iterator[str]: dir_ = tempfile.mkdtemp(prefix="poetry_") + path = Path(dir_) - yield Path(dir_).resolve().as_posix() + yield path.resolve().as_posix() - remove_directory(dir_, force=True) + remove_directory(path, force=True) @pytest.fixture diff --git a/tests/console/commands/env/test_use.py b/tests/console/commands/env/test_use.py index ad05e1e73b1..9cc5a9fc92a 100644 --- a/tests/console/commands/env/test_use.py +++ b/tests/console/commands/env/test_use.py @@ -55,7 +55,7 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file( venv_cache: Path, venv_name: str, venvs_in_cache_config: None, -): +) -> None: mocker.patch( "subprocess.check_output", side_effect=check_output_wrapper(), @@ -70,7 +70,7 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file( venv_py37 = venv_cache / f"{venv_name}-py3.7" mock_build_env.assert_called_with( venv_py37, - executable="/usr/bin/python3.7", + executable=Path("/usr/bin/python3.7"), flags={ "always-copy": False, "system-site-packages": False, @@ -99,7 +99,7 @@ def test_get_prefers_explicitly_activated_virtualenvs_over_env_var( venv_cache: Path, venv_name: str, venvs_in_cache_config: None, -): +) -> None: os.environ["VIRTUAL_ENV"] = "/environment/prefix" python_minor = ".".join(str(v) for v in current_python[:2]) @@ -128,7 +128,7 @@ def test_get_prefers_explicitly_activated_non_existing_virtualenvs_over_env_var( venv_cache: Path, venv_name: str, venvs_in_cache_config: None, -): +) -> None: os.environ["VIRTUAL_ENV"] = "/environment/prefix" python_minor = ".".join(str(v) for v in current_python[:2]) diff --git a/tests/console/commands/test_init.py b/tests/console/commands/test_init.py index 90b50b5f3cc..1feda849149 100644 --- a/tests/console/commands/test_init.py +++ b/tests/console/commands/test_init.py @@ -36,11 +36,10 @@ @pytest.fixture def source_dir(tmp_path: Path) -> Iterator[Path]: - cwd = os.getcwd() - + cwd = Path.cwd() try: - os.chdir(str(tmp_path)) - yield Path(tmp_path.as_posix()) + os.chdir(tmp_path) + yield tmp_path finally: os.chdir(cwd) diff --git a/tests/installation/test_pip_installer.py b/tests/installation/test_pip_installer.py index d333a87b8ea..29713e1daf0 100644 --- a/tests/installation/test_pip_installer.py +++ b/tests/installation/test_pip_installer.py @@ -67,7 +67,7 @@ def installer(pool: RepositoryPool, env: NullEnv) -> PipInstaller: return PipInstaller(env, NullIO(), pool) -def test_requirement(installer: PipInstaller): +def test_requirement(installer: PipInstaller) -> None: package = Package("ipython", "7.5.0") package.files = [ {"file": "foo-0.1.0.tar.gz", "hash": "md5:dbdc53e3918f28fa335a173432402a00"}, @@ -88,7 +88,7 @@ def test_requirement(installer: PipInstaller): assert result == expected -def test_requirement_source_type_url(env: NullEnv): +def test_requirement_source_type_url(env: NullEnv) -> None: installer = PipInstaller(env, NullIO(), RepositoryPool()) foo = Package( @@ -121,7 +121,9 @@ def test_requirement_git_subdirectory( assert Path(cmd[-1]).parts[-3:] == ("demo", "subdirectories", "two") -def test_requirement_git_develop_false(installer: PipInstaller, package_git: Package): +def test_requirement_git_develop_false( + installer: PipInstaller, package_git: Package +) -> None: package_git.develop = False result = installer.requirement(package_git) expected = "git+git@github.com:demo/demo.git@master#egg=demo" @@ -131,7 +133,7 @@ def test_requirement_git_develop_false(installer: PipInstaller, package_git: Pac def test_install_with_non_pypi_default_repository( pool: RepositoryPool, installer: PipInstaller -): +) -> None: default = LegacyRepository("default", "https://default.com") another = LegacyRepository("another", "https://another.com") @@ -164,7 +166,9 @@ def test_install_with_non_pypi_default_repository( ("cert", "cert"), ], ) -def test_install_with_certs(mocker: MockerFixture, key: str, option: str, env: NullEnv): +def test_install_with_certs( + mocker: MockerFixture, key: str, option: str, env: NullEnv +) -> None: client_path = "path/to/client.pem" mocker.patch( "poetry.utils.authenticator.Authenticator.get_certs_for_url", @@ -195,7 +199,9 @@ def test_install_with_certs(mocker: MockerFixture, key: str, option: str, env: N assert cmd[cert_index + 1] == str(Path(client_path)) -def test_requirement_git_develop_true(installer: PipInstaller, package_git: Package): +def test_requirement_git_develop_true( + installer: PipInstaller, package_git: Package +) -> None: package_git.develop = True result = installer.requirement(package_git) expected = ["-e", "git+git@github.com:demo/demo.git@master#egg=demo"] @@ -205,7 +211,7 @@ def test_requirement_git_develop_true(installer: PipInstaller, package_git: Pack def test_uninstall_git_package_nspkg_pth_cleanup( mocker: MockerFixture, tmp_venv: VirtualEnv, pool: RepositoryPool -): +) -> None: # this test scenario requires a real installation using the pip installer installer = PipInstaller(tmp_venv, NullIO(), pool) @@ -236,7 +242,7 @@ def copy_only(source: Path, dest: Path) -> None: installer.install(package) installer.remove(package) - pth_file = f"{package.name}-nspkg.pth" + pth_file = Path(f"{package.name}-nspkg.pth") assert not tmp_venv.site_packages.exists(pth_file) # any command in the virtual environment should trigger the error message @@ -244,7 +250,7 @@ def copy_only(source: Path, dest: Path) -> None: assert not re.match(rf"Error processing line 1 of .*{pth_file}", output) -def test_install_with_trusted_host(config: Config, env: NullEnv): +def test_install_with_trusted_host(config: Config, env: NullEnv) -> None: config.merge({"certificates": {"default": {"cert": False}}}) default = LegacyRepository("default", "https://foo.bar") @@ -272,7 +278,7 @@ def test_install_with_trusted_host(config: Config, env: NullEnv): def test_install_directory_fallback_on_poetry_create_error( mocker: MockerFixture, tmp_venv: VirtualEnv, pool: RepositoryPool -): +) -> None: mock_create_poetry = mocker.patch( "poetry.factory.Factory.create_poetry", side_effect=RuntimeError ) diff --git a/tests/masonry/builders/test_editable_builder.py b/tests/masonry/builders/test_editable_builder.py index 529f2d03e22..3e90a0b3e24 100644 --- a/tests/masonry/builders/test_editable_builder.py +++ b/tests/masonry/builders/test_editable_builder.py @@ -86,7 +86,7 @@ def env_manager(simple_poetry: Poetry) -> EnvManager: def tmp_venv(tmp_dir: str, env_manager: EnvManager) -> VirtualEnv: venv_path = Path(tmp_dir) / "venv" - env_manager.build_venv(str(venv_path)) + env_manager.build_venv(venv_path) venv = VirtualEnv(venv_path) yield venv @@ -96,20 +96,20 @@ def tmp_venv(tmp_dir: str, env_manager: EnvManager) -> VirtualEnv: def test_builder_installs_proper_files_for_standard_packages( simple_poetry: Poetry, tmp_venv: VirtualEnv -): +) -> None: builder = EditableBuilder(simple_poetry, tmp_venv, NullIO()) builder.build() assert tmp_venv._bin_dir.joinpath("foo").exists() - pth_file = "simple_project.pth" + pth_file = Path("simple_project.pth") assert tmp_venv.site_packages.exists(pth_file) assert ( simple_poetry.file.parent.resolve().as_posix() == tmp_venv.site_packages.find(pth_file)[0].read_text().strip(os.linesep) ) - dist_info = "simple_project-1.2.3.dist-info" + dist_info = Path("simple_project-1.2.3.dist-info") assert tmp_venv.site_packages.exists(dist_info) dist_info = tmp_venv.site_packages.find(dist_info)[0] @@ -176,7 +176,7 @@ def test_builder_installs_proper_files_for_standard_packages( assert all(len(row) == 3 for row in records) record_entries = {row[0] for row in records} - pth_file = "simple_project.pth" + pth_file = Path("simple_project.pth") assert tmp_venv.site_packages.exists(pth_file) assert str(tmp_venv.site_packages.find(pth_file)[0]) in record_entries assert str(tmp_venv._bin_dir.joinpath("foo")) in record_entries @@ -223,7 +223,7 @@ def test_builder_installs_proper_files_for_standard_packages( def test_builder_falls_back_on_setup_and_pip_for_packages_with_build_scripts( mocker: MockerFixture, extended_poetry: Poetry, tmp_dir: str -): +) -> None: pip_install = mocker.patch("poetry.masonry.builders.editable.pip_install") env = MockEnv(path=Path(tmp_dir) / "foo") builder = EditableBuilder(extended_poetry, env, NullIO()) @@ -273,11 +273,11 @@ def test_builder_setup_generation_runs_with_pip_editable(tmp_dir: str) -> None: def test_builder_installs_proper_files_when_packages_configured( project_with_include: Poetry, tmp_venv: VirtualEnv -): +) -> None: builder = EditableBuilder(project_with_include, tmp_venv, NullIO()) builder.build() - pth_file = "with_include.pth" + pth_file = Path("with_include.pth") assert tmp_venv.site_packages.exists(pth_file) pth_file = tmp_venv.site_packages.find(pth_file)[0] @@ -298,12 +298,12 @@ def test_builder_installs_proper_files_when_packages_configured( def test_builder_generates_proper_metadata_when_multiple_readme_files( with_multiple_readme_files: Poetry, tmp_venv: VirtualEnv -): +) -> None: builder = EditableBuilder(with_multiple_readme_files, tmp_venv, NullIO()) builder.build() - dist_info = "my_package-0.1.dist-info" + dist_info = Path("my_package-0.1.dist-info") assert tmp_venv.site_packages.exists(dist_info) dist_info = tmp_venv.site_packages.find(dist_info)[0] @@ -336,7 +336,7 @@ def test_builder_generates_proper_metadata_when_multiple_readme_files( def test_builder_should_execute_build_scripts( mocker: MockerFixture, extended_without_setup_poetry: Poetry, tmp_path: Path -): +) -> None: env = MockEnv(path=tmp_path / "foo") mocker.patch( "poetry.masonry.builders.editable.build_environment" diff --git a/tests/packages/test_locker.py b/tests/packages/test_locker.py index a86b5d770ea..6f832dc8206 100644 --- a/tests/packages/test_locker.py +++ b/tests/packages/test_locker.py @@ -34,7 +34,7 @@ def locker() -> Locker: with tempfile.NamedTemporaryFile() as f: f.close() - locker = Locker(f.name, {}) + locker = Locker(Path(f.name), {}) return locker @@ -44,7 +44,7 @@ def root() -> ProjectPackage: return ProjectPackage("root", "1.2.3") -def test_lock_file_data_is_ordered(locker: Locker, root: ProjectPackage): +def test_lock_file_data_is_ordered(locker: Locker, root: ProjectPackage) -> None: package_a = get_package("A", "1.0.0") package_a.add_dependency(Factory.create_dependency("B", "^1.0")) package_a.files = [{"file": "foo", "hash": "456"}, {"file": "bar", "hash": "123"}] @@ -200,7 +200,7 @@ def test_lock_file_data_is_ordered(locker: Locker, root: ProjectPackage): assert content == expected -def test_locker_properly_loads_extras(locker: Locker): +def test_locker_properly_loads_extras(locker: Locker) -> None: content = f"""\ # {GENERATED_COMMENT} @@ -246,7 +246,7 @@ def test_locker_properly_loads_extras(locker: Locker): assert lockfile_dep.name == "lockfile" -def test_locker_properly_loads_nested_extras(locker: Locker): +def test_locker_properly_loads_nested_extras(locker: Locker) -> None: content = f"""\ # {GENERATED_COMMENT} @@ -327,7 +327,7 @@ def test_locker_properly_loads_nested_extras(locker: Locker): assert len(packages) == 1 -def test_locker_properly_loads_extras_legacy(locker: Locker): +def test_locker_properly_loads_extras_legacy(locker: Locker) -> None: content = f"""\ # {GENERATED_COMMENT} @@ -530,7 +530,9 @@ def test_locker_properly_assigns_metadata_files(locker: Locker) -> None: package.files = [] -def test_lock_packages_with_null_description(locker: Locker, root: ProjectPackage): +def test_lock_packages_with_null_description( + locker: Locker, root: ProjectPackage +) -> None: package_a = get_package("A", "1.0.0") package_a.description = None @@ -560,7 +562,9 @@ def test_lock_packages_with_null_description(locker: Locker, root: ProjectPackag assert content == expected -def test_lock_file_should_not_have_mixed_types(locker: Locker, root: ProjectPackage): +def test_lock_file_should_not_have_mixed_types( + locker: Locker, root: ProjectPackage +) -> None: package_a = get_package("A", "1.0.0") package_a.add_dependency(Factory.create_dependency("B", "^1.0.0")) package_a.add_dependency( @@ -604,7 +608,9 @@ def test_lock_file_should_not_have_mixed_types(locker: Locker, root: ProjectPack assert content == expected -def test_reading_lock_file_should_raise_an_error_on_invalid_data(locker: Locker): +def test_reading_lock_file_should_raise_an_error_on_invalid_data( + locker: Locker, +) -> None: content = f"""\ # {GENERATED_COMMENT} @@ -639,7 +645,7 @@ def test_reading_lock_file_should_raise_an_error_on_invalid_data(locker: Locker) def test_locking_legacy_repository_package_should_include_source_section( root: ProjectPackage, locker: Locker -): +) -> None: package_a = Package( "A", "1.0.0", @@ -682,7 +688,7 @@ def test_locking_legacy_repository_package_should_include_source_section( def test_locker_should_emit_warnings_if_lock_version_is_newer_but_allowed( locker: Locker, caplog: LogCaptureFixture -): +) -> None: version = ".".join(Version.parse(Locker._VERSION).next_minor().text.split(".")[:2]) content = f"""\ [metadata] @@ -712,7 +718,7 @@ def test_locker_should_emit_warnings_if_lock_version_is_newer_but_allowed( def test_locker_should_raise_an_error_if_lock_version_is_newer_and_not_allowed( locker: Locker, caplog: LogCaptureFixture -): +) -> None: content = f"""\ # {GENERATED_COMMENT} @@ -730,7 +736,9 @@ def test_locker_should_raise_an_error_if_lock_version_is_newer_and_not_allowed( _ = locker.lock_data -def test_root_extras_dependencies_are_ordered(locker: Locker, root: ProjectPackage): +def test_root_extras_dependencies_are_ordered( + locker: Locker, root: ProjectPackage +) -> None: root_dir = Path(__file__).parent.parent.joinpath("fixtures") Factory.create_dependency("B", "1.0.0", root_dir=root_dir) Factory.create_dependency("C", "1.0.0", root_dir=root_dir) @@ -765,7 +773,7 @@ def test_root_extras_dependencies_are_ordered(locker: Locker, root: ProjectPacka assert content == expected -def test_extras_dependencies_are_ordered(locker: Locker, root: ProjectPackage): +def test_extras_dependencies_are_ordered(locker: Locker, root: ProjectPackage) -> None: package_a = get_package("A", "1.0.0") package_a.add_dependency( Factory.create_dependency( @@ -805,7 +813,7 @@ def test_extras_dependencies_are_ordered(locker: Locker, root: ProjectPackage): def test_locker_should_neither_emit_warnings_nor_raise_error_for_lower_compatible_versions( # noqa: E501 locker: Locker, caplog: LogCaptureFixture -): +) -> None: older_version = "1.1" content = f"""\ [metadata] @@ -827,7 +835,7 @@ def test_locker_should_neither_emit_warnings_nor_raise_error_for_lower_compatibl def test_locker_dumps_dependency_information_correctly( locker: Locker, root: ProjectPackage -): +) -> None: root_dir = Path(__file__).parent.parent.joinpath("fixtures") package_a = get_package("A", "1.0.0") package_a.add_dependency( @@ -950,7 +958,7 @@ def test_locker_dumps_subdir(locker: Locker, root: ProjectPackage) -> None: def test_locker_dumps_dependency_extras_in_correct_order( locker: Locker, root: ProjectPackage -): +) -> None: root_dir = Path(__file__).parent.parent.joinpath("fixtures") package_a = get_package("A", "1.0.0") Factory.create_dependency("B", "1.0.0", root_dir=root_dir) @@ -996,7 +1004,7 @@ def test_locker_dumps_dependency_extras_in_correct_order( def test_locked_repository_uses_root_dir_of_package( locker: Locker, mocker: MockerFixture -): +) -> None: content = f"""\ # {GENERATED_COMMENT} @@ -1084,7 +1092,7 @@ def test_content_hash_with_legacy_is_compatible( assert (content_hash == old_content_hash) or fresh -def test_lock_file_resolves_file_url_symlinks(root: ProjectPackage): +def test_lock_file_resolves_file_url_symlinks(root: ProjectPackage) -> None: """ Create directories and file structure as follows: @@ -1119,7 +1127,7 @@ def test_lock_file_resolves_file_url_symlinks(root: ProjectPackage): # Test is not possible in that case. return raise - locker = Locker(str(symlink_path) + os.sep + Path(lock_file.name).name, {}) + locker = Locker(symlink_path / lock_file.name, {}) package_local = Package( "local-package", diff --git a/tests/utils/test_env.py b/tests/utils/test_env.py index 07823d4fb55..b720974212a 100644 --- a/tests/utils/test_env.py +++ b/tests/utils/test_env.py @@ -68,7 +68,7 @@ def __init__( self._sys_path = sys_path @property - def sys_path(self) -> list[str] | None: + def sys_path(self) -> list[str]: if self._sys_path is not None: return self._sys_path @@ -88,10 +88,10 @@ def manager(poetry: Poetry) -> EnvManager: def test_virtualenvs_with_spaces_in_their_path_work_as_expected( tmp_dir: str, manager: EnvManager -): +) -> None: venv_path = Path(tmp_dir) / "Virtual Env" - manager.build_venv(str(venv_path)) + manager.build_venv(venv_path) venv = VirtualEnv(venv_path) @@ -99,12 +99,12 @@ def test_virtualenvs_with_spaces_in_their_path_work_as_expected( @pytest.mark.skipif(sys.platform != "darwin", reason="requires darwin") -def test_venv_backup_exclusion(tmp_dir: str, manager: EnvManager): +def test_venv_backup_exclusion(tmp_dir: str, manager: EnvManager) -> None: import xattr venv_path = Path(tmp_dir) / "Virtual Env" - manager.build_venv(str(venv_path)) + manager.build_venv(venv_path) value = ( b"bplist00_\x10\x11com.apple.backupd" @@ -121,20 +121,20 @@ def test_venv_backup_exclusion(tmp_dir: str, manager: EnvManager): def test_env_commands_with_spaces_in_their_arg_work_as_expected( tmp_dir: str, manager: EnvManager -): +) -> None: venv_path = Path(tmp_dir) / "Virtual Env" - manager.build_venv(str(venv_path)) + manager.build_venv(venv_path) venv = VirtualEnv(venv_path) - assert venv.run("python", venv.pip, "--version").startswith( + assert venv.run("python", str(venv.pip), "--version").startswith( f"pip {venv.pip_version} from " ) def test_env_shell_commands_with_stdinput_in_their_arg_work_as_expected( tmp_dir: str, manager: EnvManager -): +) -> None: venv_path = Path(tmp_dir) / "Virtual Env" - manager.build_venv(str(venv_path)) + manager.build_venv(venv_path) venv = VirtualEnv(venv_path) run_output_path = Path(venv.run("python", "-", input_=GET_BASE_PREFIX).strip()) venv_base_prefix_path = Path(str(venv.get_base_prefix())) @@ -143,9 +143,9 @@ def test_env_shell_commands_with_stdinput_in_their_arg_work_as_expected( def test_env_get_supported_tags_matches_inside_virtualenv( tmp_dir: str, manager: EnvManager -): +) -> None: venv_path = Path(tmp_dir) / "Virtual Env" - manager.build_venv(str(venv_path)) + manager.build_venv(venv_path) venv = VirtualEnv(venv_path) import packaging.tags @@ -170,7 +170,7 @@ def test_env_get_venv_with_venv_folder_present( poetry: Poetry, in_project_venv_dir: Path, in_project: bool | None, -): +) -> None: poetry.config.config["virtualenvs"]["in-project"] = in_project venv = manager.get() if in_project is False: @@ -212,7 +212,7 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file( config: Config, mocker: MockerFixture, venv_name: str, -): +) -> None: if "VIRTUAL_ENV" in os.environ: del os.environ["VIRTUAL_ENV"] @@ -232,7 +232,7 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file( m.assert_called_with( Path(tmp_dir) / f"{venv_name}-py3.7", - executable="/usr/bin/python3.7", + executable=Path("/usr/bin/python3.7"), flags={ "always-copy": False, "system-site-packages": False, @@ -259,7 +259,7 @@ def test_activate_activates_existing_virtualenv_no_envs_file( config: Config, mocker: MockerFixture, venv_name: str, -): +) -> None: if "VIRTUAL_ENV" in os.environ: del os.environ["VIRTUAL_ENV"] @@ -298,7 +298,7 @@ def test_activate_activates_same_virtualenv_with_envs_file( config: Config, mocker: MockerFixture, venv_name: str, -): +) -> None: if "VIRTUAL_ENV" in os.environ: del os.environ["VIRTUAL_ENV"] @@ -341,7 +341,7 @@ def test_activate_activates_different_virtualenv_with_envs_file( config: Config, mocker: MockerFixture, venv_name: str, -): +) -> None: if "VIRTUAL_ENV" in os.environ: del os.environ["VIRTUAL_ENV"] @@ -368,7 +368,7 @@ def test_activate_activates_different_virtualenv_with_envs_file( m.assert_called_with( Path(tmp_dir) / f"{venv_name}-py3.6", - executable="/usr/bin/python3.6", + executable=Path("/usr/bin/python3.6"), flags={ "always-copy": False, "system-site-packages": False, @@ -394,7 +394,7 @@ def test_activate_activates_recreates_for_different_patch( config: Config, mocker: MockerFixture, venv_name: str, -): +) -> None: if "VIRTUAL_ENV" in os.environ: del os.environ["VIRTUAL_ENV"] @@ -432,7 +432,7 @@ def test_activate_activates_recreates_for_different_patch( build_venv_m.assert_called_with( Path(tmp_dir) / f"{venv_name}-py3.7", - executable="/usr/bin/python3.7", + executable=Path("/usr/bin/python3.7"), flags={ "always-copy": False, "system-site-packages": False, @@ -460,7 +460,7 @@ def test_activate_does_not_recreate_when_switching_minor( config: Config, mocker: MockerFixture, venv_name: str, -): +) -> None: if "VIRTUAL_ENV" in os.environ: del os.environ["VIRTUAL_ENV"] @@ -511,7 +511,7 @@ def test_deactivate_non_activated_but_existing( config: Config, mocker: MockerFixture, venv_name: str, -): +) -> None: if "VIRTUAL_ENV" in os.environ: del os.environ["VIRTUAL_ENV"] @@ -529,7 +529,6 @@ def test_deactivate_non_activated_but_existing( env = manager.get() assert env.path == Path(tmp_dir) / f"{venv_name}-py{python}" - assert Path("/prefix") def test_deactivate_activated( @@ -539,7 +538,7 @@ def test_deactivate_activated( config: Config, mocker: MockerFixture, venv_name: str, -): +) -> None: if "VIRTUAL_ENV" in os.environ: del os.environ["VIRTUAL_ENV"] @@ -569,7 +568,6 @@ def test_deactivate_activated( env = manager.get() assert env.path == Path(tmp_dir) / f"{venv_name}-py{version.major}.{version.minor}" - assert Path("/prefix") envs = envs_file.read() assert len(envs) == 0 @@ -582,7 +580,7 @@ def test_get_prefers_explicitly_activated_virtualenvs_over_env_var( config: Config, mocker: MockerFixture, venv_name: str, -): +) -> None: os.environ["VIRTUAL_ENV"] = "/environment/prefix" config.merge({"virtualenvs": {"path": str(tmp_dir)}}) @@ -614,7 +612,7 @@ def test_list( poetry: Poetry, config: Config, venv_name: str, -): +) -> None: config.merge({"virtualenvs": {"path": str(tmp_dir)}}) (Path(tmp_dir) / f"{venv_name}-py3.7").mkdir() @@ -634,7 +632,7 @@ def test_remove_by_python_version( config: Config, mocker: MockerFixture, venv_name: str, -): +) -> None: config.merge({"virtualenvs": {"path": str(tmp_dir)}}) (Path(tmp_dir) / f"{venv_name}-py3.7").mkdir() @@ -659,7 +657,7 @@ def test_remove_by_name( config: Config, mocker: MockerFixture, venv_name: str, -): +) -> None: config.merge({"virtualenvs": {"path": str(tmp_dir)}}) (Path(tmp_dir) / f"{venv_name}-py3.7").mkdir() @@ -684,7 +682,7 @@ def test_remove_by_string_with_python_and_version( config: Config, mocker: MockerFixture, venv_name: str, -): +) -> None: config.merge({"virtualenvs": {"path": str(tmp_dir)}}) (Path(tmp_dir) / f"{venv_name}-py3.7").mkdir() @@ -709,7 +707,7 @@ def test_remove_by_full_path_to_python( config: Config, mocker: MockerFixture, venv_name: str, -): +) -> None: config.merge({"virtualenvs": {"path": str(tmp_dir)}}) (Path(tmp_dir) / f"{venv_name}-py3.7").mkdir() @@ -735,7 +733,7 @@ def test_raises_if_acting_on_different_project_by_full_path( poetry: Poetry, config: Config, mocker: MockerFixture, -): +) -> None: config.merge({"virtualenvs": {"path": str(tmp_dir)}}) different_venv_name = "different-project" @@ -761,7 +759,7 @@ def test_raises_if_acting_on_different_project_by_name( manager: EnvManager, poetry: Poetry, config: Config, -): +) -> None: config.merge({"virtualenvs": {"path": str(tmp_dir)}}) different_venv_name = ( @@ -788,7 +786,7 @@ def test_raises_when_passing_old_env_after_dir_rename( poetry: Poetry, config: Config, venv_name: str, -): +) -> None: # Make sure that poetry raises when trying to remove old venv after you've renamed # root directory of the project, which will create another venv with new name. # This is not ideal as you still "can't" remove it by name, but it at least doesn't @@ -817,7 +815,7 @@ def test_remove_also_deactivates( config: Config, mocker: MockerFixture, venv_name: str, -): +) -> None: config.merge({"virtualenvs": {"path": str(tmp_dir)}}) (Path(tmp_dir) / f"{venv_name}-py3.7").mkdir() @@ -850,7 +848,7 @@ def test_remove_keeps_dir_if_not_deleteable( config: Config, mocker: MockerFixture, venv_name: str, -): +) -> None: # Ensure we empty rather than delete folder if its is an active mount point. # See https://github.com/python-poetry/poetry/pull/2064 config.merge({"virtualenvs": {"path": str(tmp_dir)}}) @@ -897,17 +895,17 @@ def err_on_rm_venv_only(path: Path | str, *args: Any, **kwargs: Any) -> None: @pytest.mark.skipif(os.name == "nt", reason="Symlinks are not support for Windows") -def test_env_has_symlinks_on_nix(tmp_dir: str, tmp_venv: VirtualEnv): +def test_env_has_symlinks_on_nix(tmp_dir: str, tmp_venv: VirtualEnv) -> None: assert os.path.islink(tmp_venv.python) -def test_run_with_input(tmp_dir: str, tmp_venv: VirtualEnv): +def test_run_with_input(tmp_dir: str, tmp_venv: VirtualEnv) -> None: result = tmp_venv.run("python", "-", input_=MINIMAL_SCRIPT) assert result == "Minimal Output" + os.linesep -def test_run_with_input_non_zero_return(tmp_dir: str, tmp_venv: VirtualEnv): +def test_run_with_input_non_zero_return(tmp_dir: str, tmp_venv: VirtualEnv) -> None: with pytest.raises(EnvCommandError) as process_error: # Test command that will return non-zero returncode. tmp_venv.run("python", "-", input_=ERRORING_SCRIPT) @@ -917,7 +915,7 @@ def test_run_with_input_non_zero_return(tmp_dir: str, tmp_venv: VirtualEnv): def test_run_with_keyboard_interrupt( tmp_dir: str, tmp_venv: VirtualEnv, mocker: MockerFixture -): +) -> None: mocker.patch("subprocess.run", side_effect=KeyboardInterrupt()) with pytest.raises(KeyboardInterrupt): tmp_venv.run("python", "-", input_=MINIMAL_SCRIPT) @@ -926,7 +924,7 @@ def test_run_with_keyboard_interrupt( def test_call_with_input_and_keyboard_interrupt( tmp_dir: str, tmp_venv: VirtualEnv, mocker: MockerFixture -): +) -> None: mocker.patch("subprocess.run", side_effect=KeyboardInterrupt()) kwargs = {"call": True} with pytest.raises(KeyboardInterrupt): @@ -936,7 +934,7 @@ def test_call_with_input_and_keyboard_interrupt( def test_call_no_input_with_keyboard_interrupt( tmp_dir: str, tmp_venv: VirtualEnv, mocker: MockerFixture -): +) -> None: mocker.patch("subprocess.call", side_effect=KeyboardInterrupt()) kwargs = {"call": True} with pytest.raises(KeyboardInterrupt): @@ -946,7 +944,7 @@ def test_call_no_input_with_keyboard_interrupt( def test_run_with_called_process_error( tmp_dir: str, tmp_venv: VirtualEnv, mocker: MockerFixture -): +) -> None: mocker.patch( "subprocess.run", side_effect=subprocess.CalledProcessError( @@ -962,7 +960,7 @@ def test_run_with_called_process_error( def test_call_with_input_and_called_process_error( tmp_dir: str, tmp_venv: VirtualEnv, mocker: MockerFixture -): +) -> None: mocker.patch( "subprocess.run", side_effect=subprocess.CalledProcessError( @@ -979,7 +977,7 @@ def test_call_with_input_and_called_process_error( def test_call_no_input_with_called_process_error( tmp_dir: str, tmp_venv: VirtualEnv, mocker: MockerFixture -): +) -> None: mocker.patch( "subprocess.call", side_effect=subprocess.CalledProcessError( @@ -996,7 +994,7 @@ def test_call_no_input_with_called_process_error( def test_check_output_with_called_process_error( tmp_dir: str, tmp_venv: VirtualEnv, mocker: MockerFixture -): +) -> None: mocker.patch( "subprocess.check_output", side_effect=subprocess.CalledProcessError( @@ -1037,7 +1035,7 @@ def target(result: list[int]) -> None: def test_run_python_script_called_process_error( tmp_dir: str, tmp_venv: VirtualEnv, mocker: MockerFixture -): +) -> None: mocker.patch( "subprocess.run", side_effect=subprocess.CalledProcessError( @@ -1050,7 +1048,7 @@ def test_run_python_script_called_process_error( assert "some error" in str(error.value) -def test_run_python_script_only_stdout(tmp_dir: str, tmp_venv: VirtualEnv): +def test_run_python_script_only_stdout(tmp_dir: str, tmp_venv: VirtualEnv) -> None: output = tmp_venv.run_python_script( "import sys; print('some warning', file=sys.stderr); print('some output')" ) @@ -1065,7 +1063,7 @@ def test_create_venv_tries_to_find_a_compatible_python_executable_using_generic_ mocker: MockerFixture, config_virtualenvs_path: Path, venv_name: str, -): +) -> None: if "VIRTUAL_ENV" in os.environ: del os.environ["VIRTUAL_ENV"] @@ -1084,7 +1082,7 @@ def test_create_venv_tries_to_find_a_compatible_python_executable_using_generic_ m.assert_called_with( config_virtualenvs_path / f"{venv_name}-py3.7", - executable="/usr/bin/python3", + executable=Path("/usr/bin/python3"), flags={ "always-copy": False, "system-site-packages": False, @@ -1102,7 +1100,7 @@ def test_create_venv_tries_to_find_a_compatible_python_executable_using_specific mocker: MockerFixture, config_virtualenvs_path: Path, venv_name: str, -): +) -> None: if "VIRTUAL_ENV" in os.environ: del os.environ["VIRTUAL_ENV"] @@ -1120,7 +1118,7 @@ def test_create_venv_tries_to_find_a_compatible_python_executable_using_specific m.assert_called_with( config_virtualenvs_path / f"{venv_name}-py3.9", - executable="/usr/bin/python3.9", + executable=Path("/usr/bin/python3.9"), flags={ "always-copy": False, "system-site-packages": False, @@ -1133,7 +1131,7 @@ def test_create_venv_tries_to_find_a_compatible_python_executable_using_specific def test_create_venv_fails_if_no_compatible_python_version_could_be_found( manager: EnvManager, poetry: Poetry, config: Config, mocker: MockerFixture -): +) -> None: if "VIRTUAL_ENV" in os.environ: del os.environ["VIRTUAL_ENV"] @@ -1159,7 +1157,7 @@ def test_create_venv_fails_if_no_compatible_python_version_could_be_found( def test_create_venv_does_not_try_to_find_compatible_versions_with_executable( manager: EnvManager, poetry: Poetry, config: Config, mocker: MockerFixture -): +) -> None: if "VIRTUAL_ENV" in os.environ: del os.environ["VIRTUAL_ENV"] @@ -1171,7 +1169,7 @@ def test_create_venv_does_not_try_to_find_compatible_versions_with_executable( ) with pytest.raises(NoCompatiblePythonVersionFound) as e: - manager.create_venv(executable="3.8") + manager.create_venv(executable=Path("python3.8")) expected_message = ( "The specified Python version (3.8.0) is not supported by the project (^4.8).\n" @@ -1190,7 +1188,7 @@ def test_create_venv_uses_patch_version_to_detect_compatibility( mocker: MockerFixture, config_virtualenvs_path: Path, venv_name: str, -): +) -> None: if "VIRTUAL_ENV" in os.environ: del os.environ["VIRTUAL_ENV"] @@ -1231,7 +1229,7 @@ def test_create_venv_uses_patch_version_to_detect_compatibility_with_executable( mocker: MockerFixture, config_virtualenvs_path: Path, venv_name: str, -): +) -> None: if "VIRTUAL_ENV" in os.environ: del os.environ["VIRTUAL_ENV"] @@ -1249,12 +1247,12 @@ def test_create_venv_uses_patch_version_to_detect_compatibility_with_executable( "poetry.utils.env.EnvManager.build_venv", side_effect=lambda *args, **kwargs: "" ) - manager.create_venv(executable=f"python{version.major}.{version.minor - 1}") + manager.create_venv(executable=Path(f"python{version.major}.{version.minor - 1}")) assert check_output.called m.assert_called_with( config_virtualenvs_path / f"{venv_name}-py{version.major}.{version.minor - 1}", - executable=f"python{version.major}.{version.minor - 1}", + executable=Path(f"python{version.major}.{version.minor - 1}"), flags={ "always-copy": False, "system-site-packages": False, @@ -1267,7 +1265,7 @@ def test_create_venv_uses_patch_version_to_detect_compatibility_with_executable( def test_create_venv_fails_if_current_python_version_is_not_supported( manager: EnvManager, poetry: Poetry -): +) -> None: if "VIRTUAL_ENV" in os.environ: del os.environ["VIRTUAL_ENV"] @@ -1298,7 +1296,7 @@ def test_activate_with_in_project_setting_does_not_fail_if_no_venvs_dir( config: Config, tmp_dir: str, mocker: MockerFixture, -): +) -> None: if "VIRTUAL_ENV" in os.environ: del os.environ["VIRTUAL_ENV"] @@ -1325,7 +1323,7 @@ def test_activate_with_in_project_setting_does_not_fail_if_no_venvs_dir( m.assert_called_with( poetry.file.parent / ".venv", - executable="/usr/bin/python3.7", + executable=Path("/usr/bin/python3.7"), flags={ "always-copy": False, "system-site-packages": False, @@ -1339,7 +1337,7 @@ def test_activate_with_in_project_setting_does_not_fail_if_no_venvs_dir( assert not envs_file.exists() -def test_system_env_has_correct_paths(): +def test_system_env_has_correct_paths() -> None: env = SystemEnv(Path(sys.prefix)) paths = env.paths @@ -1355,7 +1353,7 @@ def test_system_env_has_correct_paths(): "enabled", [True, False], ) -def test_system_env_usersite(mocker: MockerFixture, enabled: bool): +def test_system_env_usersite(mocker: MockerFixture, enabled: bool) -> None: mocker.patch("site.check_enableusersite", return_value=enabled) env = SystemEnv(Path(sys.prefix)) assert (enabled and env.usersite is not None) or ( @@ -1363,7 +1361,7 @@ def test_system_env_usersite(mocker: MockerFixture, enabled: bool): ) -def test_venv_has_correct_paths(tmp_venv: VirtualEnv): +def test_venv_has_correct_paths(tmp_venv: VirtualEnv) -> None: paths = tmp_venv.paths assert paths.get("purelib") is not None @@ -1377,7 +1375,7 @@ def test_venv_has_correct_paths(tmp_venv: VirtualEnv): ) -def test_env_system_packages(tmp_path: Path, poetry: Poetry): +def test_env_system_packages(tmp_path: Path, poetry: Poetry) -> None: venv_path = tmp_path / "venv" pyvenv_cfg = venv_path / "pyvenv.cfg" @@ -1401,7 +1399,7 @@ def test_env_system_packages(tmp_path: Path, poetry: Poetry): ) def test_env_no_pip( tmp_path: Path, poetry: Poetry, flags: dict[str, bool], packages: set[str] -): +) -> None: venv_path = tmp_path / "venv" EnvManager(poetry).build_venv(path=venv_path, flags=flags) env = VirtualEnv(venv_path) @@ -1416,9 +1414,9 @@ def test_env_no_pip( assert installed_packages == packages -def test_env_finds_the_correct_executables(tmp_dir: str, manager: EnvManager): +def test_env_finds_the_correct_executables(tmp_dir: str, manager: EnvManager) -> None: venv_path = Path(tmp_dir) / "Virtual Env" - manager.build_venv(str(venv_path), with_pip=True) + manager.build_venv(venv_path, with_pip=True) venv = VirtualEnv(venv_path) default_executable = expected_executable = f"python{'.exe' if WINDOWS else ''}" @@ -1448,14 +1446,12 @@ def test_env_finds_the_correct_executables(tmp_dir: str, manager: EnvManager): def test_env_finds_the_correct_executables_for_generic_env( tmp_dir: str, manager: EnvManager -): +) -> None: venv_path = Path(tmp_dir) / "Virtual Env" child_venv_path = Path(tmp_dir) / "Child Virtual Env" - manager.build_venv(str(venv_path), with_pip=True) + manager.build_venv(venv_path, with_pip=True) parent_venv = VirtualEnv(venv_path) - manager.build_venv( - str(child_venv_path), executable=parent_venv.python, with_pip=True - ) + manager.build_venv(child_venv_path, executable=parent_venv.python, with_pip=True) venv = GenericEnv(parent_venv.path, child_env=VirtualEnv(child_venv_path)) expected_executable = ( @@ -1475,14 +1471,12 @@ def test_env_finds_the_correct_executables_for_generic_env( def test_env_finds_fallback_executables_for_generic_env( tmp_dir: str, manager: EnvManager -): +) -> None: venv_path = Path(tmp_dir) / "Virtual Env" child_venv_path = Path(tmp_dir) / "Child Virtual Env" - manager.build_venv(str(venv_path), with_pip=True) + manager.build_venv(venv_path, with_pip=True) parent_venv = VirtualEnv(venv_path) - manager.build_venv( - str(child_venv_path), executable=parent_venv.python, with_pip=True - ) + manager.build_venv(child_venv_path, executable=parent_venv.python, with_pip=True) venv = GenericEnv(parent_venv.path, child_env=VirtualEnv(child_venv_path)) default_executable = f"python{'.exe' if WINDOWS else ''}" @@ -1544,7 +1538,7 @@ def test_create_venv_accepts_fallback_version_w_nonzero_patchlevel( mocker: MockerFixture, config_virtualenvs_path: Path, venv_name: str, -): +) -> None: if "VIRTUAL_ENV" in os.environ: del os.environ["VIRTUAL_ENV"] @@ -1572,7 +1566,7 @@ def mock_check_output(cmd: str, *args: Any, **kwargs: Any) -> str: assert check_output.called m.assert_called_with( config_virtualenvs_path / f"{venv_name}-py3.5", - executable="/usr/bin/python3.5", + executable=Path("/usr/bin/python3.5"), flags={ "always-copy": False, "system-site-packages": False, @@ -1586,7 +1580,7 @@ def mock_check_output(cmd: str, *args: Any, **kwargs: Any) -> str: def test_generate_env_name_ignores_case_for_case_insensitive_fs( poetry: Poetry, tmp_dir: str, -): +) -> None: venv_name1 = EnvManager.generate_env_name(poetry.package.name, "MyDiR") venv_name2 = EnvManager.generate_env_name(poetry.package.name, "mYdIr") if sys.platform == "win32": @@ -1595,7 +1589,7 @@ def test_generate_env_name_ignores_case_for_case_insensitive_fs( assert venv_name1 != venv_name2 -def test_generate_env_name_uses_real_path(tmp_dir: str, mocker: MockerFixture): +def test_generate_env_name_uses_real_path(tmp_dir: str, mocker: MockerFixture) -> None: mocker.patch("os.path.realpath", return_value="the_real_dir") venv_name1 = EnvManager.generate_env_name("simple-project", "the_real_dir") venv_name2 = EnvManager.generate_env_name("simple-project", "linked_dir") @@ -1613,7 +1607,7 @@ def extended_without_setup_poetry() -> Poetry: def test_build_environment_called_build_script_specified( mocker: MockerFixture, extended_without_setup_poetry: Poetry, tmp_dir: str -): +) -> None: project_env = MockEnv(path=Path(tmp_dir) / "project") ephemeral_env = MockEnv(path=Path(tmp_dir) / "ephemeral") @@ -1625,8 +1619,8 @@ def test_build_environment_called_build_script_specified( assert env == ephemeral_env assert env.executed == [ [ - sys.executable, - env.pip_embedded, + str(sys.executable), + str(env.pip_embedded), "install", "--disable-pip-version-check", "--ignore-installed", @@ -1638,7 +1632,7 @@ def test_build_environment_called_build_script_specified( def test_build_environment_not_called_without_build_script_specified( mocker: MockerFixture, poetry: Poetry, tmp_dir: str -): +) -> None: project_env = MockEnv(path=Path(tmp_dir) / "project") ephemeral_env = MockEnv(path=Path(tmp_dir) / "ephemeral") @@ -1656,7 +1650,7 @@ def test_create_venv_project_name_empty_sets_correct_prompt( config: Config, mocker: MockerFixture, config_virtualenvs_path: Path, -): +) -> None: if "VIRTUAL_ENV" in os.environ: del os.environ["VIRTUAL_ENV"] @@ -1680,7 +1674,7 @@ def test_create_venv_project_name_empty_sets_correct_prompt( m.assert_called_with( config_virtualenvs_path / f"{venv_name}-py3.7", - executable="/usr/bin/python3", + executable=Path("/usr/bin/python3"), flags={ "always-copy": False, "system-site-packages": False, @@ -1691,7 +1685,9 @@ def test_create_venv_project_name_empty_sets_correct_prompt( ) -def test_fallback_on_detect_active_python(poetry: Poetry, mocker: MockerFixture): +def test_fallback_on_detect_active_python( + poetry: Poetry, mocker: MockerFixture +) -> None: m = mocker.patch( "subprocess.check_output", side_effect=subprocess.CalledProcessError(1, "some command"), diff --git a/tests/utils/test_setup_reader.py b/tests/utils/test_setup_reader.py index d72e5386275..551ad707b34 100644 --- a/tests/utils/test_setup_reader.py +++ b/tests/utils/test_setup_reader.py @@ -1,7 +1,6 @@ from __future__ import annotations -import os - +from pathlib import Path from typing import TYPE_CHECKING import pytest @@ -16,16 +15,16 @@ @pytest.fixture() -def setup() -> Callable[[str], str]: - def _setup(name: str) -> str: - return os.path.join(os.path.dirname(__file__), "fixtures", "setups", name) +def setup() -> Callable[[str], Path]: + def _setup(name: str) -> Path: + return Path(__file__).parent / "fixtures" / "setups" / name return _setup def test_setup_reader_read_first_level_setup_call_with_direct_types( - setup: Callable[[str], str] -): + setup: Callable[[str], Path] +) -> None: result = SetupReader.read_from_directory(setup("flask")) expected_name = "Flask" @@ -58,8 +57,8 @@ def test_setup_reader_read_first_level_setup_call_with_direct_types( def test_setup_reader_read_first_level_setup_call_with_variables( - setup: Callable[[str], str] -): + setup: Callable[[str], Path] +) -> None: result = SetupReader.read_from_directory(setup("requests")) expected_name = None @@ -85,8 +84,8 @@ def test_setup_reader_read_first_level_setup_call_with_variables( def test_setup_reader_read_sub_level_setup_call_with_direct_types( - setup: Callable[[str], str] -): + setup: Callable[[str], Path] +) -> None: result = SetupReader.read_from_directory(setup("sqlalchemy")) expected_name = "SQLAlchemy" @@ -110,7 +109,7 @@ def test_setup_reader_read_sub_level_setup_call_with_direct_types( assert result["python_requires"] is None -def test_setup_reader_read_setup_cfg(setup: Callable[[str], str]): +def test_setup_reader_read_setup_cfg(setup: Callable[[str], Path]) -> None: result = SetupReader.read_from_directory(setup("with-setup-cfg")) expected_name = "with-setup-cfg" @@ -129,12 +128,12 @@ def test_setup_reader_read_setup_cfg(setup: Callable[[str], str]): assert result["python_requires"] == expected_python_requires -def test_setup_reader_read_setup_cfg_with_attr(setup: Callable[[str], str]): +def test_setup_reader_read_setup_cfg_with_attr(setup: Callable[[str], Path]) -> None: with pytest.raises(InvalidVersion): SetupReader.read_from_directory(setup("with-setup-cfg-attr")) -def test_setup_reader_read_setup_kwargs(setup: Callable[[str], str]): +def test_setup_reader_read_setup_kwargs(setup: Callable[[str], Path]) -> None: result = SetupReader.read_from_directory(setup("pendulum")) expected_name = "pendulum" @@ -150,7 +149,7 @@ def test_setup_reader_read_setup_kwargs(setup: Callable[[str], str]): assert result["python_requires"] == expected_python_requires -def test_setup_reader_read_setup_call_in_main(setup: Callable[[str], str]): +def test_setup_reader_read_setup_call_in_main(setup: Callable[[str], Path]) -> None: result = SetupReader.read_from_directory(setup("pyyaml")) expected_name = "PyYAML" @@ -166,7 +165,9 @@ def test_setup_reader_read_setup_call_in_main(setup: Callable[[str], str]): assert result["python_requires"] == expected_python_requires -def test_setup_reader_read_extras_require_with_variables(setup: Callable[[str], str]): +def test_setup_reader_read_extras_require_with_variables( + setup: Callable[[str], Path] +) -> None: result = SetupReader.read_from_directory(setup("extras_require_with_vars")) expected_name = "extras_require_with_vars" @@ -182,7 +183,7 @@ def test_setup_reader_read_extras_require_with_variables(setup: Callable[[str], assert result["python_requires"] == expected_python_requires -def test_setup_reader_setuptools(setup: Callable[[str], str]): +def test_setup_reader_setuptools(setup: Callable[[str], Path]) -> None: result = SetupReader.read_from_directory(setup("setuptools_setup")) expected_name = "my_package"