From fc8e412fa8fe524ab3f112f02e865aa42608388b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Kul=C3=ADk?= Date: Thu, 27 Apr 2023 18:52:38 +0200 Subject: [PATCH] prevent PermissionError when using venv creator on some systems (#2543) Cherry-picked from 0597a2f8ab32705b86a25dbd1d42fd30c3033061 --- docs/changelog/2543.bugfix.rst | 2 ++ src/virtualenv/activation/via_template.py | 4 ++++ tests/unit/create/test_creator.py | 22 ++++++++++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 docs/changelog/2543.bugfix.rst diff --git a/docs/changelog/2543.bugfix.rst b/docs/changelog/2543.bugfix.rst new file mode 100644 index 0000000..5f0d6ca --- /dev/null +++ b/docs/changelog/2543.bugfix.rst @@ -0,0 +1,2 @@ +Prevent ``PermissionError`` when using venv creator on systems that deliver files without user write +permission - by :user:`kulikjak`. diff --git a/src/virtualenv/activation/via_template.py b/src/virtualenv/activation/via_template.py index 069d52e..cc9dbda 100644 --- a/src/virtualenv/activation/via_template.py +++ b/src/virtualenv/activation/via_template.py @@ -41,6 +41,10 @@ class ViaTemplateActivator(Activator, metaclass=ABCMeta): for template in templates: text = self.instantiate_template(replacements, template, creator) dest = to_folder / self.as_name(template) + # remove the file if it already exists - this prevents permission + # errors when the dest is not writable + if dest.exists(): + dest.unlink() # use write_bytes to avoid platform specific line normalization (\n -> \r\n) dest.write_bytes(text.encode("utf-8")) generated.append(dest) diff --git a/tests/unit/create/test_creator.py b/tests/unit/create/test_creator.py index ea61ed0..0ec6d62 100644 --- a/tests/unit/create/test_creator.py +++ b/tests/unit/create/test_creator.py @@ -690,3 +690,25 @@ def test_py_pyc_missing(tmp_path, mocker, py, pyc): pyc_at = Python2.from_stdlib(Python2.mappings(CURRENT), "osc.py")[1](result.creator, Path("os.pyc")) assert pyc_at.exists() is pyc + + +# Make sure that the venv creator works on systems where vendor-delivered files +# (specifically venv scripts delivered with Python itself) are not writable. +# +# https://github.com/pypa/virtualenv/issues/2419 +@pytest.mark.skipif("venv" not in CURRENT_CREATORS, reason="test needs venv creator") +def test_venv_creator_without_write_perms(tmp_path, mocker): + from virtualenv.run.session import Session + + prev = Session._create + + def func(self): + prev(self) + scripts_dir = self.creator.dest / "bin" + for script in scripts_dir.glob("*ctivate*"): + script.chmod(stat.S_IREAD | stat.S_IRGRP | stat.S_IROTH) + + mocker.patch("virtualenv.run.session.Session._create", side_effect=func, autospec=True) + + cmd = [str(tmp_path), "--seeder", "app-data", "--without-pip", "--creator", "venv"] + cli_run(cmd) -- 2.40.0