safe_shlex_split: Use real lexer object and handle ' correctly.
This commit is contained in:
parent
0c4d15ea5a
commit
1c1534b5f6
@ -98,6 +98,16 @@ def dotted_getattr(obj, path):
|
|||||||
return functools.reduce(getattr, path.split('.'), obj)
|
return functools.reduce(getattr, path.split('.'), obj)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_lexer(s):
|
||||||
|
"""Get an shlex lexer for safe_shlex_split."""
|
||||||
|
if s is None:
|
||||||
|
raise TypeError("Refusing to create a lexer with s=None!")
|
||||||
|
lexer = shlex.shlex(s, posix=True)
|
||||||
|
lexer.whitespace_split = True
|
||||||
|
lexer.commenters = ''
|
||||||
|
return lexer
|
||||||
|
|
||||||
|
|
||||||
def safe_shlex_split(s):
|
def safe_shlex_split(s):
|
||||||
r"""Split a string via shlex safely (don't bail out on unbalanced quotes).
|
r"""Split a string via shlex safely (don't bail out on unbalanced quotes).
|
||||||
|
|
||||||
@ -113,24 +123,22 @@ def safe_shlex_split(s):
|
|||||||
|
|
||||||
We try 3 times so multiple errors can be fixed.
|
We try 3 times so multiple errors can be fixed.
|
||||||
"""
|
"""
|
||||||
if s is None:
|
|
||||||
raise TypeError("Can't split None!")
|
|
||||||
tokens = None
|
tokens = None
|
||||||
orig_s = s
|
orig_s = s
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
|
lexer = _get_lexer(s)
|
||||||
try:
|
try:
|
||||||
tokens = shlex.split(s)
|
tokens = list(lexer)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
if str(e) == "No closing quotation":
|
if str(e) not in ("No closing quotation", "No escaped character"):
|
||||||
# e.g. eggs "bacon ham
|
|
||||||
# -> we fix this as eggs "bacon ham"
|
|
||||||
s += '"'
|
|
||||||
elif str(e) == "No escaped character":
|
|
||||||
# e.g. eggs\
|
|
||||||
# -> we fix this as eggs\\
|
|
||||||
s += '\\'
|
|
||||||
else:
|
|
||||||
raise
|
raise
|
||||||
|
# eggs "bacon ham -> eggs "bacon ham"
|
||||||
|
# eggs\ -> eggs\\
|
||||||
|
if lexer.state not in "\"'\\":
|
||||||
|
raise AssertionError(
|
||||||
|
"Lexer state is >{}< while parsing >{}< (attempted fixup: "
|
||||||
|
">{}<)".format(lexer.state, orig_s, s))
|
||||||
|
s += lexer.state
|
||||||
if tokens is None:
|
if tokens is None:
|
||||||
raise AssertionError("Gave up splitting >{}< after {} tries. "
|
raise AssertionError("Gave up splitting >{}< after {} tries. "
|
||||||
"Attempted fixup: >{}<. This is a bug.".format(
|
"Attempted fixup: >{}<. This is a bug.".format(
|
||||||
|
Loading…
Reference in New Issue
Block a user