Merged revisions 79822,79828,79862,80067,80069,80080-80081,80084,80432-80433 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r79822 | georg.brandl | 2010-04-06 08:18:15 +0000 (Di, 06 Apr 2010) | 1 line

  #8320: document return value of recv_into().
........
  r79828 | georg.brandl | 2010-04-06 14:33:44 +0000 (Di, 06 Apr 2010) | 1 line

  Add JP.
........
  r79862 | georg.brandl | 2010-04-06 20:27:59 +0000 (Di, 06 Apr 2010) | 1 line

  Fix syntax.
........
  r80067 | georg.brandl | 2010-04-14 08:53:38 +0000 (Mi, 14 Apr 2010) | 1 line

  #5341: typo.
........
  r80069 | georg.brandl | 2010-04-14 13:50:31 +0000 (Mi, 14 Apr 2010) | 1 line

  Add an x-ref to where the O_ constants are documented and move the SEEK_ constants after lseek().
........
  r80080 | georg.brandl | 2010-04-14 19:16:38 +0000 (Mi, 14 Apr 2010) | 1 line

  #8399: add note about Windows and O_BINARY.
........
  r80081 | georg.brandl | 2010-04-14 21:34:44 +0000 (Mi, 14 Apr 2010) | 1 line

  #5250: document __instancecheck__ and __subclasscheck__.  I hope the part about the class/metaclass distinction is understandable.
........
  r80084 | georg.brandl | 2010-04-14 21:46:45 +0000 (Mi, 14 Apr 2010) | 1 line

  Fix missing.
........
  r80432 | georg.brandl | 2010-04-24 08:56:58 +0000 (Sa, 24 Apr 2010) | 1 line

  Markup fixes.
........
  r80433 | georg.brandl | 2010-04-24 09:08:10 +0000 (Sa, 24 Apr 2010) | 1 line

  #7507: quote "!" in pipes.quote(); it is a special character for some shells.
........
diff --git a/Lib/pipes.py b/Lib/pipes.py
index 25e9915..02e1257 100644
--- a/Lib/pipes.py
+++ b/Lib/pipes.py
@@ -263,11 +263,11 @@
 
 # Reliably quote a string as a single argument for /bin/sh
 
-_safechars = string.ascii_letters + string.digits + '!@%_-+=:,./' # Safe unquoted
-_funnychars = '"`$\\'                           # Unsafe inside "double quotes"
+# Safe unquoted
+_safechars = frozenset(string.ascii_letters + string.digits + '@%_-+=:,./')
 
 def quote(file):
-    ''' return a shell-escaped version of the file string '''
+    """Return a shell-escaped version of the file string."""
     for c in file:
         if c not in _safechars:
             break
@@ -275,11 +275,6 @@
         if not file:
             return "''"
         return file
-    if '\'' not in file:
-        return '\'' + file + '\''
-    res = ''
-    for c in file:
-        if c in _funnychars:
-            c = '\\' + c
-        res = res + c
-    return '"' + res + '"'
+    # use single quotes, and put single quotes into double quotes
+    # the string $'b is then quoted as '$'"'"'b'
+    return "'" + file.replace("'", "'\"'\"'") + "'"
diff --git a/Lib/test/test_pipes.py b/Lib/test/test_pipes.py
index dd1cc9e..072d023 100644
--- a/Lib/test/test_pipes.py
+++ b/Lib/test/test_pipes.py
@@ -62,9 +62,10 @@
         self.assertEqual(open(TESTFN).read(), d)
 
     def testQuoting(self):
-        safeunquoted = string.ascii_letters + string.digits + '!@%_-+=:,./'
-        unsafe = '"`$\\'
+        safeunquoted = string.ascii_letters + string.digits + '@%_-+=:,./'
+        unsafe = '"`$\\!'
 
+        self.assertEqual(pipes.quote(''), "''")
         self.assertEqual(pipes.quote(safeunquoted), safeunquoted)
         self.assertEqual(pipes.quote('test file name'), "'test file name'")
         for u in unsafe:
@@ -72,9 +73,7 @@
                               "'test%sname'" % u)
         for u in unsafe:
             self.assertEqual(pipes.quote("test%s'name'" % u),
-                              '"test\\%s\'name\'"' % u)
-
-        self.assertEqual(pipes.quote(''), "''")
+                             "'test%s'\"'\"'name'\"'\"''" % u)
 
     def testRepr(self):
         t = pipes.Template()