Repository: pallets/click (python)

Issue:
echo_via_pager broken on Windows in 7.1
Calls to `click.echo_via_pager` are failing on Windows since upgrading to 7.1 

### Expected behavior (7.0)
```
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import click
>>> click.__version__
'7.0'
>>> text = [f"hello {i} \n" for i in range(1000)]
>>> click.echo_via_pager(text)
hello 0
hello 1
hello 2
hello 3
hello 4
-- MORE --
```

### Actual behavior (7.1)
```
Python 3.8.1 (tags/v3.8.1:1b293b6, Dec 18 2019, 23:11:46) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import click
>>> click.__version__
'7.1.1'
>>> text = [f"hello {i} \n" for i in range(1000)]
>>> click.echo_via_pager(text)
The system cannot find the file specified.
>>>
```

## Notes
- Only seems broken on Windows: tested with Ubuntu WSL and click 7.1, works as expected


### Environment

* Python version: 3.7, 3.8 (same results)
* Click version: 7.1.1


Pull request:
Revert "Use shlex.quote for quoting shell arguments"
This caused issues if the pager/editor command had options like `less -FRSX`, they would then get quoted as a single word rather than `less` then `-FRSX`.

`shlex.quote` doesn't seem to do the right thing on Windows cmd. Using `shlex.split` on the command first wouldn't help, as it would need to get re-joined and `subprocess.list2cmdline` is not an external API. Let's hold off until #1476 instead.

Reverts #1470
Closes #1514 

Patch:
diff --git a/src/click/_compat.py b/src/click/_compat.py
index ed57a18..60cb115 100644
--- a/src/click/_compat.py
+++ b/src/click/_compat.py
@@ -174,8 +174,6 @@ if PY2:
     iteritems = lambda x: x.iteritems()
     range_type = xrange
 
-    from pipes import quote as shlex_quote
-
     def is_bytes(x):
         return isinstance(x, (buffer, bytearray))
 
@@ -284,8 +282,6 @@ else:
     isidentifier = lambda x: x.isidentifier()
     iteritems = lambda x: iter(x.items())
 
-    from shlex import quote as shlex_quote
-
     def is_bytes(x):
         return isinstance(x, (bytes, memoryview, bytearray))
 
diff --git a/src/click/_termui_impl.py b/src/click/_termui_impl.py
index c6e86cc..88bec37 100644
--- a/src/click/_termui_impl.py
+++ b/src/click/_termui_impl.py
@@ -17,7 +17,6 @@ from ._compat import int_types
 from ._compat import isatty
 from ._compat import open_stream
 from ._compat import range_type
-from ._compat import shlex_quote
 from ._compat import strip_ansi
 from ._compat import term_len
 from ._compat import WIN
@@ -346,10 +345,7 @@ def pager(generator, color=None):
     fd, filename = tempfile.mkstemp()
     os.close(fd)
     try:
-        if (
-            hasattr(os, "system")
-            and os.system("more {}".format(shlex_quote(filename))) == 0
-        ):
+        if hasattr(os, "system") and os.system('more "{}"'.format(filename)) == 0:
             return _pipepager(generator, "more", color)
         return _nullpager(stdout, generator, color)
     finally:
@@ -418,7 +414,7 @@ def _tempfilepager(generator, cmd, color):
     with open_stream(filename, "wb")[0] as f:
         f.write(text.encode(encoding))
     try:
-        os.system("{} {}".format(shlex_quote(cmd), shlex_quote(filename)))
+        os.system('{} "{}"'.format(cmd, filename))
     finally:
         os.unlink(filename)
 
@@ -463,9 +459,7 @@ class Editor(object):
             environ = None
         try:
             c = subprocess.Popen(
-                "{} {}".format(shlex_quote(editor), shlex_quote(filename)),
-                env=environ,
-                shell=True,
+                '{} "{}"'.format(editor, filename), env=environ, shell=True,
             )
             exit_code = c.wait()
             if exit_code != 0:
@@ -536,16 +530,18 @@ def open_url(url, wait=False, locate=False):
     elif WIN:
         if locate:
             url = _unquote_file(url)
-            args = "explorer /select,{}".format(shlex_quote(url))
+            args = 'explorer /select,"{}"'.format(_unquote_file(url.replace('"', "")))
         else:
-            args = 'start {} "" {}'.format("/WAIT" if wait else "", shlex_quote(url))
+            args = 'start {} "" "{}"'.format(
+                "/WAIT" if wait else "", url.replace('"', "")
+            )
         return os.system(args)
     elif CYGWIN:
         if locate:
             url = _unquote_file(url)
-            args = "cygstart {}".format(shlex_quote(os.path.dirname(url)))
+            args = 'cygstart "{}"'.format(os.path.dirname(url).replace('"', ""))
         else:
-            args = "cygstart {} {}".format("-w" if wait else "", shlex_quote(url))
+            args = 'cygstart {} "{}"'.format("-w" if wait else "", url.replace('"', ""))
         return os.system(args)
 
     try:


Test patch:
diff --git a/tests/test_imports.py b/tests/test_imports.py
index b99d453..e309eac 100644
--- a/tests/test_imports.py
+++ b/tests/test_imports.py
@@ -49,7 +49,6 @@ ALLOWED_IMPORTS = {
     "fcntl",
     "datetime",
     "pipes",
-    "shlex",
 }
 
 if WIN: