diff options
Diffstat (limited to 'silx/utils/weakref.py')
-rw-r--r-- | silx/utils/weakref.py | 361 |
1 files changed, 0 insertions, 361 deletions
diff --git a/silx/utils/weakref.py b/silx/utils/weakref.py deleted file mode 100644 index 06646e8..0000000 --- a/silx/utils/weakref.py +++ /dev/null @@ -1,361 +0,0 @@ -# coding: utf-8 -# /*########################################################################## -# -# Copyright (c) 2016-2018 European Synchrotron Radiation Facility -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# -# ###########################################################################*/ -"""Weakref utils for compatibility between Python 2 and Python 3 or for -extended features. -""" -from __future__ import absolute_import - -__authors__ = ["V. Valls"] -__license__ = "MIT" -__date__ = "15/09/2016" - - -import weakref -import types -import inspect - - -def ref(object, callback=None): - """Returns a weak reference to object. The original object can be retrieved - by calling the reference object if the referent is still alive. If the - referent is no longer alive, calling the reference object will cause None - to be returned. - - The signature is the same as the standard `weakref` library, but it returns - `WeakMethod` if the object is a bound method. - - :param object: An object - :param func callback: If provided, and the returned weakref object is - still alive, the callback will be called when the object is about to - be finalized. The weak reference object will be passed as the only - parameter to the callback. Then the referent will no longer be - available. - :return: A weak reference to the object - """ - if inspect.ismethod(object): - return WeakMethod(object, callback) - else: - return weakref.ref(object, callback) - - -def proxy(object, callback=None): - """Return a proxy to object which uses a weak reference. This supports use - of the proxy in most contexts instead of requiring the explicit - dereferencing used with weak reference objects. - - The signature is the same as the standard `weakref` library, but it returns - `WeakMethodProxy` if the object is a bound method. - - :param object: An object - :param func callback: If provided, and the returned weakref object is - still alive, the callback will be called when the object is about to - be finalized. The weak reference object will be passed as the only - parameter to the callback. Then the referent will no longer be - available. - :return: A proxy to a weak reference of the object - """ - if inspect.ismethod(object): - return WeakMethodProxy(object, callback) - else: - return weakref.proxy(object, callback) - - -class WeakMethod(object): - """Wraps a callable object like a function or a bound method. - Feature callback when the object is about to be finalized. - Provids the same interface as a normal weak reference. - """ - - def __init__(self, function, callback=None): - """ - Constructor - :param function: Function/method to be called - :param callback: If callback is provided and not None, - and the returned weakref object is still alive, the - callback will be called when the object is about to - be finalized; the weak reference object will be passed - as the only parameter to the callback; the referent will - no longer be available - """ - self.__callback = callback - - if inspect.ismethod(function): - # it is a bound method - self.__obj = weakref.ref(function.__self__, self.__call_callback) - self.__method = weakref.ref(function.__func__, self.__call_callback) - else: - self.__obj = None - self.__method = weakref.ref(function, self.__call_callback) - - def __call_callback(self, ref): - """Called when the object is about to be finalized""" - if not self.is_alive(): - return - self.__obj = None - self.__method = None - if self.__callback is not None: - self.__callback(self) - - def __call__(self): - """Return a callable function or None if the WeakMethod is dead.""" - if self.__obj is not None: - method = self.__method() - obj = self.__obj() - if method is None or obj is None: - return None - return types.MethodType(method, obj) - elif self.__method is not None: - return self.__method() - else: - return None - - def is_alive(self): - """True if the WeakMethod is still alive""" - return self.__method is not None - - def __eq__(self, other): - """Check it another obect is equal to this. - - :param object other: Object to compare with - """ - if isinstance(other, WeakMethod): - if not self.is_alive(): - return False - return self.__obj == other.__obj and self.__method == other.__method - return False - - def __ne__(self, other): - """Check it another obect is not equal to this. - - :param object other: Object to compare with - """ - if isinstance(other, WeakMethod): - if not self.is_alive(): - return False - return self.__obj != other.__obj or self.__method != other.__method - return True - - def __hash__(self): - """Returns the hash for the object.""" - return self.__obj.__hash__() ^ self.__method.__hash__() - - -class WeakMethodProxy(WeakMethod): - """Wraps a callable object like a function or a bound method - with a weakref proxy. - """ - def __call__(self, *args, **kwargs): - """Dereference the method and call it if the method is still alive. - Else raises an ReferenceError. - - :raises: ReferenceError, if the method is not alive - """ - fn = super(WeakMethodProxy, self).__call__() - if fn is None: - raise ReferenceError("weakly-referenced object no longer exists") - return fn(*args, **kwargs) - - -class WeakList(list): - """Manage a list of weaked references. - When an object is dead, the list is flaged as invalid. - If expected the list is cleaned up to remove dead objects. - """ - - def __init__(self, enumerator=()): - """Create a WeakList - - :param iterator enumerator: A list of object to initialize the - list - """ - list.__init__(self) - self.__list = [] - self.__is_valid = True - for obj in enumerator: - self.append(obj) - - def __invalidate(self, ref): - """Flag the list as invalidated. The list contains dead references.""" - self.__is_valid = False - - def __create_ref(self, obj): - """Create a weakref from an object. It uses the `ref` module function. - """ - return ref(obj, self.__invalidate) - - def __clean(self): - """Clean the list from dead references""" - if self.__is_valid: - return - self.__list = [ref for ref in self.__list if ref() is not None] - self.__is_valid = True - - def __iter__(self): - """Iterate over objects of the list""" - for ref in self.__list: - obj = ref() - if obj is not None: - yield obj - - def __len__(self): - """Count item on the list""" - self.__clean() - return len(self.__list) - - def __getitem__(self, key): - """Returns the object at the requested index - - :param key: Indexes to get - :type key: int or slice - """ - self.__clean() - data = self.__list[key] - if isinstance(data, list): - result = [ref() for ref in data] - else: - result = data() - return result - - def __setitem__(self, key, obj): - """Set an item at an index - - :param key: Indexes to set - :type key: int or slice - """ - self.__clean() - if isinstance(key, slice): - objs = [self.__create_ref(o) for o in obj] - self.__list[key] = objs - else: - obj_ref = self.__create_ref(obj) - self.__list[key] = obj_ref - - def __delitem__(self, key): - """Delete an Indexes item of this list - - :param key: Index to delete - :type key: int or slice - """ - self.__clean() - del self.__list[key] - - def __delslice__(self, i, j): - """Looks to be used in Python 2.7""" - self.__delitem__(slice(i, j, None)) - - def __setslice__(self, i, j, sequence): - """Looks to be used in Python 2.7""" - self.__setitem__(slice(i, j, None), sequence) - - def __getslice__(self, i, j): - """Looks to be used in Python 2.7""" - return self.__getitem__(slice(i, j, None)) - - def __reversed__(self): - """Returns a copy of the reverted list""" - reversed_list = reversed(list(self)) - return WeakList(reversed_list) - - def __contains__(self, obj): - """Returns true if the object is in the list""" - ref = self.__create_ref(obj) - return ref in self.__list - - def __add__(self, other): - """Returns a WeakList containing this list an the other""" - l = WeakList(self) - l.extend(other) - return l - - def __iadd__(self, other): - """Add objects to this list inplace""" - self.extend(other) - return self - - def __mul__(self, n): - """Returns a WeakList containing n-duplication object of this list""" - return WeakList(list(self) * n) - - def __imul__(self, n): - """N-duplication of the objects to this list inplace""" - self.__list *= n - return self - - def append(self, obj): - """Add an object at the end of the list""" - ref = self.__create_ref(obj) - self.__list.append(ref) - - def count(self, obj): - """Returns the number of occurencies of an object""" - ref = self.__create_ref(obj) - return self.__list.count(ref) - - def extend(self, other): - """Append the list with all objects from another list""" - for obj in other: - self.append(obj) - - def index(self, obj): - """Returns the index of an object""" - ref = self.__create_ref(obj) - return self.__list.index(ref) - - def insert(self, index, obj): - """Insert an object at the requested index""" - ref = self.__create_ref(obj) - self.__list.insert(index, ref) - - def pop(self, index=-1): - """Remove and return an object at the requested index""" - self.__clean() - obj = self.__list.pop(index)() - return obj - - def remove(self, obj): - """Remove an object from the list""" - ref = self.__create_ref(obj) - self.__list.remove(ref) - - def reverse(self): - """Reverse the list inplace""" - self.__list.reverse() - - def sort(self, key=None, reverse=False): - """Sort the list inplace. - Not very efficient. - """ - sorted_list = list(self) - sorted_list.sort(key=key, reverse=reverse) - self.__list = [] - self.extend(sorted_list) - - def __str__(self): - unref_list = list(self) - return "WeakList(%s)" % str(unref_list) - - def __repr__(self): - unref_list = list(self) - return "WeakList(%s)" % repr(unref_list) |