diff --git a/dvc/utils/__init__.py b/dvc/utils/__init__.py index 864c9e5f56..a7e9ab5f42 100644 --- a/dvc/utils/__init__.py +++ b/dvc/utils/__init__.py @@ -152,9 +152,12 @@ def makedirs(path, exist_ok=False, mode=None): _makedirs(path, exist_ok=exist_ok) return - umask = os.umask(0) + # utilize umask to set proper permissions since Python 3.7 the `mode` + # `makedirs` argument no longer affects the file permission bits of + # newly-created intermediate-level directories. + umask = os.umask(0o777 - mode) try: - _makedirs(path, exist_ok=exist_ok, mode=mode) + _makedirs(path, exist_ok=exist_ok) finally: os.umask(umask) diff --git a/dvc/utils/compat.py b/dvc/utils/compat.py index 7d66dd090c..4863e4a565 100644 --- a/dvc/utils/compat.py +++ b/dvc/utils/compat.py @@ -85,8 +85,6 @@ def _makedirs(name, mode=0o777, exist_ok=False): if e.errno != errno.EEXIST: raise cdir = os.curdir - if isinstance(tail, bytes): - cdir = bytes(os.curdir, "ASCII") if tail == cdir: return try: diff --git a/tests/func/test_utils.py b/tests/func/test_utils.py index 73f489e252..594fdc332d 100644 --- a/tests/func/test_utils.py +++ b/tests/func/test_utils.py @@ -1,6 +1,10 @@ +# encoding: utf-8 import filecmp import os import shutil +import stat + +import pytest from dvc import utils from tests.basic_env import TestDvc @@ -69,3 +73,18 @@ def test_boxify(self): ) assert expected == utils.boxify("message") + + +@pytest.mark.skipif(os.name == "nt", reason="Not supported for Windows.") +def test_makedirs_permissions(tmpdir): + dir_mode = 0o755 + os.chdir(str(tmpdir)) + intermediate_dir = "тестовая-директория" + test_dir = os.path.join(intermediate_dir, "data") + + assert not os.path.exists(intermediate_dir) + + utils.makedirs(test_dir, mode=dir_mode) + + assert stat.S_IMODE(os.stat(test_dir).st_mode) == dir_mode + assert stat.S_IMODE(os.stat(intermediate_dir).st_mode) == dir_mode