diff --git a/Doc/library/shlex.rst b/Doc/library/shlex.rst index e40a10d..edd9d55 100644 --- a/Doc/library/shlex.rst +++ b/Doc/library/shlex.rst @@ -38,9 +38,9 @@ The :mod:`shlex` module defines the following functions: .. function:: quote(s) - Return a shell-escaped version of the string *s*. The returned value is a - string that can safely be used as one token in a shell command line, for - cases where you cannot use a list. + Return a shell-escaped version of the string *s* or the bytes object. The + returned value is a string literal or bytes that can safely be used as one + token in a shell command line, for cases where you cannot use a list. This idiom would be unsafe:: diff --git a/Lib/shlex.py b/Lib/shlex.py index 1a6d76a..30ef43c 100644 --- a/Lib/shlex.py +++ b/Lib/shlex.py @@ -274,17 +274,23 @@ def split(s, comments=False, posix=True): _find_unsafe = re.compile(r'[^\w@%+=:,./-]', re.ASCII).search +_find_unsafe_bytes = re.compile(rb'[^\w@%+=:,./-]', re.ASCII).search def quote(s): """Return a shell-escaped version of the string or the bytes.""" if not s: return "b''" if isinstance(s, bytes) else "''" - if _find_unsafe(s) is None: - return s + + if isinstance(s, bytes): + if _find_unsafe_bytes(s) is None: + return s + else: + if _find_unsafe(s) is None: + return s # use single quotes, and put single quotes into double quotes # the string $'b is then quoted as '$'"'"'b' - return "'" + s.replace("'", "'\"'\"'") + "'" + return b"'" + s.replace(b"'", b"'\"'\"'") + b"'" if isinstance(s, bytes) else "'" + s.replace("'", "'\"'\"'") + "'" def _print_tokens(lexer): diff --git a/Lib/test/test_shlex.py b/Lib/test/test_shlex.py index 4fafdd4..6483ef1 100644 --- a/Lib/test/test_shlex.py +++ b/Lib/test/test_shlex.py @@ -184,9 +184,14 @@ class ShlexTest(unittest.TestCase): for u in unsafe: self.assertEqual(shlex.quote('test%sname' % u), "'test%sname'" % u) + self.assertEqual(shlex.quote(b'test%sname' % u.encode('utf-8')), + b"'test%sname'" % u.encode('utf-8')) + for u in unsafe: self.assertEqual(shlex.quote("test%s'name'" % u), "'test%s'\"'\"'name'\"'\"''" % u) + self.assertEqual(shlex.quote(b"test%s'name'" % u.encode('utf-8')), + b"'test%s'\"'\"'name'\"'\"''" % u.encode('utf-8')) # Allow this test to be used with old shlex.py if not getattr(shlex, "split", None):