This commit is contained in:
MiCHiLU 2012-09-18 19:18:03 +09:00
parent ac8547656f
commit 5673e3556e
4 changed files with 48 additions and 85 deletions

View File

@ -12,11 +12,14 @@ __all__ = ['update_wrapper', 'wraps', 'WRAPPER_ASSIGNMENTS', 'WRAPPER_UPDATES',
'total_ordering', 'cmp_to_key', 'lru_cache', 'reduce', 'partial']
from _functools import partial, reduce
from collections import OrderedDict, namedtuple
from collections import MutableMapping, namedtuple
from reprlib32 import recursive_repr as _recursive_repr
from weakref import proxy as _proxy
import sys as _sys
try:
from _thread import allocate_lock as Lock
except:
from _dummy_thread import allocate_lock as Lock
from _dummy_thread32 import allocate_lock as Lock
################################################################################
### OrderedDict
@ -237,7 +240,7 @@ class OrderedDict(dict):
# update_wrapper() and wraps() are tools to help write
# wrapper functions that can handle naive introspection
WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__', '__annotations__')
WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')
WRAPPER_UPDATES = ('__dict__',)
def update_wrapper(wrapper,
wrapped,
@ -297,8 +300,7 @@ def total_ordering(cls):
('__gt__', lambda self, other: self >= other and not self == other),
('__lt__', lambda self, other: not self >= other)]
}
# Find user-defined comparisons (not those inherited from object).
roots = [op for op in convert if getattr(cls, op, None) is not getattr(object, op, None)]
roots = set(dir(cls)) & set(convert)
if not roots:
raise ValueError('must define at least one ordering operation: < > <= >=')
root = max(roots) # prefer __lt__ to __le__ to __gt__ to __ge__
@ -355,7 +357,7 @@ def lru_cache(maxsize=100):
def decorating_function(user_function,
tuple=tuple, sorted=sorted, len=len, KeyError=KeyError):
hits = misses = 0
hits, misses = [0], [0]
kwd_mark = (object(),) # separates positional and keyword args
lock = Lock() # needed because OrderedDict isn't threadsafe
@ -364,19 +366,18 @@ def lru_cache(maxsize=100):
@wraps(user_function)
def wrapper(*args, **kwds):
nonlocal hits, misses
key = args
if kwds:
key += kwd_mark + tuple(sorted(kwds.items()))
try:
result = cache[key]
hits += 1
hits[0] += 1
return result
except KeyError:
pass
result = user_function(*args, **kwds)
cache[key] = result
misses += 1
misses[0] += 1
return result
else:
cache = OrderedDict() # ordered least recent to most recent
@ -385,7 +386,6 @@ def lru_cache(maxsize=100):
@wraps(user_function)
def wrapper(*args, **kwds):
nonlocal hits, misses
key = args
if kwds:
key += kwd_mark + tuple(sorted(kwds.items()))
@ -393,14 +393,14 @@ def lru_cache(maxsize=100):
try:
result = cache[key]
cache_renew(key) # record recent use of this key
hits += 1
hits[0] += 1
return result
except KeyError:
pass
result = user_function(*args, **kwds)
with lock:
cache[key] = result # record recent use of this key
misses += 1
misses[0] += 1
if len(cache) > maxsize:
cache_popitem(0) # purge least recently used cache entry
return result
@ -408,14 +408,13 @@ def lru_cache(maxsize=100):
def cache_info():
"""Report cache statistics"""
with lock:
return _CacheInfo(hits, misses, maxsize, len(cache))
return _CacheInfo(hits[0], misses[0], maxsize, len(cache))
def cache_clear():
"""Clear the cache and cache statistics"""
nonlocal hits, misses
with lock:
cache.clear()
hits = misses = 0
hits[0] = misses[0] = 0
wrapper.cache_info = cache_info
wrapper.cache_clear = cache_clear

View File

@ -2,12 +2,12 @@
__all__ = ["Repr", "repr", "recursive_repr"]
import builtins
import __builtin__ as builtins
from itertools import islice
try:
from _thread import get_ident
except ImportError:
from _dummy_thread import get_ident
from _dummy_thread32 import get_ident
def recursive_repr(fillvalue='...'):
'Decorator to make a repr function return fillvalue for a recursive call'

View File

@ -1,8 +1,8 @@
import functools
import functools32 as functools
import collections
import sys
import unittest
from test import support
import test_support32 as support
from weakref import proxy
import pickle
from random import choice
@ -48,9 +48,9 @@ class TestPartial(unittest.TestCase):
# attributes should not be writable
if not isinstance(self.thetype, type):
return
self.assertRaises(AttributeError, setattr, p, 'func', map)
self.assertRaises(AttributeError, setattr, p, 'args', (1, 2))
self.assertRaises(AttributeError, setattr, p, 'keywords', dict(a=1, b=2))
self.assertRaises(TypeError, setattr, p, 'func', map)
self.assertRaises(TypeError, setattr, p, 'args', (1, 2))
self.assertRaises(TypeError, setattr, p, 'keywords', dict(a=1, b=2))
p = self.thetype(hex)
try:
@ -148,32 +148,6 @@ class TestPartial(unittest.TestCase):
join = self.thetype(''.join)
self.assertEqual(join(data), '0123456789')
def test_repr(self):
args = (object(), object())
args_repr = ', '.join(repr(a) for a in args)
kwargs = {'a': object(), 'b': object()}
kwargs_repr = ', '.join("%s=%r" % (k, v) for k, v in kwargs.items())
if self.thetype is functools.partial:
name = 'functools.partial'
else:
name = self.thetype.__name__
f = self.thetype(capture)
self.assertEqual('{}({!r})'.format(name, capture),
repr(f))
f = self.thetype(capture, *args)
self.assertEqual('{}({!r}, {})'.format(name, capture, args_repr),
repr(f))
f = self.thetype(capture, **kwargs)
self.assertEqual('{}({!r}, {})'.format(name, capture, kwargs_repr),
repr(f))
f = self.thetype(capture, *args, **kwargs)
self.assertEqual('{}({!r}, {}, {})'.format(name, capture, args_repr, kwargs_repr),
repr(f))
def test_pickle(self):
f = self.thetype(signature, 'asdf', bar=True)
f.add_something_to__dict__ = True
@ -213,11 +187,11 @@ class TestUpdateWrapper(unittest.TestCase):
self.assertTrue(wrapped_attr[key] is wrapper_attr[key])
def _default_update(self):
def f(a:'This is a new annotation'):
def f(a):
"""This is a test"""
pass
f.attr = 'This is also a test'
def wrapper(b:'This is the prior annotation'):
def wrapper(b):
pass
functools.update_wrapper(wrapper, f)
return wrapper, f
@ -228,8 +202,6 @@ class TestUpdateWrapper(unittest.TestCase):
self.assertIs(wrapper.__wrapped__, f)
self.assertEqual(wrapper.__name__, 'f')
self.assertEqual(wrapper.attr, 'This is also a test')
self.assertEqual(wrapper.__annotations__['a'], 'This is a new annotation')
self.assertNotIn('b', wrapper.__annotations__)
@unittest.skipIf(sys.flags.optimize >= 2,
"Docstrings are omitted with -O2 and above")
@ -248,7 +220,6 @@ class TestUpdateWrapper(unittest.TestCase):
self.check_wrapper(wrapper, f, (), ())
self.assertEqual(wrapper.__name__, 'wrapper')
self.assertEqual(wrapper.__doc__, None)
self.assertEqual(wrapper.__annotations__, {})
self.assertFalse(hasattr(wrapper, 'attr'))
def test_selective_update(self):
@ -297,7 +268,6 @@ class TestUpdateWrapper(unittest.TestCase):
functools.update_wrapper(wrapper, max)
self.assertEqual(wrapper.__name__, 'max')
self.assertTrue(wrapper.__doc__.startswith('max('))
self.assertEqual(wrapper.__annotations__, {})
class TestWraps(TestUpdateWrapper):
@ -401,11 +371,6 @@ class TestReduce(unittest.TestCase):
self.assertRaises(TypeError, self.func, add, ())
self.assertRaises(TypeError, self.func, add, object())
class TestFailingIter:
def __iter__(self):
raise RuntimeError
self.assertRaises(RuntimeError, self.func, add, TestFailingIter())
self.assertEqual(self.func(add, [], None), None)
self.assertEqual(self.func(add, [], 42), 42)
@ -520,14 +485,14 @@ class TestTotalOrdering(unittest.TestCase):
def test_total_ordering_no_overwrite(self):
# new methods should not overwrite existing
@functools.total_ordering
class A(int):
class A(str):
pass
self.assertTrue(A(1) < A(2))
self.assertTrue(A(2) > A(1))
self.assertTrue(A(1) <= A(2))
self.assertTrue(A(2) >= A(1))
self.assertTrue(A(2) <= A(2))
self.assertTrue(A(2) >= A(2))
self.assertTrue(A("a") < A("b"))
self.assertTrue(A("b") > A("a"))
self.assertTrue(A("a") <= A("b"))
self.assertTrue(A("b") >= A("a"))
self.assertTrue(A("b") <= A("b"))
self.assertTrue(A("b") >= A("b"))
def test_no_operations_defined(self):
with self.assertRaises(ValueError):
@ -596,14 +561,13 @@ class TestLRU(unittest.TestCase):
# test size zero (which means "never-cache")
@functools.lru_cache(0)
def f():
nonlocal f_cnt
f_cnt += 1
f_cnt[0] += 1
return 20
self.assertEqual(f.cache_info().maxsize, 0)
f_cnt = 0
f_cnt = [0]
for i in range(5):
self.assertEqual(f(), 20)
self.assertEqual(f_cnt, 5)
self.assertEqual(f_cnt[0], 5)
hits, misses, maxsize, currsize = f.cache_info()
self.assertEqual(hits, 0)
self.assertEqual(misses, 5)
@ -612,14 +576,13 @@ class TestLRU(unittest.TestCase):
# test size one
@functools.lru_cache(1)
def f():
nonlocal f_cnt
f_cnt += 1
f_cnt[0] += 1
return 20
self.assertEqual(f.cache_info().maxsize, 1)
f_cnt = 0
f_cnt = [0]
for i in range(5):
self.assertEqual(f(), 20)
self.assertEqual(f_cnt, 1)
self.assertEqual(f_cnt[0], 1)
hits, misses, maxsize, currsize = f.cache_info()
self.assertEqual(hits, 4)
self.assertEqual(misses, 1)
@ -628,15 +591,14 @@ class TestLRU(unittest.TestCase):
# test size two
@functools.lru_cache(2)
def f(x):
nonlocal f_cnt
f_cnt += 1
f_cnt[0] += 1
return x*10
self.assertEqual(f.cache_info().maxsize, 2)
f_cnt = 0
f_cnt = [0]
for x in 7, 9, 7, 9, 7, 9, 8, 8, 8, 9, 9, 9, 8, 8, 8, 7:
# * * * *
self.assertEqual(f(x), x*10)
self.assertEqual(f_cnt, 4)
self.assertEqual(f_cnt[0], 4)
hits, misses, maxsize, currsize = f.cache_info()
self.assertEqual(hits, 12)
self.assertEqual(misses, 4)
@ -665,9 +627,8 @@ class TestLRU(unittest.TestCase):
def func(i):
return 'abc'[i]
self.assertEqual(func(0), 'a')
with self.assertRaises(IndexError) as cm:
with self.assertRaises(IndexError):
func(15)
self.assertIsNone(cm.exception.__context__)
# Verify that the previous exception did not result in a cached entry
with self.assertRaises(IndexError):
func(15)

View File

@ -1,6 +1,6 @@
"""Supporting definitions for the Python regression tests."""
if __name__ != 'test.support':
if __name__ != 'test_support32':
raise ImportError('support must be imported from the test package')
import contextlib
@ -458,7 +458,7 @@ TESTFN = "{}_{}_tmp".format(TESTFN, os.getpid())
# TESTFN_UNICODE is a non-ascii filename
TESTFN_UNICODE = TESTFN + "-\xe0\xf2\u0258\u0141\u011f"
TESTFN_UNICODE = TESTFN + u"-\xe0\xf2\u0258\u0141\u011f"
if sys.platform == 'darwin':
# In Mac OS X's VFS API file names are, by definition, canonically
# decomposed Unicode, encoded using UTF-8. See QA1173:
@ -618,7 +618,7 @@ def open_urlresource(url, *args, **kw):
# Verify the requirement before downloading the file
requires('urlfetch')
print('\tfetching %s ...' % url, file=get_original_stdout())
print >>get_original_stdout(), '\tfetching %s ...' % url
f = urllib.request.urlopen(url, timeout=15)
try:
with open(fn, "wb") as out:
@ -865,7 +865,7 @@ ioerror_peer_reset = TransientResource(IOError, errno=errno.ECONNRESET)
@contextlib.contextmanager
def transient_internet(resource_name, *, timeout=30.0, errnos=()):
def transient_internet(resource_name, timeout=30.0, errnos=(), *_argv):
"""Return a context manager that raises ResourceDenied when various issues
with the Internet connection manifest themselves as exceptions."""
default_errnos = [
@ -900,7 +900,10 @@ def transient_internet(resource_name, *, timeout=30.0, errnos=()):
n in captured_errnos):
if not verbose:
sys.stderr.write(denied.args[0] + "\n")
raise denied from err
try:
raise err
except:
raise denied
old_timeout = socket.getdefaulttimeout()
try: