Update SQLAlchemy
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
# util/__init__.py
|
||||
# Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
from compat import callable, cmp, reduce, defaultdict, py25_dict, \
|
||||
threading, py3k_warning, jython, pypy, win32, set_types, buffer, pickle, \
|
||||
update_wrapper, partial, md5_hex, decode_slice, dottedgetter,\
|
||||
parse_qsl, any, contextmanager
|
||||
threading, py3k_warning, jython, pypy, cpython, win32, set_types, buffer, \
|
||||
pickle, update_wrapper, partial, md5_hex, decode_slice, dottedgetter,\
|
||||
parse_qsl, any, contextmanager, next
|
||||
|
||||
from _collections import NamedTuple, ImmutableContainer, immutabledict, \
|
||||
Properties, OrderedProperties, ImmutableProperties, OrderedDict, \
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# util/_collections.py
|
||||
# Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
@@ -210,7 +210,7 @@ class OrderedDict(dict):
|
||||
try:
|
||||
self._list.append(key)
|
||||
except AttributeError:
|
||||
# work around Python pickle loads() with
|
||||
# work around Python pickle loads() with
|
||||
# dict subclass (seems to ignore __setstate__?)
|
||||
self._list = [key]
|
||||
dict.__setitem__(self, key, object)
|
||||
@@ -585,7 +585,7 @@ else:
|
||||
self[key] = value = self.creator(key)
|
||||
return value
|
||||
|
||||
# define collections that are capable of storing
|
||||
# define collections that are capable of storing
|
||||
# ColumnElement objects as hashable keys/elements.
|
||||
column_set = set
|
||||
column_dict = dict
|
||||
@@ -595,12 +595,12 @@ populate_column_dict = PopulateDict
|
||||
def unique_list(seq, hashfunc=None):
|
||||
seen = {}
|
||||
if not hashfunc:
|
||||
return [x for x in seq
|
||||
if x not in seen
|
||||
return [x for x in seq
|
||||
if x not in seen
|
||||
and not seen.__setitem__(x, True)]
|
||||
else:
|
||||
return [x for x in seq
|
||||
if hashfunc(x) not in seen
|
||||
return [x for x in seq
|
||||
if hashfunc(x) not in seen
|
||||
and not seen.__setitem__(hashfunc(x), True)]
|
||||
|
||||
class UniqueAppender(object):
|
||||
@@ -801,15 +801,15 @@ class LRUCache(dict):
|
||||
|
||||
def _manage_size(self):
|
||||
while len(self) > self.capacity + self.capacity * self.threshold:
|
||||
by_counter = sorted(dict.values(self),
|
||||
by_counter = sorted(dict.values(self),
|
||||
key=operator.itemgetter(2),
|
||||
reverse=True)
|
||||
for item in by_counter[self.capacity:]:
|
||||
try:
|
||||
del self[item[0]]
|
||||
except KeyError:
|
||||
# if we couldnt find a key, most
|
||||
# likely some other thread broke in
|
||||
# if we couldnt find a key, most
|
||||
# likely some other thread broke in
|
||||
# on us. loop around and try again
|
||||
break
|
||||
|
||||
@@ -870,7 +870,7 @@ class ScopedRegistry(object):
|
||||
pass
|
||||
|
||||
class ThreadLocalRegistry(ScopedRegistry):
|
||||
"""A :class:`.ScopedRegistry` that uses a ``threading.local()``
|
||||
"""A :class:`.ScopedRegistry` that uses a ``threading.local()``
|
||||
variable for storage.
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# util/compat.py
|
||||
# Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
@@ -19,6 +19,7 @@ py3k_warning = getattr(sys, 'py3kwarning', False) or sys.version_info >= (3, 0)
|
||||
jython = sys.platform.startswith('java')
|
||||
pypy = hasattr(sys, 'pypy_version_info')
|
||||
win32 = sys.platform.startswith('win')
|
||||
cpython = not pypy and not jython # TODO: something better for this ?
|
||||
|
||||
if py3k_warning:
|
||||
set_types = set
|
||||
@@ -40,6 +41,11 @@ else:
|
||||
|
||||
set_types = set, sets.Set
|
||||
|
||||
if sys.version_info < (2, 6):
|
||||
def next(iter):
|
||||
return iter.next()
|
||||
else:
|
||||
next = next
|
||||
if py3k_warning:
|
||||
import pickle
|
||||
else:
|
||||
@@ -50,7 +56,7 @@ else:
|
||||
|
||||
# a controversial feature, required by MySQLdb currently
|
||||
def buffer(x):
|
||||
return x
|
||||
return x
|
||||
|
||||
# Py2K
|
||||
buffer = buffer
|
||||
@@ -193,7 +199,7 @@ import time
|
||||
if win32 or jython:
|
||||
time_func = time.clock
|
||||
else:
|
||||
time_func = time.time
|
||||
time_func = time.time
|
||||
|
||||
if sys.version_info >= (2, 5):
|
||||
any = any
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# util/deprecations.py
|
||||
# Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# util/langhelpers.py
|
||||
# Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
@@ -239,14 +239,16 @@ def unbound_method_to_callable(func_or_cls):
|
||||
else:
|
||||
return func_or_cls
|
||||
|
||||
def generic_repr(obj):
|
||||
def generic_repr(obj, additional_kw=(), to_inspect=None):
|
||||
"""Produce a __repr__() based on direct association of the __init__()
|
||||
specification vs. same-named attributes present.
|
||||
|
||||
|
||||
"""
|
||||
if to_inspect is None:
|
||||
to_inspect = obj
|
||||
def genargs():
|
||||
try:
|
||||
(args, vargs, vkw, defaults) = inspect.getargspec(obj.__init__)
|
||||
(args, vargs, vkw, defaults) = inspect.getargspec(to_inspect.__init__)
|
||||
except TypeError:
|
||||
return
|
||||
|
||||
@@ -267,6 +269,15 @@ def generic_repr(obj):
|
||||
yield '%s=%r' % (arg, val)
|
||||
except:
|
||||
pass
|
||||
if additional_kw:
|
||||
for arg, defval in additional_kw:
|
||||
try:
|
||||
val = getattr(obj, arg, None)
|
||||
if val != defval:
|
||||
yield '%s=%r' % (arg, val)
|
||||
except:
|
||||
pass
|
||||
|
||||
return "%s(%s)" % (obj.__class__.__name__, ", ".join(genargs()))
|
||||
|
||||
class portable_instancemethod(object):
|
||||
@@ -485,6 +496,8 @@ class memoized_property(object):
|
||||
obj.__dict__[self.__name__] = result = self.fget(obj)
|
||||
return result
|
||||
|
||||
def _reset(self, obj):
|
||||
obj.__dict__.pop(self.__name__, None)
|
||||
|
||||
class memoized_instancemethod(object):
|
||||
"""Decorate a method memoize its return value.
|
||||
@@ -551,10 +564,10 @@ class importlater(object):
|
||||
from mypackage.somemodule import somesubmod
|
||||
|
||||
except evaluted upon attribute access to "somesubmod".
|
||||
|
||||
|
||||
importlater() currently requires that resolve_all() be
|
||||
called, typically at the bottom of a package's __init__.py.
|
||||
This is so that __import__ still called only at
|
||||
This is so that __import__ still called only at
|
||||
module import time, and not potentially within
|
||||
a non-main thread later on.
|
||||
|
||||
@@ -597,14 +610,14 @@ class importlater(object):
|
||||
importlater._unresolved.discard(self)
|
||||
if self._il_addtl:
|
||||
self._initial_import = __import__(
|
||||
self._il_path, globals(), locals(),
|
||||
self._il_path, globals(), locals(),
|
||||
[self._il_addtl])
|
||||
else:
|
||||
self._initial_import = __import__(self._il_path)
|
||||
|
||||
def __getattr__(self, key):
|
||||
if key == 'module':
|
||||
raise ImportError("Could not resolve module %s"
|
||||
raise ImportError("Could not resolve module %s"
|
||||
% self._full_path)
|
||||
try:
|
||||
attr = getattr(self.module, key)
|
||||
@@ -860,8 +873,8 @@ def warn(msg, stacklevel=3):
|
||||
If msg is a string, :class:`.exc.SAWarning` is used as
|
||||
the category.
|
||||
|
||||
.. note::
|
||||
|
||||
.. note::
|
||||
|
||||
This function is swapped out when the test suite
|
||||
runs, with a compatible version that uses
|
||||
warnings.warn_explicit, so that the warnings registry can
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# util/queue.py
|
||||
# Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
@@ -16,6 +16,15 @@ condition."""
|
||||
from collections import deque
|
||||
from time import time as _time
|
||||
from sqlalchemy.util import threading
|
||||
import sys
|
||||
|
||||
if sys.version_info < (2, 6):
|
||||
def notify_all(condition):
|
||||
condition.notify()
|
||||
else:
|
||||
def notify_all(condition):
|
||||
condition.notify_all()
|
||||
|
||||
|
||||
__all__ = ['Empty', 'Full', 'Queue']
|
||||
|
||||
@@ -29,6 +38,11 @@ class Full(Exception):
|
||||
|
||||
pass
|
||||
|
||||
class SAAbort(Exception):
|
||||
"Special SQLA exception to abort waiting"
|
||||
def __init__(self, context):
|
||||
self.context = context
|
||||
|
||||
class Queue:
|
||||
def __init__(self, maxsize=0):
|
||||
"""Initialize a queue object with a given maximum size.
|
||||
@@ -49,6 +63,9 @@ class Queue:
|
||||
# a thread waiting to put is notified then.
|
||||
self.not_full = threading.Condition(self.mutex)
|
||||
|
||||
# when this is set, SAAbort is raised within get().
|
||||
self._sqla_abort_context = False
|
||||
|
||||
def qsize(self):
|
||||
"""Return the approximate size of the queue (not reliable!)."""
|
||||
|
||||
@@ -138,6 +155,8 @@ class Queue:
|
||||
elif timeout is None:
|
||||
while self._empty():
|
||||
self.not_empty.wait()
|
||||
if self._sqla_abort_context:
|
||||
raise SAAbort(self._sqla_abort_context)
|
||||
else:
|
||||
if timeout < 0:
|
||||
raise ValueError("'timeout' must be a positive number")
|
||||
@@ -147,12 +166,27 @@ class Queue:
|
||||
if remaining <= 0.0:
|
||||
raise Empty
|
||||
self.not_empty.wait(remaining)
|
||||
if self._sqla_abort_context:
|
||||
raise SAAbort(self._sqla_abort_context)
|
||||
item = self._get()
|
||||
self.not_full.notify()
|
||||
return item
|
||||
finally:
|
||||
self.not_empty.release()
|
||||
|
||||
def abort(self, context):
|
||||
"""Issue an 'abort', will force any thread waiting on get()
|
||||
to stop waiting and raise SAAbort.
|
||||
|
||||
"""
|
||||
self._sqla_abort_context = context
|
||||
if not self.not_full.acquire(False):
|
||||
return
|
||||
try:
|
||||
notify_all(self.not_empty)
|
||||
finally:
|
||||
self.not_full.release()
|
||||
|
||||
def get_nowait(self):
|
||||
"""Remove and return an item from the queue without blocking.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# util/topological.py
|
||||
# Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
@@ -29,7 +29,7 @@ def sort_as_subsets(tuples, allitems):
|
||||
if not output:
|
||||
raise CircularDependencyError(
|
||||
"Circular dependency detected.",
|
||||
find_cycles(tuples, allitems),
|
||||
find_cycles(tuples, allitems),
|
||||
_gen_edges(edges)
|
||||
)
|
||||
|
||||
@@ -56,7 +56,7 @@ def find_cycles(tuples, allitems):
|
||||
|
||||
output = set()
|
||||
|
||||
# we'd like to find all nodes that are
|
||||
# we'd like to find all nodes that are
|
||||
# involved in cycles, so we do the full
|
||||
# pass through the whole thing for each
|
||||
# node in the original list.
|
||||
@@ -86,7 +86,7 @@ def find_cycles(tuples, allitems):
|
||||
|
||||
def _gen_edges(edges):
|
||||
return set([
|
||||
(right, left)
|
||||
for left in edges
|
||||
for right in edges[left]
|
||||
(right, left)
|
||||
for left in edges
|
||||
for right in edges[left]
|
||||
])
|
||||
|
||||
Reference in New Issue
Block a user