mirror of
https://github.com/python/cpython.git
synced 2025-08-30 21:48:47 +00:00

This function used to live as pipes.quote, where it was undocumented but used anyway. (An alias still exists for backward compatibility.) The tests have been moved as is, but the code of the function was changed to use a regex instead of a loop with string comparisons (at Ian Bicking’s suggestion). I’m terrible at regexes, so any feedback is welcome.
202 lines
5.7 KiB
Python
202 lines
5.7 KiB
Python
import io
|
|
import shlex
|
|
import string
|
|
import unittest
|
|
|
|
from test import support
|
|
|
|
|
|
# The original test data set was from shellwords, by Hartmut Goebel.
|
|
|
|
data = r"""x|x|
|
|
foo bar|foo|bar|
|
|
foo bar|foo|bar|
|
|
foo bar |foo|bar|
|
|
foo bar bla fasel|foo|bar|bla|fasel|
|
|
x y z xxxx|x|y|z|xxxx|
|
|
\x bar|\|x|bar|
|
|
\ x bar|\|x|bar|
|
|
\ bar|\|bar|
|
|
foo \x bar|foo|\|x|bar|
|
|
foo \ x bar|foo|\|x|bar|
|
|
foo \ bar|foo|\|bar|
|
|
foo "bar" bla|foo|"bar"|bla|
|
|
"foo" "bar" "bla"|"foo"|"bar"|"bla"|
|
|
"foo" bar "bla"|"foo"|bar|"bla"|
|
|
"foo" bar bla|"foo"|bar|bla|
|
|
foo 'bar' bla|foo|'bar'|bla|
|
|
'foo' 'bar' 'bla'|'foo'|'bar'|'bla'|
|
|
'foo' bar 'bla'|'foo'|bar|'bla'|
|
|
'foo' bar bla|'foo'|bar|bla|
|
|
blurb foo"bar"bar"fasel" baz|blurb|foo"bar"bar"fasel"|baz|
|
|
blurb foo'bar'bar'fasel' baz|blurb|foo'bar'bar'fasel'|baz|
|
|
""|""|
|
|
''|''|
|
|
foo "" bar|foo|""|bar|
|
|
foo '' bar|foo|''|bar|
|
|
foo "" "" "" bar|foo|""|""|""|bar|
|
|
foo '' '' '' bar|foo|''|''|''|bar|
|
|
\""|\|""|
|
|
"\"|"\"|
|
|
"foo\ bar"|"foo\ bar"|
|
|
"foo\\ bar"|"foo\\ bar"|
|
|
"foo\\ bar\"|"foo\\ bar\"|
|
|
"foo\\" bar\""|"foo\\"|bar|\|""|
|
|
"foo\\ bar\" dfadf"|"foo\\ bar\"|dfadf"|
|
|
"foo\\\ bar\" dfadf"|"foo\\\ bar\"|dfadf"|
|
|
"foo\\\x bar\" dfadf"|"foo\\\x bar\"|dfadf"|
|
|
"foo\x bar\" dfadf"|"foo\x bar\"|dfadf"|
|
|
\''|\|''|
|
|
'foo\ bar'|'foo\ bar'|
|
|
'foo\\ bar'|'foo\\ bar'|
|
|
"foo\\\x bar\" df'a\ 'df'|"foo\\\x bar\"|df'a|\|'df'|
|
|
\"foo"|\|"foo"|
|
|
\"foo"\x|\|"foo"|\|x|
|
|
"foo\x"|"foo\x"|
|
|
"foo\ "|"foo\ "|
|
|
foo\ xx|foo|\|xx|
|
|
foo\ x\x|foo|\|x|\|x|
|
|
foo\ x\x\""|foo|\|x|\|x|\|""|
|
|
"foo\ x\x"|"foo\ x\x"|
|
|
"foo\ x\x\\"|"foo\ x\x\\"|
|
|
"foo\ x\x\\""foobar"|"foo\ x\x\\"|"foobar"|
|
|
"foo\ x\x\\"\''"foobar"|"foo\ x\x\\"|\|''|"foobar"|
|
|
"foo\ x\x\\"\'"fo'obar"|"foo\ x\x\\"|\|'"fo'|obar"|
|
|
"foo\ x\x\\"\'"fo'obar" 'don'\''t'|"foo\ x\x\\"|\|'"fo'|obar"|'don'|\|''|t'|
|
|
'foo\ bar'|'foo\ bar'|
|
|
'foo\\ bar'|'foo\\ bar'|
|
|
foo\ bar|foo|\|bar|
|
|
foo#bar\nbaz|foobaz|
|
|
:-) ;-)|:|-|)|;|-|)|
|
|
áéíóú|á|é|í|ó|ú|
|
|
"""
|
|
|
|
posix_data = r"""x|x|
|
|
foo bar|foo|bar|
|
|
foo bar|foo|bar|
|
|
foo bar |foo|bar|
|
|
foo bar bla fasel|foo|bar|bla|fasel|
|
|
x y z xxxx|x|y|z|xxxx|
|
|
\x bar|x|bar|
|
|
\ x bar| x|bar|
|
|
\ bar| bar|
|
|
foo \x bar|foo|x|bar|
|
|
foo \ x bar|foo| x|bar|
|
|
foo \ bar|foo| bar|
|
|
foo "bar" bla|foo|bar|bla|
|
|
"foo" "bar" "bla"|foo|bar|bla|
|
|
"foo" bar "bla"|foo|bar|bla|
|
|
"foo" bar bla|foo|bar|bla|
|
|
foo 'bar' bla|foo|bar|bla|
|
|
'foo' 'bar' 'bla'|foo|bar|bla|
|
|
'foo' bar 'bla'|foo|bar|bla|
|
|
'foo' bar bla|foo|bar|bla|
|
|
blurb foo"bar"bar"fasel" baz|blurb|foobarbarfasel|baz|
|
|
blurb foo'bar'bar'fasel' baz|blurb|foobarbarfasel|baz|
|
|
""||
|
|
''||
|
|
foo "" bar|foo||bar|
|
|
foo '' bar|foo||bar|
|
|
foo "" "" "" bar|foo||||bar|
|
|
foo '' '' '' bar|foo||||bar|
|
|
\"|"|
|
|
"\""|"|
|
|
"foo\ bar"|foo\ bar|
|
|
"foo\\ bar"|foo\ bar|
|
|
"foo\\ bar\""|foo\ bar"|
|
|
"foo\\" bar\"|foo\|bar"|
|
|
"foo\\ bar\" dfadf"|foo\ bar" dfadf|
|
|
"foo\\\ bar\" dfadf"|foo\\ bar" dfadf|
|
|
"foo\\\x bar\" dfadf"|foo\\x bar" dfadf|
|
|
"foo\x bar\" dfadf"|foo\x bar" dfadf|
|
|
\'|'|
|
|
'foo\ bar'|foo\ bar|
|
|
'foo\\ bar'|foo\\ bar|
|
|
"foo\\\x bar\" df'a\ 'df"|foo\\x bar" df'a\ 'df|
|
|
\"foo|"foo|
|
|
\"foo\x|"foox|
|
|
"foo\x"|foo\x|
|
|
"foo\ "|foo\ |
|
|
foo\ xx|foo xx|
|
|
foo\ x\x|foo xx|
|
|
foo\ x\x\"|foo xx"|
|
|
"foo\ x\x"|foo\ x\x|
|
|
"foo\ x\x\\"|foo\ x\x\|
|
|
"foo\ x\x\\""foobar"|foo\ x\x\foobar|
|
|
"foo\ x\x\\"\'"foobar"|foo\ x\x\'foobar|
|
|
"foo\ x\x\\"\'"fo'obar"|foo\ x\x\'fo'obar|
|
|
"foo\ x\x\\"\'"fo'obar" 'don'\''t'|foo\ x\x\'fo'obar|don't|
|
|
"foo\ x\x\\"\'"fo'obar" 'don'\''t' \\|foo\ x\x\'fo'obar|don't|\|
|
|
'foo\ bar'|foo\ bar|
|
|
'foo\\ bar'|foo\\ bar|
|
|
foo\ bar|foo bar|
|
|
foo#bar\nbaz|foo|baz|
|
|
:-) ;-)|:-)|;-)|
|
|
áéíóú|áéíóú|
|
|
"""
|
|
|
|
class ShlexTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.data = [x.split("|")[:-1]
|
|
for x in data.splitlines()]
|
|
self.posix_data = [x.split("|")[:-1]
|
|
for x in posix_data.splitlines()]
|
|
for item in self.data:
|
|
item[0] = item[0].replace(r"\n", "\n")
|
|
for item in self.posix_data:
|
|
item[0] = item[0].replace(r"\n", "\n")
|
|
|
|
def splitTest(self, data, comments):
|
|
for i in range(len(data)):
|
|
l = shlex.split(data[i][0], comments=comments)
|
|
self.assertEqual(l, data[i][1:],
|
|
"%s: %s != %s" %
|
|
(data[i][0], l, data[i][1:]))
|
|
|
|
def oldSplit(self, s):
|
|
ret = []
|
|
lex = shlex.shlex(io.StringIO(s))
|
|
tok = lex.get_token()
|
|
while tok:
|
|
ret.append(tok)
|
|
tok = lex.get_token()
|
|
return ret
|
|
|
|
def testSplitPosix(self):
|
|
"""Test data splitting with posix parser"""
|
|
self.splitTest(self.posix_data, comments=True)
|
|
|
|
def testCompat(self):
|
|
"""Test compatibility interface"""
|
|
for i in range(len(self.data)):
|
|
l = self.oldSplit(self.data[i][0])
|
|
self.assertEqual(l, self.data[i][1:],
|
|
"%s: %s != %s" %
|
|
(self.data[i][0], l, self.data[i][1:]))
|
|
|
|
def testQuote(self):
|
|
safeunquoted = string.ascii_letters + string.digits + '@%_-+=:,./'
|
|
unsafe = '"`$\\!'
|
|
|
|
self.assertEqual(shlex.quote(''), "''")
|
|
self.assertEqual(shlex.quote(safeunquoted), safeunquoted)
|
|
self.assertEqual(shlex.quote('test file name'), "'test file name'")
|
|
for u in unsafe:
|
|
self.assertEqual(shlex.quote('test%sname' % u),
|
|
"'test%sname'" % u)
|
|
for u in unsafe:
|
|
self.assertEqual(shlex.quote("test%s'name'" % u),
|
|
"'test%s'\"'\"'name'\"'\"''" % u)
|
|
|
|
|
|
# Allow this test to be used with old shlex.py
|
|
if not getattr(shlex, "split", None):
|
|
for methname in dir(ShlexTest):
|
|
if methname.startswith("test") and methname != "testCompat":
|
|
delattr(ShlexTest, methname)
|
|
|
|
def test_main():
|
|
support.run_unittest(ShlexTest)
|
|
|
|
if __name__ == "__main__":
|
|
test_main()
|