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) {