diff --git a/src/virtualenv/dirs.py b/src/virtualenv/dirs.py index 50919eabd..0a2db11e1 100644 --- a/src/virtualenv/dirs.py +++ b/src/virtualenv/dirs.py @@ -1,4 +1,5 @@ import os +import tempfile from appdirs import user_config_dir, user_data_dir @@ -23,9 +24,23 @@ def _get_default_data_folder(): folder = os.environ[key] else: folder = user_data_dir(appname="virtualenv", appauthor="pypa") + + if not _writable(folder): + folder = os.path.join(tempfile.gettempdir(), "virtualenv") return folder +def _writable(folder) -> bool: + head = os.path.normpath(folder) + + while not (os.path.exists(head) and os.access(head, os.W_OK)): + head, tail = os.path.split(head) + if not tail: + return False + + return True + + def default_config_dir(): from virtualenv.util.path import Path diff --git a/tests/unit/test_dirs.py b/tests/unit/test_dirs.py new file mode 100644 index 000000000..b6da6b5cb --- /dev/null +++ b/tests/unit/test_dirs.py @@ -0,0 +1,31 @@ +import logging +import os +import tempfile + +import appdirs + +from virtualenv import dirs +from virtualenv.dirs import _get_default_data_folder + + +def test_get_default_data_dir(monkeypatch): + # given + data_dirs = { + "/.local/share": os.path.join(tempfile.gettempdir(), "virtualenv"), + os.getenv('HOME'): os.path.join(os.getenv('HOME'), "virtualenv"), + "/tmp/share/": os.path.join("/tmp/share", "virtualenv") + } + + def user_data_dir(data_dir): + def wrapper(appname=None, appauthor=None, version=None, roaming=False): + return os.path.join(data_dir, appname) + return wrapper + + for data_dir, expected in data_dirs.items(): + monkeypatch.setattr(dirs, "user_data_dir", user_data_dir(data_dir)) + + # when + actual = _get_default_data_folder() + + # then + assert actual == expected