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