Factor out shlex.split workaround

This commit is contained in:
Adrian Sampson 2015-11-14 13:17:44 -08:00
parent d5b7ce64da
commit 3a5dd47e3a
2 changed files with 22 additions and 11 deletions

View file

@ -19,7 +19,6 @@ from __future__ import (division, absolute_import, print_function,
import os
import sys
import shlex
import unicodedata
import time
import re
@ -1139,13 +1138,8 @@ def parse_query_string(s, model_cls):
The string is split into components using shell-like syntax.
"""
assert isinstance(s, unicode), "Query is not unicode: {0!r}".format(s)
# A bug in Python < 2.7.3 prevents correct shlex splitting of
# Unicode strings.
# http://bugs.python.org/issue6988
s = s.encode('utf8')
try:
parts = [p.decode('utf8') for p in shlex.split(s)]
parts = util.shlex_split(s)
except ValueError as exc:
raise dbcore.InvalidQueryError(s, exc)
return parse_query_parts(parts, model_cls)

View file

@ -749,6 +749,26 @@ def editor_command():
return open_anything()
def shlex_split(s):
"""Split a Unicode or bytes string according to shell lexing rules.
Raise `ValueError` if the string is not a well-formed shell string.
This is a workaround for a bug in some versions of Python.
"""
if isinstance(s, bytes):
# Shlex works fine.
return shlex.split(s)
elif isinstance(s, unicode):
# Work around a Python bug.
# http://bugs.python.org/issue6988
bs = s.encode('utf8')
return [c.decode('utf8') for c in shlex.split(bs)]
else:
raise TypeError('shlex_split called with non-string')
def interactive_open(targets, command):
"""Open the files in `targets` by `exec`ing a new `command`, given
as a Unicode string. (The new program takes over, and Python
@ -757,15 +777,12 @@ def interactive_open(targets, command):
Can raise `OSError`.
"""
# Split the command string into its arguments.
command = command.encode('utf8')
try:
command = [c.decode('utf8')
for c in shlex.split(command)]
command = shlex_split(command)
except ValueError: # Malformed shell tokens.
command = [command]
command.insert(0, command[0]) # for argv[0]
# Add the explicit arguments.
command += targets
return os.execlp(*command)