From 448bde6869b837aa361934b82fc17da2f62b3b88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Natal=20Ng=C3=A9tal?= Date: Mon, 3 Dec 2018 19:53:31 +0100 Subject: [PATCH] bpo-25567: Add the support of bytes in quotes. Add the support of bytes in quotes method in shlex module. Co-authored-by: Nan Wu --- Doc/library/shlex.rst | 9 ++++++--- Lib/shlex.py | 12 +++++++++--- Lib/test/test_shlex.py | 5 +++++ .../Library/2018-12-04-16-15-06.bpo-25567.5krN3D.rst | 1 + 4 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2018-12-04-16-15-06.bpo-25567.5krN3D.rst diff --git a/Doc/library/shlex.rst b/Doc/library/shlex.rst index fb335c69006816..bcbbc02a8d4a9f 100644 --- a/Doc/library/shlex.rst +++ b/Doc/library/shlex.rst @@ -39,9 +39,12 @@ 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. + + .. versionchanged:: 3.8 + The *s* parameter can be a bytes object. This idiom would be unsafe: diff --git a/Lib/shlex.py b/Lib/shlex.py index 2c9786c517a350..87634cc5efd87c 100644 --- a/Lib/shlex.py +++ b/Lib/shlex.py @@ -306,17 +306,23 @@ def split(s, comments=False, posix=True): _find_unsafe = re.compile(r'[^\w@%+=:,./-]', re.ASCII).search +_find_unsafe_bytes = re.compile(b'[^\w@%+=:,./-]').search def quote(s): """Return a shell-escaped version of the string *s*.""" if not s: return "''" - 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("'", "'\"'\"'") + "'" + if isinstance(s, bytes): + if _find_unsafe_bytes(s) is None: + return s + return b"'" + s.replace(b"'", b"'\"'\"'") + b"'" + else: + if _find_unsafe(s) is None: + return s + return "'" + s.replace("'", "'\"'\"'") + "'" def _print_tokens(lexer): diff --git a/Lib/test/test_shlex.py b/Lib/test/test_shlex.py index fd35788e81b272..c47380682c1713 100644 --- a/Lib/test/test_shlex.py +++ b/Lib/test/test_shlex.py @@ -304,9 +304,14 @@ def testQuote(self): 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): diff --git a/Misc/NEWS.d/next/Library/2018-12-04-16-15-06.bpo-25567.5krN3D.rst b/Misc/NEWS.d/next/Library/2018-12-04-16-15-06.bpo-25567.5krN3D.rst new file mode 100644 index 00000000000000..de9ba60e480224 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-12-04-16-15-06.bpo-25567.5krN3D.rst @@ -0,0 +1 @@ +Add the bytes support the the :func:`shlex.quote` function.