diff --git a/pipenv/utils.py b/pipenv/utils.py index 4b97c4ea..33f4e0c7 100644 --- a/pipenv/utils.py +++ b/pipenv/utils.py @@ -341,6 +341,9 @@ def shellquote(s): """Prepares a string for the shell (on Windows too!)""" if s is None: return None + # Additional escaping for windows paths + if os.name == 'nt': + s = "{}".format(s.replace("\\", "\\\\")) return '"' + s.replace("'", "'\\''") + '"' @@ -851,8 +854,7 @@ def get_windows_path(*args): """Sanitize a path for windows environments Accepts an arbitrary list of arguments and makes a clean windows path""" - clean_path = os.path.join(*args) - return os.path.normpath(clean_path) + return os.path.normpath(os.path.join(*args)) def find_windows_executable(bin_path, exe_name): diff --git a/tests/test_utils.py b/tests/test_utils.py index e68d9888..176e94ef 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- +import os import pytest from mock import patch, Mock @@ -165,3 +166,10 @@ class TestUtils: run_ret.out = version_output mocked_delegator.return_value = run_ret assert pipenv.utils.python_version('some/path') == version + + @pytest.mark.windows + @pytest.mark.skipif(os.name != 'nt', reason='Windows test only') + def test_windows_shellquote(self): + test_path = 'C:\Program Files\Python36\python.exe' + expected_path = '"C:\\\\Program Files\\\\Python36\\\\python.exe"' + assert pipenv.utils.shellquote(test_path) == expected_path