Repository: pypa/pipenv

Issue:
Pipenv breaks on Windows paths with spaces. 
```bash
Micaiah Parker@COMPUTERNAME MINGW64 ~
$ cd project/

Micaiah Parker@COMPUTERNAME MINGW64 ~/project (master)
$ pipenv install --dev pytest
Installing pytest▒

Error:  An error occurred while installing pytest!
'C:\Users\Micaiah' is not recognized as an internal or external command,
operable program or batch file.
```

I noticed that `utils` does have a `get_windows_path`, but I couldn't find where it is being used.


Discussion:
Pipenv doesn’t actually break windows paths with spaces, it only breaks windows paths with spaces when using MINGW/MSYS/bash emulators. I think I know how to fix this but may not get to it today depending on how the day goes, but essentially we need to quadruple escape spaces or use the altsep to join paths 



> On Oct 9, 2017, at 8:08 AM, Micaiah Parker <notifications@github.com> wrote:
> 
> Micaiah Parker@COMPUTERNAME MINGW64 ~
> $ cd project/
> 
> Micaiah Parker@COMPUTERNAME MINGW64 ~/project (master)
> $ pipenv install --dev pytest
> Installing pytest▒
> 
> Error:  An error occurred while installing pytest!
> 'C:\Users\Micaiah' is not recognized as an internal or external command,
> operable program or batch file.
> I noticed that utils does have a get_windows_path, but I couldn't find where it is being used.
> 
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub, or mute the thread.
> 

When I got home I tried it from the default Command Prompt and still got the same issue

```
C:\Users\Micaiah Parker\project>pipenv install --dev pytest
Installing pytest…

Error:  An error occurred while installing pytest!
'C:\Users\Micaiah' is not recognized as an internal or external command,
operable program or batch file.
```


Resolving patch:
diff --git a/pipenv/utils.py b/pipenv/utils.py
--- a/pipenv/utils.py
+++ b/pipenv/utils.py
@@ -340,6 +340,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("'", "'\\''") + '"'
 
@@ -850,8 +853,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):


Test patch:
diff --git a/tests/test_utils.py b/tests/test_utils.py
--- 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 @@ def test_python_version_output_variants(self, mocked_delegator, version_output,
         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