<html><body>
<p>1 new commit in yt:</p>
<p><a href="https://bitbucket.org/yt_analysis/yt/commits/236cd5cc2b6a/">https://bitbucket.org/yt_analysis/yt/commits/236cd5cc2b6a/</a> Changeset:   236cd5cc2b6a Branch:      yt User:        chummels Date:        2016-05-03 00:23:36+00:00 Summary:     Merged in ngoldbaum/yt (pull request #2142)</p>
<p>Units speedup Affected #:  6 files</p>
<p>diff -r 2d7b93e59428f2dc6d4cde5030cacc4b113c6ea4 -r 236cd5cc2b6a0b7b96ebe64a9a223f14bc86728e setup.cfg --- a/setup.cfg +++ b/setup.cfg @@ -10,10 +10,10 @@</p>
<pre>[flake8]
# we exclude:</pre>
<p>-#      api.py and __init__.py files to avoid spurious unused import errors -#      _mpl_imports.py for the same reason +#      api.py, mods.py, _mpl_imports.py, and __init__.py files to avoid spurious +#      unused import errors</p>
<pre>#      autogenerated __config__.py files
#      vendored libraries</pre>
<p>-exclude = */api.py,*/__init__.py,*/__config__.py,yt/visualization/_mpl_imports.py,yt/utilities/lodgeit.py,yt/utilities/poster/*,yt/extern/*,yt/mods.py +exclude = */api.py,*/__init__.py,*/__config__.py,yt/visualization/_mpl_imports.py,yt/utilities/lodgeit.py,yt/utilities/lru_cache.py,yt/utilities/poster/*,yt/extern/*,yt/mods.py</p>
<pre>max-line-length=999
ignore = E111,E121,E122,E123,E124,E125,E126,E127,E128,E129,E131,E201,E202,E211,E221,E222,E227,E228,E241,E301,E203,E225,E226,E231,E251,E261,E262,E265,E266,E302,E303,E402,E502,E701,E703,E731,W291,W292,W293,W391,W503</pre>
<p>\ No newline at end of file</p>
<p>diff -r 2d7b93e59428f2dc6d4cde5030cacc4b113c6ea4 -r 236cd5cc2b6a0b7b96ebe64a9a223f14bc86728e yt/extern/functools32.py --- a/yt/extern/functools32.py +++ /dev/null @@ -1,423 +0,0 @@ -"""functools.py – Tools for working with functions and callable objects -""" -# Python module wrapper for <em>functools C module -# to allow utilities written in Python to be added -# to the functools module. -# Written by Nick Coghlan <ncoghlan at gmail.com> -# and Raymond Hettinger <python at rcn.com> -#   Copyright © 2006-2010 Python Software Foundation. -# See C source code for <em>functools credits/copyright – -__all</em></em> = ['update_wrapper', ‘wraps’, ‘WRAPPER_ASSIGNMENTS’, ‘WRAPPER_UPDATES’,</p>
<ul><li><p>‘total_ordering’, ‘cmp_to_key’, ‘lru_cache’, ‘reduce’, ‘partial’]</p></li></ul>
<p>– -from _functools import partial, reduce -from collections import MutableMapping, namedtuple -from .reprlib32 import recursive_repr as _recursive_repr -from weakref import proxy as _proxy -import sys as _sys -try:</p>
<ul><li><p>from _thread import allocate_lock as Lock</p></li></ul>
<p>-except:</p>
<ul><li><p>from ._dummy_thread32 import allocate_lock as Lock</p></li></ul>
<p>– -################################################################################ -### OrderedDict -################################################################################ – -class _Link(object):</p>
<ul><li><p><em>_slots</em>_ = ‘prev’, ‘next’, ‘key’, ‘__weakref__’</p></li></ul>
<p>– -class OrderedDict(dict):</p>
<ul><li><p>‘Dictionary that remembers insertion order’</p></li>
<li><p># An inherited dict maps keys to values.</p></li>
<li><p># The inherited dict provides <em>_getitem_</em>, <em>_len_</em>, <em>_contains_</em>, and get.</p></li>
<li><p># The remaining methods are order-aware.</p></li>
<li><p># Big-O running times for all methods are the same as regular dictionaries.</p></li></ul>
<p>–</p>
<ul><li><p># The internal self.__map dict maps keys to links in a doubly linked list.</p></li>
<li><p># The circular doubly linked list starts and ends with a sentinel element.</p></li>
<li><p># The sentinel element never gets deleted (this simplifies the algorithm).</p></li>
<li><p># The sentinel is in self.__hardroot with a weakref proxy in self.__root.</p></li>
<li><p># The prev links are weakref proxies (to prevent circular references).</p></li>
<li><p># Individual links are kept alive by the hard reference in self.__map.</p></li>
<li><p># Those hard references disappear when a key is deleted from an OrderedDict.</p></li></ul>
<p>–</p>
<ul><li><p>def __init__(self, *args, **kwds):</p></li>
<li><p>'''Initialize an ordered dictionary.  The signature is the same as</p></li>
<li><p>regular dictionaries, but keyword arguments are not recommended because</p></li>
<li><p>their insertion order is arbitrary.</p></li></ul>
<p>–</p>
<ul><li><p>'''</p></li>
<li><p>if len(args) > 1:</p></li>
<li><p>raise TypeError('expected at most 1 arguments, got %d' % len(args))</p></li>
<li><p>try:</p></li>
<li><p>self.__root</p></li>
<li><p>except AttributeError:</p></li>
<li><p>self.__hardroot = _Link()</p></li>
<li><p>self.__root = root = _proxy(self.__hardroot)</p></li>
<li><p>root.prev = root.next = root</p></li>
<li><p>self.__map = {}</p></li>
<li><p>self.__update(*args, **kwds)</p></li></ul>
<p>–</p>
<ul><li><p>def __setitem__(self, key, value,</p></li>
<li><p>dict_setitem=dict.__setitem__, proxy=_proxy, Link=_Link):</p></li>
<li><p>‘od.__setitem__(i, y) <==> od[i]=y’</p></li>
<li><p># Setting a new item creates a new link at the end of the linked list,</p></li>
<li><p># and the inherited dictionary is updated with the new key/value pair.</p></li>
<li><p>if key not in self:</p></li>
<li><p>self.__map[key] = link = Link()</p></li>
<li><p>root = self.__root</p></li>
<li><p>last = root.prev</p></li>
<li><p>link.prev, link.next, link.key = last, root, key</p></li>
<li><p>last.next = link</p></li>
<li><p>root.prev = proxy(link)</p></li>
<li><p>dict_setitem(self, key, value)</p></li></ul>
<p>–</p>
<ul><li><p>def __delitem__(self, key, dict_delitem=dict.__delitem__):</p></li>
<li><p>‘od.__delitem__(y) <==> del od[y]’</p></li>
<li><p># Deleting an existing item uses self.__map to find the link which gets</p></li>
<li><p># removed by updating the links in the predecessor and successor nodes.</p></li>
<li><p>dict_delitem(self, key)</p></li>
<li><p>link = self.__map.pop(key)</p></li>
<li><p>link_prev = link.prev</p></li>
<li><p>link_next = link.next</p></li>
<li><p>link_prev.next = link_next</p></li>
<li><p>link_next.prev = link_prev</p></li></ul>
<p>–</p>
<ul><li><p>def __iter__(self):</p></li>
<li><p>‘od.__iter__() <==> iter(od)’</p></li>
<li><p># Traverse the linked list in order.</p></li>
<li><p>root = self.__root</p></li>
<li><p>curr = root.next</p></li>
<li><p>while curr is not root:</p></li>
<li><p>yield curr.key</p></li>
<li><p>curr = curr.next</p></li></ul>
<p>–</p>
<ul><li><p>def __reversed__(self):</p></li>
<li><p>‘od.__reversed__() <==> reversed(od)’</p></li>
<li><p># Traverse the linked list in reverse order.</p></li>
<li><p>root = self.__root</p></li>
<li><p>curr = root.prev</p></li>
<li><p>while curr is not root:</p></li>
<li><p>yield curr.key</p></li>
<li><p>curr = curr.prev</p></li></ul>
<p>–</p>
<ul><li><p>def clear(self):</p></li>
<li><p>‘od.clear() -> None.  Remove all items from od.’</p></li>
<li><p>root = self.__root</p></li>
<li><p>root.prev = root.next = root</p></li>
<li><p>self.__map.clear()</p></li>
<li><p>dict.clear(self)</p></li></ul>
<p>–</p>
<ul><li><p>def popitem(self, last=True):</p></li>
<li><p>'''od.popitem() -> (k, v), return and remove a (key, value) pair.</p></li>
<li><p>Pairs are returned in LIFO order if last is true or FIFO order if false.</p></li></ul>
<p>–</p>
<ul><li><p>'''</p></li>
<li><p>if not self:</p></li>
<li><p>raise KeyError('dictionary is empty')</p></li>
<li><p>root = self.__root</p></li>
<li><p>if last:</p></li>
<li><p>link = root.prev</p></li>
<li><p>link_prev = link.prev</p></li>
<li><p>link_prev.next = root</p></li>
<li><p>root.prev = link_prev</p></li>
<li><p>else:</p></li>
<li><p>link = root.next</p></li>
<li><p>link_next = link.next</p></li>
<li><p>root.next = link_next</p></li>
<li><p>link_next.prev = root</p></li>
<li><p>key = link.key</p></li>
<li><p>del self.__map[key]</p></li>
<li><p>value = dict.pop(self, key)</p></li>
<li><p>return key, value</p></li></ul>
<p>–</p>
<ul><li><p>def move_to_end(self, key, last=True):</p></li>
<li><p>'''Move an existing element to the end (or beginning if last==False).</p></li></ul>
<p>–</p>
<ul><li><p>Raises KeyError if the element does not exist.</p></li>
<li><p>When last=True, acts like a fast version of self[key]=self.pop(key).</p></li></ul>
<p>–</p>
<ul><li><p>'''</p></li>
<li><p>link = self.__map[key]</p></li>
<li><p>link_prev = link.prev</p></li>
<li><p>link_next = link.next</p></li>
<li><p>link_prev.next = link_next</p></li>
<li><p>link_next.prev = link_prev</p></li>
<li><p>root = self.__root</p></li>
<li><p>if last:</p></li>
<li><p>last = root.prev</p></li>
<li><p>link.prev = last</p></li>
<li><p>link.next = root</p></li>
<li><p>last.next = root.prev = link</p></li>
<li><p>else:</p></li>
<li><p>first = root.next</p></li>
<li><p>link.prev = root</p></li>
<li><p>link.next = first</p></li>
<li><p>root.next = first.prev = link</p></li></ul>
<p>–</p>
<ul><li><p>def __sizeof__(self):</p></li>
<li><p>sizeof = _sys.getsizeof</p></li>
<li><p>n = len(self) + 1                       # number of links including root</p></li>
<li><p>size = sizeof(self.__dict__)            # instance dictionary</p></li>
<li><p>size += sizeof(self.__map) * 2          # internal dict and inherited dict</p></li>
<li><p>size += sizeof(self.__hardroot) * n     # link objects</p></li>
<li><p>size += sizeof(self.__root) * n         # proxy objects</p></li>
<li><p>return size</p></li></ul>
<p>–</p>
<ul><li><p>update = __update = MutableMapping.update</p></li>
<li><p>keys = MutableMapping.keys</p></li>
<li><p>values = MutableMapping.values</p></li>
<li><p>items = MutableMapping.items</p></li>
<li><p><em>_ne</em>_ = MutableMapping.__ne__</p></li></ul>
<p>–</p>
<ul><li><p>__marker = object()</p></li></ul>
<p>–</p>
<ul><li><p>def pop(self, key, default=__marker):</p></li>
<li><p>'''od.pop(k[,d]) -> v, remove specified key and return the corresponding</p></li>
<li><p>value.  If key is not found, d is returned if given, otherwise KeyError</p></li>
<li><p>is raised.</p></li></ul>
<p>–</p>
<ul><li><p>'''</p></li>
<li><p>if key in self:</p></li>
<li><p>result = self[key]</p></li>
<li><p>del self[key]</p></li>
<li><p>return result</p></li>
<li><p>if default is self.__marker:</p></li>
<li><p>raise KeyError(key)</p></li>
<li><p>return default</p></li></ul>
<p>–</p>
<ul><li><p>def setdefault(self, key, default=None):</p></li>
<li><p>‘od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od’</p></li>
<li><p>if key in self:</p></li>
<li><p>return self[key]</p></li>
<li><p>self[key] = default</p></li>
<li><p>return default</p></li></ul>
<p>–</p>
<ul><li><p>@_recursive_repr()</p></li>
<li><p>def __repr__(self):</p></li>
<li><p>‘od.__repr__() <==> repr(od)’</p></li>
<li><p>if not self:</p></li>
<li><p>return ‘%s()’ % (self.__class__.__name__,)</p></li>
<li><p>return ‘%s(%r)’ % (self.__class__.__name__, list(self.items()))</p></li></ul>
<p>–</p>
<ul><li><p>def __reduce__(self):</p></li>
<li><p>‘Return state information for pickling’</p></li>
<li><p>items = [[k, self[k]] for k in self]</p></li>
<li><p>inst_dict = vars(self).copy()</p></li>
<li><p>for k in vars(OrderedDict()):</p></li>
<li><p>inst_dict.pop(k, None)</p></li>
<li><p>if inst_dict:</p></li>
<li><p>return (self.__class__, (items,), inst_dict)</p></li>
<li><p>return self.__class__, (items,)</p></li></ul>
<p>–</p>
<ul><li><p>def copy(self):</p></li>
<li><p>‘od.copy() -> a shallow copy of od’</p></li>
<li><p>return self.__class__(self)</p></li></ul>
<p>–</p>
<ul><li><p>@classmethod</p></li>
<li><p>def fromkeys(cls, iterable, value=None):</p></li>
<li><p>'''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S.</p></li>
<li><p>If not specified, the value defaults to None.</p></li></ul>
<p>–</p>
<ul><li><p>'''</p></li>
<li><p>self = cls()</p></li>
<li><p>for key in iterable:</p></li>
<li><p>self[key] = value</p></li>
<li><p>return self</p></li></ul>
<p>–</p>
<ul><li><p>def __eq__(self, other):</p></li>
<li><p>'''od.__eq__(y) <==> od==y.  Comparison to another OD is order-sensitive</p></li>
<li><p>while comparison to a regular mapping is order-insensitive.</p></li></ul>
<p>–</p>
<ul><li><p>'''</p></li>
<li><p>if isinstance(other, OrderedDict):</p></li>
<li><p>return len(self)==len(other) and \</p></li>
<li><p>all(p==q for p, q in zip(self.items(), other.items()))</p></li>
<li><p>return dict.__eq__(self, other)</p></li></ul>
<p>– -# update_wrapper() and wraps() are tools to help write -# wrapper functions that can handle naive introspection – -WRAPPER_ASSIGNMENTS = ('__module__', ‘__name__’, ‘__doc__’) -WRAPPER_UPDATES = ('__dict__',) -def update_wrapper(wrapper,</p>
<ul><li><p>wrapped,</p></li>
<li><p>assigned = WRAPPER_ASSIGNMENTS,</p></li>
<li><p>updated = WRAPPER_UPDATES):</p></li>
<li><p>"""Update a wrapper function to look like the wrapped function</p></li></ul>
<p>–</p>
<ul><li><p>wrapper is the function to be updated</p></li>
<li><p>wrapped is the original function</p></li>
<li><p>assigned is a tuple naming the attributes assigned directly</p></li>
<li><p>from the wrapped function to the wrapper function (defaults to</p></li>
<li><p>functools.WRAPPER_ASSIGNMENTS)</p></li>
<li><p>updated is a tuple naming the attributes of the wrapper that</p></li>
<li><p>are updated with the corresponding attribute from the wrapped</p></li>
<li><p>function (defaults to functools.WRAPPER_UPDATES)</p></li>
<li><p>"""</p></li>
<li><p>wrapper.__wrapped__ = wrapped</p></li>
<li><p>for attr in assigned:</p></li>
<li><p>try:</p></li>
<li><p>value = getattr(wrapped, attr)</p></li>
<li><p>except AttributeError:</p></li>
<li><p>pass</p></li>
<li><p>else:</p></li>
<li><p>setattr(wrapper, attr, value)</p></li>
<li><p>for attr in updated:</p></li>
<li><p>getattr(wrapper, attr).update(getattr(wrapped, attr, {}))</p></li>
<li><p># Return the wrapper so this can be used as a decorator via partial()</p></li>
<li><p>return wrapper</p></li></ul>
<p>– -def wraps(wrapped,</p>
<ul><li><p>assigned = WRAPPER_ASSIGNMENTS,</p></li>
<li><p>updated = WRAPPER_UPDATES):</p></li>
<li><p>"""Decorator factory to apply update_wrapper() to a wrapper function</p></li></ul>
<p>–</p>
<ul><li><p>Returns a decorator that invokes update_wrapper() with the decorated</p></li>
<li><p>function as the wrapper argument and the arguments to wraps() as the</p></li>
<li><p>remaining arguments. Default arguments are as for update_wrapper().</p></li>
<li><p>This is a convenience function to simplify applying partial() to</p></li>
<li><p>update_wrapper().</p></li>
<li><p>"""</p></li>
<li><p>return partial(update_wrapper, wrapped=wrapped,</p></li>
<li><p>assigned=assigned, updated=updated)</p></li></ul>
<p>– -def total_ordering(cls):</p>
<ul><li><p>"""Class decorator that fills in missing ordering methods"""</p></li>
<li><p>convert = {</p></li>
<li><p>‘__lt__’: [('__gt__', lambda self, other: not (self < other or self == other)),</p></li>
<li><p>('__le__', lambda self, other: self < other or self == other),</p></li>
<li><p>('__ge__', lambda self, other: not self < other)],</p></li>
<li><p>‘__le__’: [('__ge__', lambda self, other: not self <= other or self == other),</p></li>
<li><p>('__lt__', lambda self, other: self <= other and not self == other),</p></li>
<li><p>('__gt__', lambda self, other: not self <= other)],</p></li>
<li><p>‘__gt__’: [('__lt__', lambda self, other: not (self > other or self == other)),</p></li>
<li><p>('__ge__', lambda self, other: self > other or self == other),</p></li>
<li><p>('__le__', lambda self, other: not self > other)],</p></li>
<li><p>‘__ge__’: [('__le__', lambda self, other: (not self >= other) or self == other),</p></li>
<li><p>('__gt__', lambda self, other: self >= other and not self == other),</p></li>
<li><p>('__lt__', lambda self, other: not self >= other)]</p></li>
<li><p>}</p></li>
<li><p>roots = set(dir(cls)) & set(convert)</p></li>
<li><p>if not roots:</p></li>
<li><p>raise ValueError('must define at least one ordering operation: < ><= >=')</p></li>
<li><p>root = max(roots)       # prefer <em>_lt</em>_ to <em>_le</em>_ to <em>_gt</em>_ to <em>_ge</em>_</p></li>
<li><p>for opname, opfunc in convert[root]:</p></li>
<li><p>if opname not in roots:</p></li>
<li><p>opfunc.__name__ = opname</p></li>
<li><p>opfunc.__doc__ = getattr(int, opname).__doc__</p></li>
<li><p>setattr(cls, opname, opfunc)</p></li>
<li><p>return cls</p></li></ul>
<p>– -def cmp_to_key(mycmp):</p>
<ul><li><p>"""Convert a cmp= function into a key= function"""</p></li>
<li><p>class K(object):</p></li>
<li><p><em>_slots</em>_ = ['obj']</p></li>
<li><p>def __init__(self, obj):</p></li>
<li><p>self.obj = obj</p></li>
<li><p>def __lt__(self, other):</p></li>
<li><p>return mycmp(self.obj, other.obj) < 0</p></li>
<li><p>def __gt__(self, other):</p></li>
<li><p>return mycmp(self.obj, other.obj) > 0</p></li>
<li><p>def __eq__(self, other):</p></li>
<li><p>return mycmp(self.obj, other.obj) == 0</p></li>
<li><p>def __le__(self, other):</p></li>
<li><p>return mycmp(self.obj, other.obj) <= 0</p></li>
<li><p>def __ge__(self, other):</p></li>
<li><p>return mycmp(self.obj, other.obj) >= 0</p></li>
<li><p>def __ne__(self, other):</p></li>
<li><p>return mycmp(self.obj, other.obj) != 0</p></li>
<li><p><em>_hash</em>_ = None</p></li>
<li><p>return K</p></li></ul>
<p>– -_CacheInfo = namedtuple("CacheInfo", “hits misses maxsize currsize”) – -def lru_cache(maxsize=100):</p>
<ul><li><p>"""Least-recently-used cache decorator.</p></li></ul>
<p>–</p>
<ul><li><p>If <strong>maxsize</strong> is set to None, the LRU features are disabled and the cache</p></li>
<li><p>can grow without bound.</p></li></ul>
<p>–</p>
<ul><li><p>Arguments to the cached function must be hashable.</p></li></ul>
<p>–</p>
<ul><li><p>View the cache statistics named tuple (hits, misses, maxsize, currsize) with</p></li>
<li><p>f.cache_info().  Clear the cache and statistics with f.cache_clear().</p></li>
<li><p>Access the underlying function with f.__wrapped__.</p></li></ul>
<p>–</p>
<ul><li><p>See:  <a href="http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used">http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used</a></p></li></ul>
<p>–</p>
<ul><li><p>"""</p></li>
<li><p># Users should only access the lru_cache through its public API:</p></li>
<li><p>#       cache_info, cache_clear, and f.__wrapped__</p></li>
<li><p># The internals of the lru_cache are encapsulated for thread safety and</p></li>
<li><p># to allow the implementation to change (including a possible C version).</p></li></ul>
<p>–</p>
<ul><li><p>def decorating_function(user_function,</p></li>
<li><p>tuple=tuple, sorted=sorted, len=len, KeyError=KeyError):</p></li></ul>
<p>–</p>
<ul><li><p>hits, misses = [0], [0]</p></li>
<li><p>kwd_mark = (object(),)          # separates positional and keyword args</p></li>
<li><p>lock = Lock()                   # needed because OrderedDict isn't threadsafe</p></li></ul>
<p>–</p>
<ul><li><p>if maxsize is None:</p></li>
<li><p>cache = dict()              # simple cache without ordering or size limit</p></li></ul>
<p>–</p>
<ul><li><p>@wraps(user_function)</p></li>
<li><p>def wrapper(*args, **kwds):</p></li>
<li><p>key = args</p></li>
<li><p>if kwds:</p></li>
<li><p>key += kwd_mark + tuple(sorted(kwds.items()))</p></li>
<li><p>try:</p></li>
<li><p>result = cache[key]</p></li>
<li><p>hits[0] += 1</p></li>
<li><p>return result</p></li>
<li><p>except KeyError:</p></li>
<li><p>pass</p></li>
<li><p>result = user_function(*args, **kwds)</p></li>
<li><p>cache[key] = result</p></li>
<li><p>misses[0] += 1</p></li>
<li><p>return result</p></li>
<li><p>else:</p></li>
<li><p>cache = OrderedDict()           # ordered least recent to most recent</p></li>
<li><p>cache_popitem = cache.popitem</p></li>
<li><p>cache_renew = cache.move_to_end</p></li></ul>
<p>–</p>
<ul><li><p>@wraps(user_function)</p></li>
<li><p>def wrapper(*args, **kwds):</p></li>
<li><p>key = args</p></li>
<li><p>if kwds:</p></li>
<li><p>key += kwd_mark + tuple(sorted(kwds.items()))</p></li>
<li><p>with lock:</p></li>
<li><p>try:</p></li>
<li><p>result = cache[key]</p></li>
<li><p>cache_renew(key)    # record recent use of this key</p></li>
<li><p>hits[0] += 1</p></li>
<li><p>return result</p></li>
<li><p>except KeyError:</p></li>
<li><p>pass</p></li>
<li><p>result = user_function(*args, **kwds)</p></li>
<li><p>with lock:</p></li>
<li><p>cache[key] = result     # record recent use of this key</p></li>
<li><p>misses[0] += 1</p></li>
<li><p>if len(cache) > maxsize:</p></li>
<li><p>cache_popitem(0)    # purge least recently used cache entry</p></li>
<li><p>return result</p></li></ul>
<p>–</p>
<ul><li><p>def cache_info():</p></li>
<li><p>"""Report cache statistics"""</p></li>
<li><p>with lock:</p></li>
<li><p>return _CacheInfo(hits[0], misses[0], maxsize, len(cache))</p></li></ul>
<p>–</p>
<ul><li><p>def cache_clear():</p></li>
<li><p>"""Clear the cache and cache statistics"""</p></li>
<li><p>with lock:</p></li>
<li><p>cache.clear()</p></li>
<li><p>hits[0] = misses[0] = 0</p></li></ul>
<p>–</p>
<ul><li><p>wrapper.cache_info = cache_info</p></li>
<li><p>wrapper.cache_clear = cache_clear</p></li>
<li><p>return wrapper</p></li></ul>
<p>–</p>
<ul><li><p>return decorating_function</p></li></ul>
<p>diff -r 2d7b93e59428f2dc6d4cde5030cacc4b113c6ea4 -r 236cd5cc2b6a0b7b96ebe64a9a223f14bc86728e yt/units/unit_object.py --- a/yt/units/unit_object.py +++ b/yt/units/unit_object.py @@ -393,7 +393,7 @@</p>
<pre>@property
def is_dimensionless(self):</pre>
<ul><li><p>return self.dimensions == sympy_one</p></li></ul>
<p>+        return self.dimensions is sympy_one</p>
<pre>@property
def is_code_unit(self):</pre>
<p>diff -r 2d7b93e59428f2dc6d4cde5030cacc4b113c6ea4 -r 236cd5cc2b6a0b7b96ebe64a9a223f14bc86728e yt/units/unit_registry.py --- a/yt/units/unit_registry.py +++ b/yt/units/unit_registry.py @@ -106,9 +106,9 @@</p>
<pre>                "in this registry." % symbol)

        if hasattr(base_value, "in_base"):</pre>
<ul><li><p>base_value = float(base_value.in_base().value)</p></li></ul>
<p>+            base_value = base_value.in_base().value</p>
<ul><li><p>self.lut[symbol] = (base_value, ) + self.lut[symbol][1:]</p></li></ul>
<p>+        self.lut[symbol] = (float(base_value), ) + self.lut[symbol][1:]</p>
<pre>def keys(self):
    """</pre>
<p>diff -r 2d7b93e59428f2dc6d4cde5030cacc4b113c6ea4 -r 236cd5cc2b6a0b7b96ebe64a9a223f14bc86728e yt/units/yt_array.py --- a/yt/units/yt_array.py +++ b/yt/units/yt_array.py @@ -36,6 +36,7 @@</p>
<pre>YTUnitOperationError, YTUnitConversionError, \
YTUfuncUnitError, YTIterableUnitCoercionError, \
YTInvalidUnitEquivalence, YTEquivalentDimsError</pre>
<p>+from yt.utilities.lru_cache import lru_cache</p>
<pre>from numbers import Number as numeric_type
from yt.utilities.on_demand_imports import _astropy
from sympy import Rational</pre>
<p>@@ -64,24 +65,30 @@</p>
<pre>            return type(args[0])(ret, units)
    return wrapped
</pre>
<p>+@lru_cache(maxsize=128, typed=False)</p>
<pre>def sqrt_unit(unit):
    return unit**0.5
</pre>
<p>+@lru_cache(maxsize=128, typed=False)</p>
<pre>def multiply_units(unit1, unit2):
    return unit1 * unit2

def preserve_units(unit1, unit2):
    return unit1
</pre>
<p>+@lru_cache(maxsize=128, typed=False)</p>
<pre>def power_unit(unit, power):
    return unit**power
</pre>
<p>+@lru_cache(maxsize=128, typed=False)</p>
<pre>def square_unit(unit):
    return unit*unit
</pre>
<p>+@lru_cache(maxsize=128, typed=False)</p>
<pre>def divide_units(unit1, unit2):
    return unit1/unit2
</pre>
<p>+@lru_cache(maxsize=128, typed=False)</p>
<pre>def reciprocal_unit(unit):
    return unit**-1
</pre>
<p>@@ -1191,7 +1198,7 @@</p>
<pre>    raise YTUnitOperationError(context[0], unit1, unit2)
else:
    raise YTUfuncUnitError(context[0], unit1, unit2)</pre>
<ul><li><p>unit = self._ufunc_registry[context[0]](unit1, unit2)</p></li></ul>
<p>+            unit = unit_operator(unit1, unit2)</p>
<pre>if unit_operator in (multiply_units, divide_units):
    if unit.is_dimensionless and unit.base_value != 1.0:
        if not unit1.is_dimensionless:</pre>
<p>diff -r 2d7b93e59428f2dc6d4cde5030cacc4b113c6ea4 -r 236cd5cc2b6a0b7b96ebe64a9a223f14bc86728e yt/utilities/lru_cache.py --- /dev/null +++ b/yt/utilities/lru_cache.py @@ -0,0 +1,192 @@ +""" + +lru_cache compatible with py2.6->py3.2 copied directly from +<a href="http://code.activestate.com/">http://code.activestate.com/</a> +recipes/578078-py26-and-py30-backport-of-python-33s-lru-cache/ + +adapted from sympy by Nathan Goldbaum + +""" + +#----------------------------------------------------------------------------- +# Copyright © 2016, yt Development Team. +# +# Distributed under the terms of the Modified BSD License. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- + +import sys + +from collections import namedtuple +from functools import update_wrapper +from threading import RLock + +_CacheInfo = namedtuple("CacheInfo", ["hits", “misses”, “maxsize”, "currsize"]) + +class <em>HashedSeq(list): +    <em>_slots</em></em> = ‘hashvalue’ + +    def __init__(self, tup, hash=hash): +        self[:] = tup +        self.hashvalue = hash(tup) + +    def __hash__(self): +        return self.hashvalue + +def _make_key(args, kwds, typed, +             kwd_mark = (object(),), +             fasttypes = set((int, str, frozenset, type(None))), +             sorted=sorted, tuple=tuple, type=type, len=len): +    ‘Make a cache key from optionally typed positional and keyword arguments’ +    key = args +    if kwds: +        sorted_items = sorted(kwds.items()) +        key += kwd_mark +        for item in sorted_items: +            key += item +    if typed: +        key += tuple(type(v) for v in args) +        if kwds: +            key += tuple(type(v) for k, v in sorted_items) +    elif len(key) == 1 and type(key[0]) in fasttypes: +        return key[0] +    return _HashedSeq(key) + +def lru_cache(maxsize=100, typed=False): +    """Least-recently-used cache decorator. +    If <strong>maxsize</strong> is set to None, the LRU features are disabled and the cache +    can grow without bound. +    If <strong>typed</strong> is True, arguments of different types will be cached separately. +    For example, f(3.0) and f(3) will be treated as distinct calls with +    distinct results. +    Arguments to the cached function must be hashable. +    View the cache statistics named tuple (hits, misses, maxsize, currsize) with +    f.cache_info().  Clear the cache and statistics with f.cache_clear(). +    Access the underlying function with f.__wrapped__. +    See:  <a href="http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used">http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used</a> +    """ + +    # Users should only access the lru_cache through its public API: +    #       cache_info, cache_clear, and f.__wrapped__ +    # The internals of the lru_cache are encapsulated for thread safety and +    # to allow the implementation to change (including a possible C version). + +    def decorating_function(user_function): + +        cache = dict() +        stats = [0, 0]                  # make statistics updateable non-locally +        HITS, MISSES = 0, 1             # names for the stats fields +        make_key = <em>make_key +        cache_get = cache.get           # bound method to lookup key or return None +        <em>len = len                      # localize the global len() function +        lock = RLock()                  # because linkedlist updates aren't threadsafe +        root = []                       # root of the circular doubly linked list +        root[:] = [root, root, None, None]      # initialize by pointing to self +        nonlocal_root = [root]                  # make updateable non-locally +        PREV, NEXT, KEY, RESULT = 0, 1, 2, 3    # names for the link fields + +        if maxsize == 0: + +            def wrapper(*args, **kwds): +                # no caching, just do a statistics update after a successful call +                result = user_function(*args, **kwds) +                stats[MISSES] += 1 +                return result + +        elif maxsize is None: + +            def wrapper(*args, **kwds): +                # simple caching without ordering or size limit +                key = make_key(args, kwds, typed) +                result = cache_get(key, root)   # root used here as a unique not-found sentinel +                if result is not root: +                    stats[HITS] += 1 +                    return result +                result = user_function(*args, **kwds) +                cache[key] = result +                stats[MISSES] += 1 +                return result + +        else: + +            def wrapper(*args, **kwds): +                # size limited caching that tracks accesses by recency +                try: +                    key = make_key(args, kwds, typed) if kwds or typed else args +                except TypeError: +                    stats[MISSES] += 1 +                    return user_function(*args, **kwds) +                with lock: +                    link = cache_get(key) +                    if link is not None: +                        # record recent use of the key by moving it to the front of the list +                        root, = nonlocal_root +                        link_prev, link_next, key, result = link +                        link_prev[NEXT] = link_next +                        link_next[PREV] = link_prev +                        last = root[PREV] +                        last[NEXT] = root[PREV] = link +                        link[PREV] = last +                        link[NEXT] = root +                        stats[HITS] += 1 +                        return result +                result = user_function(*args, **kwds) +                with lock: +                    root, = nonlocal_root +                    if key in cache: +                        # getting here means that this same key was added to the +                        # cache while the lock was released.  since the link +                        # update is already done, we need only return the +                        # computed result and update the count of misses. +                        pass +                    elif _len(cache) >= maxsize: +                        # use the old root to store the new key and result +                        oldroot = root +                        oldroot[KEY] = key +                        oldroot[RESULT] = result +                        # empty the oldest link and make it the new root +                        root = nonlocal_root[0] = oldroot[NEXT] +                        oldkey = root[KEY] +                        oldvalue = root[RESULT] +                        root[KEY] = root[RESULT] = None +                        # now update the cache dictionary for the new links +                        del cache[oldkey] +                        cache[key] = oldroot +                    else: +                        # put result in a new link at the front of the list +                        last = root[PREV] +                        link = [last, root, key, result] +                        last[NEXT] = root[PREV] = cache[key] = link +                    stats[MISSES] += 1 +                return result + +        def cache_info(): +            """Report cache statistics""" +            with lock: +                return _CacheInfo(stats[HITS], stats[MISSES], maxsize, len(cache)) + +        def cache_clear(): +            """Clear the cache and cache statistics""" +            with lock: +                cache.clear() +                root = nonlocal_root[0] +                root[:] = [root, root, None, None] +                stats[:] = [0, 0] + +        wrapper.__wrapped</em></em> = user_function +        wrapper.cache_info = cache_info +        wrapper.cache_clear = cache_clear +        return update_wrapper(wrapper, user_function) + +    return decorating_function +### End of backported lru_cache + +if sys.version_info[:2] >= (3, 3): +    # 3.2 has an lru_cache with an incompatible API +    from functools import lru_cache + +try: +    from fastcache import clru_cache as lru_cache +except ImportError: +    pass</p>
<p>Repository URL: <a href="https://bitbucket.org/yt_analysis/yt/">https://bitbucket.org/yt_analysis/yt/</a></p>
<p>—</p>
<p>This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.</p>

<img src="http://link.bitbucket.org/wf/open?upn=ll4ctv0L-2ByeRZFC1LslHcg6aJmnQ70VruLbmeLQr27B7XThACs6ZY9e7RoRDISCuoGICuKfd6OjDoj432u9oM2ngSe5tnewqVht2M3FvcKA-2BIyPfG7x8rMBbYUgDQ17YTtAsFVsJesyZ-2F-2BiHHzdj-2FNvsKtjkm6w1VKweRQ-2BjO2p9KzGdsDxpuaiLA7cGtwHFx7KHnvdwP9p3oLoWLBrXvQX-2BFwUrYCdJxLYlOSWON4U-3D" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;"/>
</body></html>