Serhiy Storchaka added the comment:

Patches updated to resolve conflicts with recent commits. Some minor test 
errors fixed.

----------
Added file: http://bugs.python.org/file28333/glob_dotfiles_2.patch
Added file: http://bugs.python.org/file28334/glob_tests-2.7_2.patch

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue16618>
_______________________________________
diff -r 2d2d4807a3ed Lib/_pyio.py
--- a/Lib/_pyio.py      Sun Dec 16 16:40:22 2012 +0100
+++ b/Lib/_pyio.py      Sun Dec 16 20:53:44 2012 +0200
@@ -346,8 +346,10 @@
         This method has no effect if the file is already closed.
         """
         if not self.__closed:
-            self.flush()
-            self.__closed = True
+            try:
+                self.flush()
+            finally:
+                self.__closed = True
 
     def __del__(self):
         """Destructor.  Calls close()."""
@@ -1584,8 +1586,10 @@
 
     def close(self):
         if self.buffer is not None and not self.closed:
-            self.flush()
-            self.buffer.close()
+            try:
+                self.flush()
+            finally:
+                self.buffer.close()
 
     @property
     def closed(self):
@@ -2074,3 +2078,56 @@
     def detach(self):
         # This doesn't make sense on StringIO.
         self._unsupported("detach")
+
+
+class BytesPipeIO(BufferedIOBase):
+
+    def __init__(self, maxsize=0):
+        self.maxsize = maxsize
+        self._queue = BytesIO()
+        self._size = 0
+        self._offset = 0
+        self.mutex = threading.Lock()
+        self.not_empty = threading.Condition(self.mutex)
+        self.not_full = threading.Condition(self.mutex)
+        self.all_tasks_done = threading.Condition(self.mutex)
+        self.unfinished_tasks = 0
+
+    def readable(self):
+        return True
+
+    def writable(self):
+        return True
+
+    def read1(self, n=-1):
+        with self.not_empty:
+            while not self._queue:
+                self.not_empty.wait()
+            self._queue.seek(self._offset)
+            b = self._queue.read(n)
+            self._offset += len(b)
+            self.not_full.notify()
+            return b
+
+    #def readall(self):
+        #pass
+
+    #def readinto(self, b):
+        #pass
+
+    def write(self, b):
+        with self.not_full:
+            if self.maxsize > 0:
+                while self._size - self._offset >= self.maxsize:
+                    self.not_full.wait()
+            if self._offset * 2 > self._size + 0x1000:
+                self._pack()
+            self._queue.seek(self._size)
+            self._size += self._queue.write(b)
+            self.unfinished_tasks += 1
+            self.not_empty.notify()
+
+    def _pack(self):
+        self._queue = BytesIO(self._queue.read())
+        self._size -= self._offset
+        self._offset = 0
diff -r 2d2d4807a3ed Lib/codecs.py
--- a/Lib/codecs.py     Sun Dec 16 16:40:22 2012 +0100
+++ b/Lib/codecs.py     Sun Dec 16 20:53:44 2012 +0200
@@ -462,15 +462,8 @@
         # read until we get the required number of characters (if available)
         while True:
             # can the request be satisfied from the character buffer?
-            if chars < 0:
-                if size < 0:
-                    if self.charbuffer:
-                        break
-                elif len(self.charbuffer) >= size:
-                    break
-            else:
-                if len(self.charbuffer) >= chars:
-                    break
+            if chars >= 0 and len(self.charbuffer) >= chars:
+                break
             # we need more data
             if size < 0:
                 newdata = self.stream.read()
diff -r 2d2d4807a3ed Lib/ftplib.py
--- a/Lib/ftplib.py     Sun Dec 16 16:40:22 2012 +0100
+++ b/Lib/ftplib.py     Sun Dec 16 20:53:44 2012 +0200
@@ -288,21 +288,25 @@
 
     def makeport(self):
         '''Create a new socket and send a PORT command for it.'''
-        msg = "getaddrinfo returns an empty list"
         sock = None
+        saved_err = None
         for res in socket.getaddrinfo(None, 0, self.af, socket.SOCK_STREAM, 0, 
socket.AI_PASSIVE):
             af, socktype, proto, canonname, sa = res
             try:
                 sock = socket.socket(af, socktype, proto)
                 sock.bind(sa)
-            except socket.error as msg:
+            except OSError as err:
+                saved_err = err
                 if sock:
                     sock.close()
                 sock = None
                 continue
             break
         if not sock:
-            raise socket.error(msg)
+            if saved_err is not None:
+                raise saved_err from None
+            else:
+                raise OSError("getaddrinfo returns an empty list")
         sock.listen(1)
         port = sock.getsockname()[1] # Get proper port
         host = self.sock.getsockname()[0] # Get proper host
diff -r 2d2d4807a3ed Lib/glob.py
--- a/Lib/glob.py       Sun Dec 16 16:40:22 2012 +0100
+++ b/Lib/glob.py       Sun Dec 16 20:53:44 2012 +0200
@@ -57,8 +57,8 @@
         names = os.listdir(dirname)
     except os.error:
         return []
-    if pattern[0] != '.':
-        names = [x for x in names if x[0] != '.']
+    if not _ishidden(pattern):
+        names = [x for x in names if not _ishidden(x)]
     return fnmatch.filter(names, pattern)
 
 def glob0(dirname, basename):
@@ -82,3 +82,6 @@
     else:
         match = magic_check.search(s)
     return match is not None
+
+def _ishidden(path):
+    return path[0] in ('.', b'.'[0])
diff -r 2d2d4807a3ed Lib/idlelib/CallTips.py
--- a/Lib/idlelib/CallTips.py   Sun Dec 16 16:40:22 2012 +0100
+++ b/Lib/idlelib/CallTips.py   Sun Dec 16 20:53:44 2012 +0200
@@ -116,6 +116,9 @@
             # exception, especially if user classes are involved.
             return None
 
+_MAXARGSPECLINES = 10
+_MAXARGSPECCOLS = 70
+
 # The following are used in both get_argspec and tests
 _first_param = re.compile('(?<=\()\w*\,?\s*')
 _default_callable_argspec = "No docstring, see docs."
@@ -125,8 +128,9 @@
 
     For Python-coded functions and methods, the first line is introspected.
     Delete 'self' parameter for classes (.__init__) and bound methods.
-    The last line is the first line of the doc string.  For builtins, this 
typically
-    includes the arguments in addition to the return value.
+    The next lines are the first lines of the doc string up to the first
+    empty line.  For builtins, this typically includes the arguments in
+    addition to the return value.
 
     '''
     argspec = ""
@@ -148,13 +152,13 @@
         else:
             doc = getattr(ob, "__doc__", "")
         if doc:
-            doc = doc.lstrip()
-            pos = doc.find("\n")
-            if pos < 0 or pos > 70:
-                pos = 70
-            if argspec:
-                argspec += "\n"
-            argspec += doc[:pos]
+            lines = [argspec] if argspec else []
+            for line in doc.splitlines()[:_MAXARGSPECLINES - len(lines)]:
+                line = line.strip()
+                if not line:
+                    break
+                lines.append(line[:_MAXARGSPECCOLS])
+            argspec = '\n'.join(lines)
         if not argspec:
             argspec = _default_callable_argspec
     return argspec
@@ -209,12 +213,14 @@
             print(fmt % (expression, expected, argspec))
 
     def test_builtins():
-        # if first line of a possibly multiline compiled docstring changes,
+        # if a compiled docstring changes,
         # must change corresponding test string
-        test('int',  "int(x=0) -> integer")
+        test('int',  "int(x=0) -> integer\n"
+             "int(x, base=10) -> integer")
         test('Int',  Int.__doc__)
         test('types.MethodType', "method(function, instance)")
-        test('list', "list() -> new empty list")
+        test('list', "list() -> new empty list\n"
+             "list(iterable) -> new list initialized from iterable's items")
         test('List', List.__doc__)
         test('list.__new__',
                'T.__new__(S, ...) -> a new object with type S, a subtype of T')
diff -r 2d2d4807a3ed Lib/pty.py
--- a/Lib/pty.py        Sun Dec 16 16:40:22 2012 +0100
+++ b/Lib/pty.py        Sun Dec 16 20:53:44 2012 +0200
@@ -54,10 +54,7 @@
     except ImportError:
         pass
     else:
-        try:
-            tty_name, master_fd = sgi._getpty(os.O_RDWR, 0o666, 0)
-        except IOError as msg:
-            raise os.error(msg)
+        tty_name, master_fd = sgi._getpty(os.O_RDWR, 0o666, 0)
         return master_fd, tty_name
     for x in 'pqrstuvwxyzPQRST':
         for y in '0123456789abcdef':
diff -r 2d2d4807a3ed Lib/random.py
--- a/Lib/random.py     Sun Dec 16 16:40:22 2012 +0100
+++ b/Lib/random.py     Sun Dec 16 20:53:44 2012 +0200
@@ -31,8 +31,7 @@
 
 * The period is 2**19937-1.
 * It is one of the most extensively tested generators in existence.
-* The random() method is implemented in C, executes in a single Python step,
-  and is, therefore, threadsafe.
+* random() and getrandbits() method are threadsafe.
 
 """
 
@@ -43,6 +42,12 @@
 from os import urandom as _urandom
 from collections.abc import Set as _Set, Sequence as _Sequence
 from hashlib import sha512 as _sha512
+from struct import pack as _pack, unpack as _unpack
+from time import time as _time
+try:
+    from threading import RLock as _RLock
+except ImportError:
+    from dummy_threading import RLock as _RLock
 
 __all__ = ["Random","seed","random","uniform","randint","choice","sample",
            "randrange","shuffle","normalvariate","lognormvariate",
@@ -59,13 +64,160 @@
 RECIP_BPF = 2**-BPF
 
 
+class _Random:
+    """Mersenne Twister core generator."""
+    # See more comments in Modules/_randommodule.c.
+
+    def __new__(cls, *args, **kwargs):
+        if cls == _Random and kwargs:
+            raise TypeError('Random() does not take keyword arguments')
+        self = super(_Random, cls).__new__(cls)
+        self.__lock = _RLock()
+        self.seed(*args)
+        return self
+
+    def random(self):
+        """Generates a float in the interval [0, 1)."""
+        with self.__lock:
+            genrand_int32 = self.__genrand_int32
+            a = genrand_int32() >> 5  # 27 bits
+            b = genrand_int32() >> 6  # 26 bits
+            return ((a << 26) + b) * (1 / 0x20000000000000)  # 1 / 2**53
+
+    def seed(self, n=None):
+        """Initialize internal state from hashable object.
+
+        None or no argument seeds from current time.
+
+        If *n* is not an int, all bits are used, otherwise the hash() of *n*
+        is used instead.
+        """
+        with self.__lock:
+            if n is None:
+                self.__init_genrand(int(_time()))
+                return None
+            if isinstance(n, int):
+                n = abs(n)
+            else:
+                n = hash(n)
+                if n < 0:
+                    n, = _unpack('N', _pack('n', n))
+            # Now split n into 32-bit chunks, from the right.
+            bits = n.bit_length()
+            keysize = ((bits - 1) >> 5) + 1 if bits else 1
+            key = _unpack('<%dI' % keysize, n.to_bytes(keysize * 4, 'little'))
+            self.__init_by_array(key)
+
+    def getstate(self):
+        """Return tuple containing the current state.;
+        can be passed to setstate() later."""
+        with self.__lock:
+            return tuple(self.__state) + (self.__index,)
+
+    def setstate(self, state):
+        """Restore internal state from tuple returned by getstate()."""
+        with self.__lock:
+            if not isinstance(state, tuple):
+                raise TypeError('state vector must be a tuple')
+            if len(state) != len(self.__state) + 1:
+                raise ValueError('state vector is the wrong size')
+            self.__state = [x & 0xffffffff for x in state[:-1]]
+            self.__index = int(state[-1])
+
+    def getrandbits(self, k):
+        """Generates an int with k random bits."""
+        with self.__lock:
+            if k <= 0:
+                raise ValueError('number of bits must be greater than zero')
+
+            if k <= 32:
+                return self.__genrand_int32() >> (32 - k)
+
+            # Fill-out whole words, byte-by-byte to avoid endianness issues
+            genrand_int32 = self.__genrand_int32
+            words = [genrand_int32() for i in range(((k - 1) >> 5) + 1)]
+            k &= 31
+            if k:
+                words[-1] >>= 32 - k
+            # little endian order to match bytearray assignment order
+            return int.from_bytes(_pack('<%dI' % len(words), *words), 'little')
+
+    # Generates a random number on [0,0xffffffff]-interval
+    def __genrand_int32(self):
+        try:
+            y = self.__state[self.__index]
+            self.__index += 1
+        except IndexError:
+            mt = self.__state
+            N = len(mt)
+            # generate N words at one time
+            for kk in range(N):
+                y = (mt[kk] & 0x80000000) | (mt[kk + 1 - N] & 0x7fffffff)
+                x = mt[kk + 397 - N] ^ (y >> 1)
+                if y & 1:
+                    x ^= 0x9908b0df
+                mt[kk] = x
+            y = mt[0]
+            self.__index = 1
+
+        y ^= (y >> 11)
+        y ^= (y << 7) & 0x9d2c5680
+        y ^= (y << 15) & 0xefc60000
+        y ^= (y >> 18)
+        return y
+
+    # Initialize by an integer seed
+    def __init_genrand(self, s):
+        x = s & 0xffffffff
+        mt = [x]
+        append = mt.append
+        for i in range(1, 624):
+            x ^= x >> 30
+            x = (1812433253 * x + i) & 0xffffffff
+            append(x)
+            # See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier.
+            # In the previous versions, MSBs of the seed affect
+            # only MSBs of the array mt[].
+            # 2002/01/09 modified by Makoto Matsumoto
+        self.__state = mt
+        self.__index = len(mt)
+
+    # Initialize by an integer array
+    def __init_by_array(self, init_key):
+        self.__init_genrand(19650218)
+        mt = self.__state
+        N = len(self.__state)
+        i = 1
+        j = 0
+        x = mt[0]
+        for k in range(max(N, len(init_key))):
+            x ^= x >> 30
+            mt[i] = x = ((mt[i] ^ (x * 1664525)) + init_key[j] + j) & 
0xffffffff
+            i += 1
+            if i >= N:
+                i = 1
+            j += 1
+            if j >= len(init_key):
+                j = 0
+        for k in range(N - 1):
+            x ^= x >> 30
+            mt[i] = x = ((mt[i] ^ (x * 1566083941)) - i) & 0xffffffff
+            i += 1
+            if i >= N:
+                i = 1
+        mt[0] = 0x80000000  # MSB is 1; assuring non-zero initial array
+
+try:
+    from _random import Random as _Random
+except ImportError:
+    pass
+
+
 # Translated by Guido van Rossum from C source provided by
 # Adrian Baddeley.  Adapted by Raymond Hettinger for use with
 # the Mersenne Twister  and os.urandom() core generators.
 
-import _random
-
-class Random(_random.Random):
+class Random(_Random):
     """Random number generator base class used by bound module functions.
 
     Used to instantiate instances of Random to get generators that don't
diff -r 2d2d4807a3ed Lib/shutil.py
--- a/Lib/shutil.py     Sun Dec 16 16:40:22 2012 +0100
+++ b/Lib/shutil.py     Sun Dec 16 20:53:44 2012 +0200
@@ -356,24 +356,24 @@
     names = []
     try:
         names = os.listdir(path)
-    except os.error:
+    except OSError:
         onerror(os.listdir, path, sys.exc_info())
     for name in names:
         fullname = os.path.join(path, name)
         try:
             mode = os.lstat(fullname).st_mode
-        except os.error:
+        except OSError:
             mode = 0
         if stat.S_ISDIR(mode):
             _rmtree_unsafe(fullname, onerror)
         else:
             try:
                 os.unlink(fullname)
-            except os.error:
+            except OSError:
                 onerror(os.unlink, fullname, sys.exc_info())
     try:
         os.rmdir(path)
-    except os.error:
+    except OSError:
         onerror(os.rmdir, path, sys.exc_info())
 
 # Version using fd-based APIs to protect against races
@@ -464,7 +464,7 @@
                 _rmtree_safe_fd(fd, path, onerror)
                 try:
                     os.rmdir(path)
-                except os.error:
+                except OSError:
                     onerror(os.rmdir, path, sys.exc_info())
             else:
                 try:
diff -r 2d2d4807a3ed Lib/smtplib.py
--- a/Lib/smtplib.py    Sun Dec 16 16:40:22 2012 +0100
+++ b/Lib/smtplib.py    Sun Dec 16 20:53:44 2012 +0200
@@ -920,13 +920,13 @@
             self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
             self.file = None
             self.sock.connect(host)
-        except socket.error as msg:
+        except socket.error:
             if self.debuglevel > 0:
                 print('connect fail:', host, file=stderr)
             if self.sock:
                 self.sock.close()
             self.sock = None
-            raise socket.error(msg)
+            raise
         (code, msg) = self.getreply()
         if self.debuglevel > 0:
             print('connect:', msg, file=stderr)
diff -r 2d2d4807a3ed Lib/test/test_codecs.py
--- a/Lib/test/test_codecs.py   Sun Dec 16 16:40:22 2012 +0100
+++ b/Lib/test/test_codecs.py   Sun Dec 16 20:53:44 2012 +0200
@@ -168,6 +168,12 @@
                         size*"a",
                     )
 
+        # Test readlines() followed by read()
+        f = getreader("a\n" + "b" * 1000)
+        self.assertEqual(f.readline(), u"a\n")
+        self.assertEqual(f.read(), u"b" * 1000)
+        self.assertEqual(f.read(), u"")
+
     def test_bug1175396(self):
         s = [
             '<%!--===================================================\r\n',
diff -r 2d2d4807a3ed Lib/test/test_glob.py
--- a/Lib/test/test_glob.py     Sun Dec 16 16:40:22 2012 +0100
+++ b/Lib/test/test_glob.py     Sun Dec 16 20:53:44 2012 +0200
@@ -31,7 +31,8 @@
         self.mktemp('a', 'bcd', 'efg', 'ha')
         if can_symlink():
             os.symlink(self.norm('broken'), self.norm('sym1'))
-            os.symlink(self.norm('broken'), self.norm('sym2'))
+            os.symlink('broken', self.norm('sym2'))
+            os.symlink(os.path.join('a', 'bcd'), self.norm('sym3'))
 
     def tearDown(self):
         shutil.rmtree(self.tempdir)
@@ -44,10 +45,16 @@
         p = os.path.join(self.tempdir, pattern)
         res = glob.glob(p)
         self.assertEqual(list(glob.iglob(p)), res)
+        bres = [os.fsencode(x) for x in res]
+        self.assertEqual(glob.glob(os.fsencode(p)), bres)
+        self.assertEqual(list(glob.iglob(os.fsencode(p))), bres)
         return res
 
     def assertSequencesEqual_noorder(self, l1, l2):
+        l1 = list(l1)
+        l2 = list(l2)
         self.assertEqual(set(l1), set(l2))
+        self.assertEqual(sorted(l1), sorted(l2))
 
     def test_glob_literal(self):
         eq = self.assertSequencesEqual_noorder
@@ -58,13 +65,23 @@
 
         # test return types are unicode, but only if os.listdir
         # returns unicode filenames
-        uniset = set([str])
-        tmp = os.listdir('.')
-        if set(type(x) for x in tmp) == uniset:
+        uniset = {str}
+        tmp = os.listdir(os.curdir)
+        if {type(x) for x in tmp} == uniset:
             u1 = glob.glob('*')
-            u2 = glob.glob('./*')
-            self.assertEqual(set(type(r) for r in u1), uniset)
-            self.assertEqual(set(type(r) for r in u2), uniset)
+            u2 = glob.glob(os.path.join(os.curdir, '*'))
+            self.assertEqual({type(r) for r in u1}, uniset)
+            self.assertEqual({type(r) for r in u2}, uniset)
+
+        # test return types are bytes, but only if os.listdir
+        # returns bytes filenames
+        bytset = {bytes}
+        tmp = os.listdir(os.fsencode(os.curdir))
+        if {type(x) for x in tmp} == bytset:
+            u1 = glob.glob(b'*')
+            u2 = glob.glob(os.path.join(os.fsencode(os.curdir), b'*'))
+            self.assertEqual({type(r) for r in u1}, bytset)
+            self.assertEqual({type(r) for r in u2}, bytset)
 
     def test_glob_one_directory(self):
         eq = self.assertSequencesEqual_noorder
@@ -111,6 +128,9 @@
                       {self.norm('aaa'), self.norm('aab')},
                       {self.norm('aaa') + os.sep, self.norm('aab') + os.sep},
                       ])
+        eq = self.assertSequencesEqual_noorder
+        eq(self.glob('a*', ''), [os.path.join(self.tempdir, x, '')
+                                 for x in ['a', 'aaa', 'aab']])
 
     def test_glob_bytes_directory_with_trailing_slash(self):
         # Same as test_glob_directory_with_trailing_slash, but with a
@@ -128,9 +148,20 @@
                       ])
 
     @skip_unless_symlink
+    def test_glob_symlinks(self):
+        eq = self.assertSequencesEqual_noorder
+        eq(self.glob('sym3'), [self.norm('sym3')])
+        eq(self.glob('sym3', '*'), [self.norm('sym3', 'EF'),
+                                    self.norm('sym3', 'efg')])
+        eq(self.glob('sym3', ''), [os.path.join(self.norm('sym3'), '')])
+        eq(self.glob('*', '*F'), [self.norm('aaa', 'zzzF'),
+                self.norm('aab', 'F'), self.norm('sym3', 'EF')])
+
+    @skip_unless_symlink
     def test_glob_broken_symlinks(self):
         eq = self.assertSequencesEqual_noorder
-        eq(self.glob('sym*'), [self.norm('sym1'), self.norm('sym2')])
+        eq(self.glob('sym*'), [self.norm('sym1'), self.norm('sym2'),
+                               self.norm('sym3')])
         eq(self.glob('sym1'), [self.norm('sym1')])
         eq(self.glob('sym2'), [self.norm('sym2')])
 
diff -r 2d2d4807a3ed Lib/test/test_random.py
--- a/Lib/test/test_random.py   Sun Dec 16 16:40:22 2012 +0100
+++ b/Lib/test/test_random.py   Sun Dec 16 20:53:44 2012 +0200
@@ -1,13 +1,16 @@
 #!/usr/bin/env python3
 
 import unittest
-import random
 import time
 import pickle
+import sys
 import warnings
 from math import log, exp, pi, fsum, sin
 from test import support
 
+py_random = support.import_fresh_module('random', blocked=['_random'])
+c_random = support.import_fresh_module('random', fresh=['_random'])
+
 class TestBasicOps(unittest.TestCase):
     # Superclass with tests common to all generators.
     # Subclasses must arrange for self.gen to retrieve the Random instance
@@ -148,11 +151,23 @@
             self.assertEqual(y1, y2)
 
     def test_pickling(self):
-        state = pickle.dumps(self.gen)
-        origseq = [self.gen.random() for i in range(10)]
-        newgen = pickle.loads(state)
-        restoredseq = [newgen.random() for i in range(10)]
-        self.assertEqual(origseq, restoredseq)
+        with support.CleanImport('random'):
+            sys.modules['random'] = self.module
+            state = pickle.dumps(self.gen)
+            origseq = [self.gen.random() for i in range(10)]
+            newgen = pickle.loads(state)
+            restoredseq = [newgen.random() for i in range(10)]
+            self.assertEqual(origseq, restoredseq)
+
+            if c_random:
+                # Test interchangeability
+                if self.module != c_random:
+                    sys.modules['random'] = c_random
+                else:
+                    sys.modules['random'] = py_random
+                newgen = pickle.loads(state)
+                restoredseq = [newgen.random() for i in range(10)]
+                self.assertEqual(origseq, restoredseq)
 
     def test_bug_1727780(self):
         # verify that version-2-pickles can be loaded
@@ -175,9 +190,8 @@
         k = sum(randrange(6755399441055744) % 3 == 2 for i in range(n))
         self.assertTrue(0.30 < k/n < .37, (k/n))
 
+
 class SystemRandom_TestBasicOps(TestBasicOps):
-    gen = random.SystemRandom()
-
     def test_autoseed(self):
         # Doesn't need to do anything except not fail
         self.gen.seed()
@@ -271,10 +285,17 @@
             self.assertEqual(k, numbits)        # note the stronger assertion
             self.assertTrue(2**k > n > 2**(k-1))   # note the stronger 
assertion
 
+class SystemRandom_TestBasicOpsPython(SystemRandom_TestBasicOps):
+    module = py_random
+    gen = module.SystemRandom()
+
+@unittest.skipUnless(c_random, 'requires _random')
+class SystemRandom_TestBasicOpsC(SystemRandom_TestBasicOps):
+    module = c_random
+    gen = module.SystemRandom()
+
 
 class MersenneTwister_TestBasicOps(TestBasicOps):
-    gen = random.Random()
-
     def test_guaranteed_stable(self):
         # These sequences are guaranteed to stay the same across versions of 
python
         self.gen.seed(3456147, version=1)
@@ -446,6 +467,16 @@
         self.assertTrue(stop < x <= start)
         self.assertEqual((x+stop)%step, 0)
 
+class MersenneTwister_TestBasicOpsPython(MersenneTwister_TestBasicOps):
+    module = py_random
+    gen = module.Random()
+
+@unittest.skipUnless(c_random, 'requires _random')
+class MersenneTwister_TestBasicOpsC(MersenneTwister_TestBasicOps):
+    module = c_random
+    gen = module.Random()
+
+
 def gamma(z, sqrt2pi=(2.0*pi)**0.5):
     # Reflection to right half of complex plane
     if z < 0.5:
@@ -467,7 +498,7 @@
 class TestDistributions(unittest.TestCase):
     def test_zeroinputs(self):
         # Verify that distributions can handle a series of zero inputs'
-        g = random.Random()
+        g = self.module.Random()
         x = [g.random() for i in range(50)] + [0.0]*5
         g.random = x[:].pop; g.uniform(1,10)
         g.random = x[:].pop; g.paretovariate(1.0)
@@ -486,7 +517,7 @@
     def test_avg_std(self):
         # Use integration to test distribution average and standard deviation.
         # Only works for distributions which do not consume variates in pairs
-        g = random.Random()
+        g = self.module.Random()
         N = 5000
         x = [i/float(N) for i in range(1,N)]
         for variate, args, mu, sigmasqrd in [
@@ -512,36 +543,53 @@
             self.assertAlmostEqual(s1/N, mu, places=2)
             self.assertAlmostEqual(s2/(N-1), sigmasqrd, places=2)
 
+class TestDistributionsPython(TestDistributions):
+    module = py_random
+
+@unittest.skipUnless(c_random, 'requires _random')
+class TestDistributionsC(TestDistributions):
+    module = c_random
+
+
 class TestModule(unittest.TestCase):
     def testMagicConstants(self):
-        self.assertAlmostEqual(random.NV_MAGICCONST, 1.71552776992141)
-        self.assertAlmostEqual(random.TWOPI, 6.28318530718)
-        self.assertAlmostEqual(random.LOG4, 1.38629436111989)
-        self.assertAlmostEqual(random.SG_MAGICCONST, 2.50407739677627)
+        self.assertAlmostEqual(self.module.NV_MAGICCONST, 1.71552776992141)
+        self.assertAlmostEqual(self.module.TWOPI, 6.28318530718)
+        self.assertAlmostEqual(self.module.LOG4, 1.38629436111989)
+        self.assertAlmostEqual(self.module.SG_MAGICCONST, 2.50407739677627)
 
     def test__all__(self):
         # tests validity but not completeness of the __all__ list
-        self.assertTrue(set(random.__all__) <= set(dir(random)))
+        self.assertTrue(set(self.module.__all__) <= set(dir(self.module)))
 
     def test_random_subclass_with_kwargs(self):
         # SF bug #1486663 -- this used to erroneously raise a TypeError
-        class Subclass(random.Random):
+        module = self.module
+        class Subclass(module.Random):
             def __init__(self, newarg=None):
-                random.Random.__init__(self)
+                module.Random.__init__(self)
         Subclass(newarg=1)
 
+class TestModulePython(TestModule):
+    module = py_random
+
+@unittest.skipUnless(c_random, 'requires _random')
+class TestModuleC(TestModule):
+    module = c_random
+
 
 def test_main(verbose=None):
-    testclasses =    [MersenneTwister_TestBasicOps,
-                      TestDistributions,
-                      TestModule]
+    testclasses = [
+        MersenneTwister_TestBasicOpsPython, MersenneTwister_TestBasicOpsC,
+        TestDistributionsPython, TestDistributionsC,
+        TestModulePython, TestModuleC]
 
     try:
-        random.SystemRandom().random()
+        py_random.SystemRandom().random()
     except NotImplementedError:
         pass
     else:
-        testclasses.append(SystemRandom_TestBasicOps)
+        testclasses.extend([SystemRandom_TestBasicOpsPython, 
SystemRandom_TestBasicOpsC])
 
     support.run_unittest(*testclasses)
 
diff -r 2d2d4807a3ed Lib/test/test_subprocess.py
--- a/Lib/test/test_subprocess.py       Sun Dec 16 16:40:22 2012 +0100
+++ b/Lib/test/test_subprocess.py       Sun Dec 16 20:53:44 2012 +0200
@@ -2161,8 +2161,7 @@
                                   stderr=subprocess.PIPE) as proc:
                 pass
 
-            if c.exception.errno != errno.ENOENT:  # ignore "no such file"
-                raise c.exception
+        self.assertEqual(c.exception.errno, errno.ENOENT)
 
 
 def test_main():
diff -r 2d2d4807a3ed Lib/test/test_tarfile.py
--- a/Lib/test/test_tarfile.py  Sun Dec 16 16:40:22 2012 +0100
+++ b/Lib/test/test_tarfile.py  Sun Dec 16 20:53:44 2012 +0200
@@ -340,22 +340,16 @@
 
         try:
             tar.extract("ustar/regtype", TEMPDIR)
-            try:
-                tar.extract("ustar/lnktype", TEMPDIR)
-            except EnvironmentError as e:
-                if e.errno == errno.ENOENT:
-                    self.fail("hardlink not extracted properly")
+            self.addCleanup(os.remove, os.path.join(TEMPDIR, "ustar/regtype"))
 
+            tar.extract("ustar/lnktype", TEMPDIR)
+            self.addCleanup(os.remove, os.path.join(TEMPDIR, "ustar/lnktype"))
             with open(os.path.join(TEMPDIR, "ustar/lnktype"), "rb") as f:
                 data = f.read()
             self.assertEqual(md5sum(data), md5_regtype)
 
-            try:
-                tar.extract("ustar/symtype", TEMPDIR)
-            except EnvironmentError as e:
-                if e.errno == errno.ENOENT:
-                    self.fail("symlink not extracted properly")
-
+            tar.extract("ustar/symtype", TEMPDIR)
+            self.addCleanup(os.remove, os.path.join(TEMPDIR, "ustar/symtype"))
             with open(os.path.join(TEMPDIR, "ustar/symtype"), "rb") as f:
                 data = f.read()
             self.assertEqual(md5sum(data), md5_regtype)
diff -r 2d2d4807a3ed Modules/_randommodule.c
--- a/Modules/_randommodule.c   Sun Dec 16 16:40:22 2012 +0100
+++ b/Modules/_randommodule.c   Sun Dec 16 20:53:44 2012 +0200
@@ -389,6 +389,9 @@
         return NULL;
     }
 
+    if (k <= 32)  /* Fast path */
+        return PyLong_FromUnsignedLong(genrand_int32(self) >> (32 - k));
+
     bytes = ((k - 1) / 32 + 1) * 4;
     bytearray = (unsigned char *)PyMem_Malloc(bytes);
     if (bytearray == NULL) {
diff -r b0935ef48186 Lib/lib-tk/Tkinter.py
--- a/Lib/lib-tk/Tkinter.py     Sun Dec 16 13:55:47 2012 +0100
+++ b/Lib/lib-tk/Tkinter.py     Sun Dec 16 20:53:46 2012 +0200
@@ -41,6 +41,7 @@
 TclError = _tkinter.TclError
 from types import *
 from Tkconstants import *
+import re
 
 wantobjects = 1
 
@@ -58,6 +59,37 @@
 except AttributeError: _tkinter.deletefilehandler = None
 
 
+_magic_re = re.compile(r'([\\{}])')
+_space_re = re.compile(r'([\s])')
+
+def _join(value):
+    """Internal function."""
+    return ' '.join(map(_stringify, value))
+
+def _stringify(value):
+    """Internal function."""
+    if isinstance(value, (list, tuple)):
+        if len(value) == 1:
+            value = _stringify(value[0])
+            if value[0] == '{':
+                value = '{%s}' % value
+        else:
+            value = '{%s}' % _join(value)
+    else:
+        if isinstance(value, basestring):
+            value = unicode(value)
+        else:
+            value = str(value)
+        if not value:
+            value = '{}'
+        elif _magic_re.search(value):
+            # add '\' before special characters and spaces
+            value = _magic_re.sub(r'\\\1', value)
+            value = _space_re.sub(r'\\\1', value)
+        elif value[0] == '"' or _space_re.search(value):
+            value = '{%s}' % value
+    return value
+
 def _flatten(tuple):
     """Internal function."""
     res = ()
@@ -1086,7 +1118,7 @@
                             nv.append('%d' % item)
                         else:
                             # format it to proper Tcl code if it contains space
-                            nv.append(('{%s}' if ' ' in item else '%s') % item)
+                            nv.append(_stringify(item))
                     else:
                         v = ' '.join(nv)
                 res = res + ('-'+k, v)
diff -r b0935ef48186 Lib/lib-tk/test/test_ttk/test_functions.py
--- a/Lib/lib-tk/test/test_ttk/test_functions.py        Sun Dec 16 13:55:47 
2012 +0100
+++ b/Lib/lib-tk/test/test_ttk/test_functions.py        Sun Dec 16 20:53:46 
2012 +0200
@@ -50,13 +50,17 @@
             ttk._format_optdict({'test': {'left': 'as is'}}),
             {'-test': {'left': 'as is'}})
 
-        # check script formatting and untouched value(s)
+        # check script formatting
         check_against(
             ttk._format_optdict(
-                {'test': [1, -1, '', '2m', 0], 'nochange1': 3,
-                 'nochange2': 'abc def'}, script=True),
-            {'-test': '{1 -1 {} 2m 0}', '-nochange1': 3,
-             '-nochange2': 'abc def' })
+                {'test': [1, -1, '', '2m', 0], 'test2': 3,
+                 'test3': '', 'test4': 'abc def',
+                 'test5': '"abc"', 'test6': '{}',
+                 'test7': '} -spam {'}, script=True),
+            {'-test': '{1 -1 {} 2m 0}', '-test2': '3',
+             '-test3': '{}', '-test4': '{abc def}',
+             '-test5': '{"abc"}', '-test6': r'\{\}',
+             '-test7': r'\}\ -spam\ \{'})
 
         opts = {u'αβγ': True, u'á': False}
         orig_opts = opts.copy()
@@ -70,6 +74,32 @@
             ttk._format_optdict(
                 {'option': ('one two', 'three')}),
             {'-option': '{one two} three'})
+        check_against(
+            ttk._format_optdict(
+                {'option': ('one\ttwo', 'three')}),
+            {'-option': '{one\ttwo} three'})
+
+        # passing empty strings inside a tuple/list
+        check_against(
+            ttk._format_optdict(
+                {'option': ('', 'one')}),
+            {'-option': '{} one'})
+
+        # passing values with braces inside a tuple/list
+        check_against(
+            ttk._format_optdict(
+                {'option': ('one} {two', 'three')}),
+            {'-option': r'one\}\ \{two three'})
+
+        # passing quoted strings inside a tuple/list
+        check_against(
+            ttk._format_optdict(
+                {'option': ('"one"', 'two')}),
+            {'-option': '{"one"} two'})
+        check_against(
+            ttk._format_optdict(
+                {'option': ('{one}', 'two')}),
+            {'-option': r'\{one\} two'})
 
         # ignore an option
         amount_opts = len(ttk._format_optdict(opts, ignore=(u'á'))) // 2
diff -r b0935ef48186 Lib/lib-tk/test/test_ttk/test_widgets.py
--- a/Lib/lib-tk/test/test_ttk/test_widgets.py  Sun Dec 16 13:55:47 2012 +0100
+++ b/Lib/lib-tk/test/test_ttk/test_widgets.py  Sun Dec 16 20:53:46 2012 +0200
@@ -188,6 +188,14 @@
         self.combo.configure(values=[1, '', 2])
         self.assertEqual(self.combo['values'], ('1', '', '2'))
 
+        # testing values with spaces
+        self.combo['values'] = ['a b', 'a\tb', 'a\nb']
+        self.assertEqual(self.combo['values'], ('a b', 'a\tb', 'a\nb'))
+
+        # testing values with special characters
+        self.combo['values'] = [r'a\tb', '"a"', '} {']
+        self.assertEqual(self.combo['values'], (r'a\tb', '"a"', '} {'))
+
         # out of range
         self.assertRaises(Tkinter.TclError, self.combo.current,
             len(self.combo['values']))
diff -r b0935ef48186 Lib/lib-tk/ttk.py
--- a/Lib/lib-tk/ttk.py Sun Dec 16 13:55:47 2012 +0100
+++ b/Lib/lib-tk/ttk.py Sun Dec 16 20:53:46 2012 +0200
@@ -26,8 +26,7 @@
            "tclobjs_to_py", "setup_master"]
 
 import Tkinter
-
-_flatten = Tkinter._flatten
+from Tkinter import _flatten, _join, _stringify
 
 # Verify if Tk is new enough to not need the Tile package
 _REQUIRE_TILE = True if Tkinter.TkVersion < 8.5 else False
@@ -47,39 +46,56 @@
         master.tk.eval('package require tile') # TclError may be raised here
         master._tile_loaded = True
 
+def _format_optvalue(value, script=False):
+    """Internal function."""
+    if script:
+        # if caller passes a Tcl script to tk.call, all the values need to
+        # be grouped into words (arguments to a command in Tcl dialect)
+        value = _stringify(value)
+    elif isinstance(value, (list, tuple)):
+        value = _join(value)
+    return value
+
 def _format_optdict(optdict, script=False, ignore=None):
     """Formats optdict to a tuple to pass it to tk.call.
 
     E.g. (script=False):
       {'foreground': 'blue', 'padding': [1, 2, 3, 4]} returns:
       ('-foreground', 'blue', '-padding', '1 2 3 4')"""
-    format = "%s" if not script else "{%s}"
 
     opts = []
     for opt, value in optdict.iteritems():
-        if ignore and opt in ignore:
-            continue
+        if not ignore or opt not in ignore:
+            opts.append("-%s" % opt)
+            if value is not None:
+                opts.append(_format_optvalue(value, script))
 
-        if isinstance(value, (list, tuple)):
-            v = []
-            for val in value:
-                if isinstance(val, basestring):
-                    v.append(unicode(val) if val else '{}')
-                else:
-                    v.append(str(val))
+    return _flatten(opts)
 
-            # format v according to the script option, but also check for
-            # space in any value in v in order to group them correctly
-            value = format % ' '.join(
-                ('{%s}' if ' ' in val else '%s') % val for val in v)
-
-        if script and value == '':
-            value = '{}' # empty string in Python is equivalent to {} in Tcl
-
-        opts.append(("-%s" % opt, value))
-
-    # Remember: _flatten skips over None
-    return _flatten(opts)
+def _mapdict_values(items):
+    # each value in mapdict is expected to be a sequence, where each item
+    # is another sequence containing a state (or several) and a value
+    # E.g. (script=False):
+    #   [('active', 'selected', 'grey'), ('focus', [1, 2, 3, 4])]
+    #   returns:
+    #   ['active selected', 'grey', 'focus', [1, 2, 3, 4]]
+    opt_val = []
+    for item in items:
+        state = item[:-1]
+        val = item[-1]
+        # hacks for bakward compatibility
+        state[0] # raise IndexError if empty
+        if len(state) == 1:
+            # if it is empty (something that evaluates to False), then
+            # format it to Tcl code to denote the "normal" state
+            state = state[0] or ''
+        else:
+            # group multiple states
+            state = ' '.join(state) # raise TypeError if not str
+        opt_val.append(state)
+        if val is not None:
+            opt_val.append(val)
+    return opt_val
 
 def _format_mapdict(mapdict, script=False):
     """Formats mapdict to pass it to tk.call.
@@ -90,32 +106,11 @@
       returns:
 
       ('-expand', '{active selected} grey focus {1, 2, 3, 4}')"""
-    # if caller passes a Tcl script to tk.call, all the values need to
-    # be grouped into words (arguments to a command in Tcl dialect)
-    format = "%s" if not script else "{%s}"
 
     opts = []
     for opt, value in mapdict.iteritems():
-
-        opt_val = []
-        # each value in mapdict is expected to be a sequence, where each item
-        # is another sequence containing a state (or several) and a value
-        for statespec in value:
-            state, val = statespec[:-1], statespec[-1]
-
-            if len(state) > 1: # group multiple states
-                state = "{%s}" % ' '.join(state)
-            else: # single state
-                # if it is empty (something that evaluates to False), then
-                # format it to Tcl code to denote the "normal" state
-                state = state[0] or '{}'
-
-            if isinstance(val, (list, tuple)): # val needs to be grouped
-                val = "{%s}" % ' '.join(map(str, val))
-
-            opt_val.append("%s %s" % (state, val))
-
-        opts.append(("-%s" % opt, format % ' '.join(opt_val)))
+        opts.extend(("-%s" % opt,
+                     _format_optvalue(_mapdict_values(value), script)))
 
     return _flatten(opts)
 
@@ -129,7 +124,7 @@
             iname = args[0]
             # next args, if any, are statespec/value pairs which is almost
             # a mapdict, but we just need the value
-            imagespec = _format_mapdict({None: args[1:]})[1]
+            imagespec = _join(_mapdict_values(args[1:]))
             spec = "%s %s" % (iname, imagespec)
 
         else:
@@ -138,7 +133,7 @@
             # themed styles on Windows XP and Vista.
             # Availability: Tk 8.6, Windows XP and Vista.
             class_name, part_id = args[:2]
-            statemap = _format_mapdict({None: args[2:]})[1]
+            statemap = _join(_mapdict_values(args[2:]))
             spec = "%s %s %s" % (class_name, part_id, statemap)
 
         opts = _format_optdict(kw, script)
@@ -148,11 +143,11 @@
         # otherwise it will clone {} (empty element)
         spec = args[0] # theme name
         if len(args) > 1: # elementfrom specified
-            opts = (args[1], )
+            opts = (_format_optvalue(args[1], script),)
 
     if script:
         spec = '{%s}' % spec
-        opts = ' '.join(map(str, opts))
+        opts = ' '.join(opts)
 
     return spec, opts
 
@@ -189,7 +184,7 @@
     for layout_elem in layout:
         elem, opts = layout_elem
         opts = opts or {}
-        fopts = ' '.join(map(str, _format_optdict(opts, True, "children")))
+        fopts = ' '.join(_format_optdict(opts, True, ("children",)))
         head = "%s%s%s" % (' ' * indent, elem, (" %s" % fopts) if fopts else 
'')
 
         if "children" in opts:
@@ -215,11 +210,11 @@
     for name, opts in settings.iteritems():
         # will format specific keys according to Tcl code
         if opts.get('configure'): # format 'configure'
-            s = ' '.join(map(unicode, _format_optdict(opts['configure'], 
True)))
+            s = ' '.join(_format_optdict(opts['configure'], True))
             script.append("ttk::style configure %s %s;" % (name, s))
 
         if opts.get('map'): # format 'map'
-            s = ' '.join(map(unicode, _format_mapdict(opts['map'], True)))
+            s = ' '.join(_format_mapdict(opts['map'], True))
             script.append("ttk::style map %s %s;" % (name, s))
 
         if 'layout' in opts: # format 'layout' which may be empty
@@ -706,30 +701,9 @@
             exportselection, justify, height, postcommand, state,
             textvariable, values, width
         """
-        # The "values" option may need special formatting, so leave to
-        # _format_optdict the responsibility to format it
-        if "values" in kw:
-            kw["values"] = _format_optdict({'v': kw["values"]})[1]
-
         Entry.__init__(self, master, "ttk::combobox", **kw)
 
 
-    def __setitem__(self, item, value):
-        if item == "values":
-            value = _format_optdict({item: value})[1]
-
-        Entry.__setitem__(self, item, value)
-
-
-    def configure(self, cnf=None, **kw):
-        """Custom Combobox configure, created to properly format the values
-        option."""
-        if "values" in kw:
-            kw["values"] = _format_optdict({'v': kw["values"]})[1]
-
-        return Entry.configure(self, cnf, **kw)
-
-
     def current(self, newindex=None):
         """If newindex is supplied, sets the combobox value to the
         element at position newindex in the list of values. Otherwise,
diff -r b0935ef48186 Lib/test/test_glob.py
--- a/Lib/test/test_glob.py     Sun Dec 16 13:55:47 2012 +0100
+++ b/Lib/test/test_glob.py     Sun Dec 16 20:53:46 2012 +0200
@@ -5,6 +5,8 @@
 import shutil
 import sys
 
+def fsdecode(s):
+    return unicode(s, sys.getfilesystemencoding())
 
 class GlobTests(unittest.TestCase):
 
@@ -31,7 +33,8 @@
         self.mktemp('a', 'bcd', 'efg', 'ha')
         if hasattr(os, 'symlink'):
             os.symlink(self.norm('broken'), self.norm('sym1'))
-            os.symlink(self.norm('broken'), self.norm('sym2'))
+            os.symlink('broken', self.norm('sym2'))
+            os.symlink(os.path.join('a', 'bcd'), self.norm('sym3'))
 
     def tearDown(self):
         shutil.rmtree(self.tempdir)
@@ -44,10 +47,16 @@
         p = os.path.join(self.tempdir, pattern)
         res = glob.glob(p)
         self.assertEqual(list(glob.iglob(p)), res)
+        ures = [fsdecode(x) for x in res]
+        self.assertEqual(glob.glob(fsdecode(p)), ures)
+        self.assertEqual(list(glob.iglob(fsdecode(p))), ures)
         return res
 
     def assertSequencesEqual_noorder(self, l1, l2):
+        l1 = list(l1)
+        l2 = list(l2)
         self.assertEqual(set(l1), set(l2))
+        self.assertEqual(sorted(l1), sorted(l2))
 
     def test_glob_literal(self):
         eq = self.assertSequencesEqual_noorder
@@ -58,13 +67,23 @@
 
         # test return types are unicode, but only if os.listdir
         # returns unicode filenames
-        uniset = set([unicode])
-        tmp = os.listdir(u'.')
-        if set(type(x) for x in tmp) == uniset:
+        uniset = {unicode}
+        tmp = os.listdir(fsdecode(os.curdir))
+        if {type(x) for x in tmp} == uniset:
             u1 = glob.glob(u'*')
-            u2 = glob.glob(u'./*')
-            self.assertEqual(set(type(r) for r in u1), uniset)
-            self.assertEqual(set(type(r) for r in u2), uniset)
+            u2 = glob.glob(os.path.join(fsdecode(os.curdir), u'*'))
+            self.assertEqual({type(r) for r in u1}, uniset)
+            self.assertEqual({type(r) for r in u2}, uniset)
+
+        # test return types are string, but only if os.listdir
+        # returns string filenames
+        strset = {str}
+        tmp = os.listdir(os.curdir)
+        if {type(x) for x in tmp} == strset:
+            u1 = glob.glob('*')
+            u2 = glob.glob(os.path.join(os.curdir, '*'))
+            self.assertEqual({type(r) for r in u1}, strset)
+            self.assertEqual({type(r) for r in u2}, strset)
 
     def test_glob_one_directory(self):
         eq = self.assertSequencesEqual_noorder
@@ -103,11 +122,24 @@
         self.assertEqual(len(res), 1)
         # either of these results are reasonable
         self.assertIn(res[0], [self.tempdir, self.tempdir + os.sep])
+        eq = self.assertSequencesEqual_noorder
+        eq(self.glob('a*', ''), [os.path.join(self.tempdir, x, '')
+                                 for x in ['a', 'aaa', 'aab']])
+
+    def test_glob_symlinks(self):
+        if hasattr(os, 'symlink'):
+            eq = self.assertSequencesEqual_noorder
+            eq(self.glob('sym3'), [self.norm('sym3')])
+            eq(self.glob('sym3', '*'), [self.norm('sym3', 'EF'),
+                                        self.norm('sym3', 'efg')])
+            eq(self.glob('*', '*F'), [self.norm('aaa', 'zzzF'),
+                    self.norm('aab', 'F'), self.norm('sym3', 'EF')])
 
     def test_glob_broken_symlinks(self):
         if hasattr(os, 'symlink'):
             eq = self.assertSequencesEqual_noorder
-            eq(self.glob('sym*'), [self.norm('sym1'), self.norm('sym2')])
+            eq(self.glob('sym*'), [self.norm('sym1'), self.norm('sym2'),
+                                self.norm('sym3')])
             eq(self.glob('sym1'), [self.norm('sym1')])
             eq(self.glob('sym2'), [self.norm('sym2')])
 
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to