def test_weakref_subclassing(self): import _weakref, gc class A(object): pass class Ref(_weakref.ref): def __init__(self, ob, callback=None, **other): self.__dict__.update(other) def callable(ref): b.a = 42 a = A() b = A() b.a = 1 w = Ref(a, callable, x=1, y=2) assert w.x == 1 assert w.y == 2 assert a.__weakref__ is w assert b.__weakref__ is None w1 = _weakref.ref(a) w2 = _weakref.ref(a, callable) assert a.__weakref__ is w1 del a gc.collect() assert w1() is None assert w() is None assert w2() is None assert b.a == 42
def weakref_data(data, destroy_cb = None): if type(data) in (str, int, long, types.NoneType, types.FunctionType): # Naive optimization for common immutable cases. return data elif type(data) == types.MethodType: cb = WeakCallback(data) if destroy_cb: cb.weakref_destroyed_cb = destroy_cb cb.ignore_caller_args = True return cb elif type(data) in (list, tuple): d = [] for item in data: d.append(weakref_data(item, destroy_cb)) if type(data) == tuple: d = tuple(d) return d elif type(data) == dict: d = {} for key, val in data.items(): d[weakref_data(key)] = weakref_data(val, destroy_cb) return d else: try: if destroy_cb: return _weakref.ref(data, destroy_cb) return _weakref.ref(data) except TypeError: pass return data
def test_weakref_equality(self): import _weakref, gc class A(object): def __eq__(self, other): return True def __ne__(self, other): return False a1 = A() a2 = A() ref1 = _weakref.ref(a1) ref2 = _weakref.ref(a2) assert ref1 == ref2 assert not (ref1 != ref2) assert not (ref1 == []) assert ref1 != [] del a1 gc.collect() assert not ref1 == ref2 assert ref1 != ref2 assert not (ref1 == []) assert ref1 != [] del a2 gc.collect() assert not ref1 == ref2 assert ref1 != ref2 assert not (ref1 == []) assert ref1 != []
def setdefault(self, key, default): try: ref = self.data[key] except KeyError: def remove(o, data=self.data, key=key): del data[key] ref = ref(default, remove) self.data[key] = ref return default else: return ref()
def test_weakref_reusing(self): import _weakref, gc class A(object): pass a = A() ref1 = _weakref.ref(a) ref2 = _weakref.ref(a) assert ref1 is ref2 class wref(_weakref.ref): pass wref1 = wref(a) assert isinstance(wref1, wref)
def Startup(self, slimItem): sm.RegisterNotify(self) self.ball = _weakref.ref(sm.GetService('michelle').GetBall(slimItem.itemID)) self.slimItem = _weakref.ref(slimItem) self.id = slimItem.itemID self.itemID = slimItem.itemID self.updatedamage = slimItem.categoryID != const.categoryAsteroid and slimItem.groupID != const.groupHarvestableCloud and slimItem.groupID != const.groupOrbitalTarget self.AddUIObjects(slimItem, self.itemID) iconPar = self.sr.iconPar barAndImageCont = self.barAndImageCont barAndImageCont.isDragObject = True barAndImageCont.GetDragData = self.GetTargetDragData barAndImageCont.OnMouseDown = self.OnTargetMouseDown barAndImageCont.OnClick = self.OnTargetClick barAndImageCont.GetMenu = self.GetTargetMenu barAndImageCont.OnMouseEnter = self.OnTargetMouseEnter barAndImageCont.OnMouseExit = self.OnTargetMouseExit self.sr.activeTarget = uicls.ActiveTargetOnBracket(parent=iconPar, itemID=self.itemID) self.slimForFlag = slimItem self.SetStandingIcon() self.sr.hilite = uiprimitives.Sprite(name='hiliteSprite', parent=iconPar, left=-3, top=-3, width=100, height=100, texturePath='res:/UI/Texture/classes/Target/targetUnderlay.png', color=(1.0, 1.0, 1.0, 0.05)) self.sr.activeTarget.RotateArrows() labelClass = uicontrols.EveLabelSmall labelContainer = uicontrols.ContainerAutoSize(parent=self, name='labelContainer', align=uiconst.TOTOP) self.sr.label = labelClass(text=' ', parent=labelContainer, align=uiconst.TOTOP, state=uiconst.UI_DISABLED, maxLines=1) self.sr.label2 = labelClass(text=' ', parent=labelContainer, align=uiconst.TOTOP, state=uiconst.UI_DISABLED, maxLines=1) self.sr.shipLabel = labelClass(text=' ', parent=labelContainer, align=uiconst.TOTOP, state=uiconst.UI_DISABLED, maxLines=1) self.sr.distanceLabel = labelClass(text=' ', parent=labelContainer, align=uiconst.TOTOP, state=uiconst.UI_DISABLED, maxLines=1) self.SetTargetLabel() self.sr.assignedPar = uiprimitives.Container(name='assignedPar', align=uiconst.TOTOP, parent=self, height=32) self.sr.assigned = uiprimitives.Container(name='assigned', align=uiconst.CENTERTOP, parent=self.sr.assignedPar, height=32) self.sr.updateTimer = base.AutoTimer(random.randint(750, 1000), self.UpdateData) self.UpdateData() selected = sm.GetService('state').GetExclState(state.selected) self.Select(selected == slimItem.itemID) hilited = sm.GetService('state').GetExclState(state.mouseOver) self.Hilite(hilited == slimItem.itemID) activeTargetID = sm.GetService('target').GetActiveTargetID() self.ActiveTarget(activeTargetID == slimItem.itemID) drones = sm.GetService('michelle').GetDrones() for key in drones: droneState = drones[key] if droneState.targetID == self.id: self.drones[droneState.droneID] = droneState.typeID self.UpdateDrones() for moduleInfo in sm.GetService('godma').GetStateManager().GetActiveModulesOnTargetID(slimItem.itemID): if moduleInfo: moduleID = moduleInfo.itemID if moduleID and moduleID not in self.activeModules: self.AddWeapon(moduleInfo) self.activeModules[moduleID] = moduleInfo
def test_correct_weakrefcount_after_death(self): import _weakref, gc class A(object): pass a = A() ref1 = _weakref.ref(a) ref2 = _weakref.ref(a) assert _weakref.getweakrefcount(a) == 1 del ref1 gc.collect() assert _weakref.getweakrefcount(a) == 1 del ref2 gc.collect() assert _weakref.getweakrefcount(a) == 0
def test_hashing(self): import _weakref, gc class A(object): def __hash__(self): return 42 a = A() w = _weakref.ref(a) assert hash(a) == hash(w) del a gc.collect() assert hash(w) == 42 w = _weakref.ref(A()) gc.collect() raises(TypeError, hash, w)
def test_callback_cannot_ressurect(self): import _weakref, gc class A(object): pass a = A() alive = A() alive.a = 1 def callback(ref2): alive.a = ref1() ref1 = _weakref.ref(a, callback) ref2 = _weakref.ref(a, callback) del a gc.collect() assert alive.a is None
def test_eq(self): import _weakref class A(object): pass a = A() assert not(_weakref.ref(a) == a) assert _weakref.ref(a) != a class A(object): def __eq__(self, other): return True a = A() assert _weakref.ref(a) == a
def __init__(self, callback, *args, **kwargs): super(WeakCallback, self).__init__(callback, *args, **kwargs) if type(callback) == types.MethodType: # For methods self._instance = _weakref.ref(callback.im_self, self._weakref_destroyed) self._callback = callback.im_func.func_name else: self._instance = None # Don't weakref lambdas. if not hasattr(callback, 'func_name') or callback.func_name != '<lambda>': self._callback = _weakref.ref(callback, self._weakref_destroyed) self._args = weakref_data(args, self._weakref_destroyed) self._kwargs = weakref_data(kwargs, self._weakref_destroyed) self._weakref_destroyed_user_cb = None
def test_callback(self): import _weakref, gc class A(object): pass a1 = A() a2 = A() def callback(ref): a2.ref = ref() ref1 = _weakref.ref(a1, callback) ref2 = _weakref.ref(a1) assert _weakref.getweakrefcount(a1) == 2 del a1 gc.collect() assert ref1() is None assert a2.ref is None
def test_callback_order(self): import _weakref, gc class A(object): pass a1 = A() a2 = A() def callback1(ref): a2.x = 42 def callback2(ref): a2.x = 43 ref1 = _weakref.ref(a1, callback1) ref2 = _weakref.ref(a1, callback2) del a1 gc.collect() assert a2.x == 42
def discard_member(self,member,safemode=False): if not self._remember: if safemode: return else: raise GroupError("This group does not remember its members") self.__delete_member_by_ref(weakref.ref(member))
def _remove(item, selfref=ref(self)): self = selfref() if self is not None: if self._iterating: self._pending_removals.append(item) else: self.data.discard(item)
def __contains__(self, item): try: wr = ref(item) except TypeError: return False return wr in self.data
def keys(self): L = [] for ref in self.data.keys(): o = ref() if o is not None: L.append(o) return L
def _get_cached_value(self, prop, child, otherkey = None): if child: child = _weakref.ref(child) if (prop, child, otherkey) in self._values_cache: #print "CACHE HIT", self, prop, child, otherkey return self._values_cache[(prop, child, otherkey)]
def test_ne(self): import _weakref class X(object): pass ref1 = _weakref.ref(X()) assert ref1.__eq__(X()) is NotImplemented assert ref1.__ne__(X()) is NotImplemented
def remove(wr, selfref=ref(self)): self = selfref() if self is not None: try: del self.data[wr.key] except KeyError: pass
def has_key(self, key): try: wr = ref(key) except TypeError: return 0 return wr in self.data
def remove(wr, selfref=ref(self)): self = selfref() if self is not None: if self._iterating: self._pending_removals.append(wr.key) else: del self.data[wr.key]
def remove(k, selfref=ref(self)): self = selfref() if self is not None: if self._iterating: self._pending_removals.append(k) else: del self.data[k]
def test_runner(): import _weakref global called called = 0 a = IronPythonTest.Events() # wire up an event w/ a circular reference # back to the object, ensure the event # is delivered def foo(): global called called += 1 foo.abc = a a.InstanceTest += foo a.CallInstance() self.assertEqual(called, 1) ret_val = _weakref.ref(foo) #self.assertTrue(hasattr(ret_val, "abc")) #BUG keep_alive(foo) # ensure as long as the objects are still alive the event # handler remains alive import gc for i in xrange(10): gc.collect() a.CallInstance() self.assertEqual(called, 2) return ret_val
def copy(self): new = WeakValueDictionary() for key, ref in self.data.items(): o = ref() if o is not None: new[key] = o return new
def update(self, dict): d = self.data L = [] for key, value in dict.items(): L.append((ref(key, self._remove), value)) for key, r in L: d[key] = r
def __contains__(self, key): try: wr = ref(key) except TypeError: return 0 return wr in self.data
def items(self): L = [] for key, ref in self.data.items(): o = ref() if o is not None: L.append((key, o)) return L
def test_method_weakrefable(self): import _weakref, gc class A(object): def f(self): return 42 a = A() meth = A.f w_unbound = _weakref.ref(meth) assert w_unbound()(A()) == 42 meth = A().f w_bound = _weakref.ref(meth) assert w_bound()() == 42 del meth gc.collect() assert w_unbound() is None assert w_bound() is None
def symmetric_difference_update(self, other): if self._pending_removals: self._commit_removals() if self is other: self.data.clear() else: self.data.symmetric_difference_update(ref(item) for item in other)
def get(self, key, default=None): return self.data.get(ref(key), default)
def __eq__(self, other): if not isinstance(other, self.__class__): return NotImplemented return self.data == set(ref(item) for item in other)
def __delitem__(self, key): self._dirty_len = True del self.data[ref(key)]
def __isub__(self, other): if self is other: self.data.clear() else: self.data.difference_update(ref(item) for item in other) return self
def issubset(self, other): return self.data.issubset(ref(item) for item in other)
def __iand__(self, other): if self._pending_removals: self._commit_removals() self.data.intersection_update(ref(item) for item in other) return self
def __init__(self, weakcontainer): # Don't create cycles self.weakcontainer = ref(weakcontainer)
def discard(self, item): if self._pending_removals: self._commit_removals() self.data.discard(ref(item))
def remove(self, item): if self._pending_removals: self._commit_removals() self.data.remove(ref(item))
def pop(self, key, *args): self._dirty_len = True return self.data.pop(ref(key), *args)
def add(self, item): if self._pending_removals: self._commit_removals() self.data.add(ref(item, self._remove))
def __setattr__(self, name, val): if callable(val): ref = CallableWeakRef(val) else: ref = _weakref.ref(val) self.__dict__[name] = ref
def setdefault(self, key, default=None): return self.data.setdefault(ref(key, self._remove), default)
def __contains__(self, item): return ref(item) in self.data
def __ge__(self, other): return self.data >= set(ref(item) for item in other)
def __setitem__(self, key, value): self.data[key] = ref(value, self.__makeremove(key))
def update(self, dict): d = self.data for key, value in dict.items(): d[ref(key, self._remove)] = value
def throw(self, type=None, value=None, tb=None, aborted=False): """ This method should be called when the owner (creator) of the InProgress is finished because it raised an exception. Any callbacks connected to the :attr:`~kaa.InProgress.exception` signal will then be emitted with the arguments passed to this method. The parameters correspond to sys.exc_info(). If they are not specified then the current exception in sys.exc_info() will be used; this is analogous to a naked ``raise`` within an ``except`` block. :param type: the class of the exception :param value: the instance of the exception :param tb: the traceback object representing where the exception took place """ # This function must deal with a tricky problem. See: # http://mail.python.org/pipermail/python-dev/2005-September/056091.html # # Ideally, we want to store the traceback object so we can defer the # exception handling until some later time. The problem is that by # storing the traceback, we create some ridiculously deep circular # references. # # The way we deal with this is to pass along the traceback object to # any handler that can handle the exception immediately, and then # discard the traceback. A stringified formatted traceback is attached # to the exception in the formatted_traceback attribute. # # The above URL suggests a possible non-trivial workaround: create a # custom traceback object in C code that preserves the parts of the # stack frames needed for printing tracebacks, but discarding objects # that would create circular references. This might be a TODO. if type is None: type, value, tb = sys.exc_info() if value is None: raise ValueError( 'throw() with no parameters but there is no current exception' ) self._exception = type, value, tb self._unhandled_exception = True stack = traceback.extract_tb(tb) # Attach a stringified traceback to the exception object. Right now, # this is the best we can do for asynchronous handlers. trace = ''.join(traceback.format_exception(*self._exception)).strip() value.formatted_traceback = trace # Wake any threads waiting on us. We've initialized _exception with # the traceback object, so any threads that access the result property # between now and the end of this function will have an opportunity to # get the live traceback. self._finished_event_poke(set=True) if self._exception_signal.count() == 0: # There are no exception handlers, so we know we will end up # queuing the traceback in the exception signal. Set it to None # to prevent that. tb = None if self._exception_signal.emit_when_handled(type, value, tb) == False: # A handler has acknowledged handling this exception by returning # False. So we won't log it. self._unhandled_exception = None # If we were thrown an InProgressAborted, the likely reason is an InProgress # we were waiting on has been aborted. In this case, we emit the abort # signal and clear _unhandled_exception, provided we are abortable (which # by default is true as long as there are any callbacks connected to the # abort signal. Otherwise, do not clear _unhandled_exception so that it # gets logged. if isinstance(value, InProgressAborted) and self.abortable: if not aborted: self.signals['abort'].emit(value) self._unhandled_exception = None if self._unhandled_exception: # This exception was not handled synchronously, so we set up a # weakref object with a finalize callback to a function that # logs the exception. We could do this in __del__, except that # the gc refuses to collect objects with a destructor. The weakref # kludge lets us accomplish the same thing without actually using # __del__. # # If the exception is passed back via result property, then it is # considered handled, and it will not be logged. cb = Callable(InProgress._log_exception, trace, value, self._stack) self._unhandled_exception = _weakref.ref(self, cb) # Remove traceback from stored exception. If any waiting threads # haven't gotten it by now, it's too late. if not isinstance(value, AsyncExceptionBase): value = AsyncException(value, stack) if hasattr(value, 'with_traceback'): # Remove traceback attached to exception objects in Python 3. value = value.with_traceback(None) self._exception = value.__class__, value, None # cleanup self.disconnect_all() self._exception_signal.disconnect_all() self.signals['abort'].disconnect_all() # We return False here so that if we've received a thrown exception # from another InProgress we're waiting on, we essentially inherit # the exception from it and indicate to it that we'll handle it # from here on. (Otherwise the linked InProgress would figure # nobody handled it and would dump out an unhandled async exception.) return False
def pop(self, key, *args): return self.data.pop(ref(key), *args)
def __getitem__(self, key): return self.data[ref(key)]
def remove(o, selfref=ref(self), key=key): self = selfref() if self is not None: del self.data[key]
def __delitem__(self, key): for ref in self.data.iterkeys(): o = ref() if o == key: del self.data[ref] return
def remove(k, selfref=ref(self)): self = selfref() if self is not None: del self.data[k]
def update(self, dict): d = self.data for key, o in dict.items(): d[key] = ref(o, self.__makeremove(key))
def __delitem__(self, key): del self.data[ref(key)]
def difference_update(self, other): if self is other: self.data.clear() else: self.data.difference_update(ref(item) for item in other)
def __setitem__(self, key, value): self.data[ref(key, self._remove)] = value