diff --git a/CHANGELOG.md b/CHANGELOG.md index 50037843e3..9740f84cf6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## dev +- Delete directories directly instead of spawning rmdir on Windows +- Fix "Failed to delete" error when using Microsoft Store Python +- Fix "No pyvenv.cfg file" error when using Microsoft Store Python (#1164) - Add `--quiet` and `--verbose` options for the `pipx` subcommands - [docs] Add Scoop installation instructions - Add ability to install multiple packages at once diff --git a/src/pipx/util.py b/src/pipx/util.py index b2c340818f..3e899aa69e 100644 --- a/src/pipx/util.py +++ b/src/pipx/util.py @@ -54,10 +54,7 @@ def rmdir(path: Path, safe_rm: bool = True) -> None: logger.info(f"removing directory {path}") try: - if WINDOWS: - os.system(f'rmdir /S /Q "{str(path)}"') - else: - shutil.rmtree(path) + shutil.rmtree(path) except FileNotFoundError: pass @@ -171,6 +168,14 @@ def run_subprocess( logger.info(f"running {log_cmd_str}") # windows cannot take Path objects, only strings cmd_str_list = [str(c) for c in cmd] + # Make sure to call the binary using its real path. This matters especially on Windows when using the packaged app + # (Microsoft Store) version of Python, which uses path redirection for sandboxing. If the path to the executable is + # redirected, the executable can get confused as to which directory it's being run from, leading to problems. + # See https://github.com/pypa/pipx/issues/1164 + # Conversely, if the binary is a symlink, then we should NOT use the real path, as Python expects to receive the + # symlink in argv[0] so that it can locate the venv. + if not os.path.islink(cmd_str_list[0]): + cmd_str_list[0] = os.path.realpath(cmd_str_list[0]) completed_process = subprocess.run( cmd_str_list, env=env,