def test_weakfuncref_method(): class Thing(object): def method(self): return 'existent!' def __priv_method(self): return 'existent!' @classmethod def clsmethod(clsself): return 'existent!' t = Thing() gcd_methref = make_weakfuncref_that_will_get_gcd() methref = weakfuncref.WeakFunctionRef(t.method) privmethref = weakfuncref.WeakFunctionRef(t._Thing__priv_method) clsmethref = weakfuncref.WeakFunctionRef(t.clsmethod) assert gcd_methref.function() is None assert privmethref.function()() == 'existent!' assert methref.function()() == 'existent!' assert clsmethref.function()() == 'existent!' print(gcd_methref) print(methref) t = None assert methref.function() is None assert privmethref.function() is None assert clsmethref.function()() == 'existent!'
def __init__(self, target, propNames, keyFunc, triggers): """Create a ``PropCache``. :arg target: Target :class:`.HasProperties` instance whose property values are to be cached. :arg propNames: Names of properties on the ``target`` to be cached :arg keyFunc: Function which will be called whenever a trigger property changes, to generate a suitable key to use for cached property values. :arg triggers: Sequence of ``(hasProps, propName)`` pairs, specifying which property changes should trigger caching of the ``target`` property values. """ self.__name = '{}_{}'.format(type(self).__name__, id(self)) self.__cache = {} self.__target = weakref.ref(target) self.__propNames = propNames self.__keyFunc = weakfuncref.WeakFunctionRef(keyFunc) self.__triggers = [(weakref.ref(tobj), tprop) for (tobj, tprop) in triggers] for tobj, tprop in triggers: tobj.addListener(tprop, self.__name, self.__doCache, immediate=True)
def addAttributeListener(self, name, listener, weak=True, immediate=False): """Adds an attribute listener for this ``PropertyValue``. The listener callback function must accept the following arguments: - ``context``: The context associated with this ``PropertyValue``. - ``attribute``: The name of the attribute that changed. - ``value``: The new attribute value. - ``name``: The name of this ``PropertyValue`` instance. :param name: A unique name for the listener. If a listener with the specified name already exists, it will be overwritten. :param listener: The callback function. :param weak: If ``True`` (the default), a weak reference to the callback function is used. :param immediate: If ``False`` (the default), the listener is called immediately; otherwise, it is called via the :attr:`queue`. """ log.debug('Adding attribute listener on {}.{} ({}): {}'.format( self._context().__class__.__name__, self._name, id(self), name)) if weak: listener = weakfuncref.WeakFunctionRef(listener) name = self.__saltListenerName(name) self._attributeListeners[name] = Listener(self, name, listener, True, immediate)
def test_weakfuncref_function(): def func(): pass non_gcd_func = weakfuncref.WeakFunctionRef(func) gcd_func = make_weakfuncref_that_will_get_gcd() assert gcd_func.function() is None assert non_gcd_func.function() is func
def __init__(self, name, callback, topic, runOnIdle): self.name = name # We use a WeakFunctionRef so we can refer to # both functions and class/instance methods self.__callback = weakfuncref.WeakFunctionRef(callback) self.topic = topic self.runOnIdle = runOnIdle self.enabled = True
def make_weakfuncref_method_that_will_get_gcd(): class Thing(object): def method(self): pass return weakfuncref.WeakFunctionRef(Thing.method)
def make_weakfuncref_that_will_get_gcd(): def thefunc(): pass return weakfuncref.WeakFunctionRef(thefunc)
def addListener(self, name, callback, overwrite=False, weak=True, immediate=False): """Adds a listener for this value. When the value changes, the listener callback function is called. The callback function must accept the following arguments: - ``value``: The property value - ``valid``: Whether the value is valid or invalid - ``context``: The context object passed to :meth:`__init__`. - ``name``: The name of this ``PropertyValue`` instance. Listener names ``prenotify`` and ``postnotify`` are reserved - if either of these are passed in for the listener name, a :exc`ValueError` is raised. :param str name: A unique name for this listener. If a listener with the name already exists, a :exc`RuntimeError` will be raised, or it will be overwritten, depending upon the value of the ``overwrite`` argument. :param callback: The callback function. :param overwrite: If ``True`` any previous listener with the same name will be overwritten. :param weak: If ``True`` (the default), a weak reference to the callback function is retained, meaning that it can be garbage-collected. If passing in a lambda or inner function, you will probably want to set ``weak`` to ``False``, in which case a strong reference will be used. :param immediate: If ``False`` (the default), this listener will be notified through the :class:`.CallQueue` - listeners for all ``PropertyValue`` instances are queued, and notified in turn. If ``True``, If ``True``, the ``CallQueue`` will not be used, and this listener will be notified as soon as this ``PropertyValue`` changes. """ if name in ('prenotify', 'postnotify'): raise ValueError('Reserved listener name used: {}. ' 'Use a different name.'.format(name)) log.debug('Adding listener on {}.{}: {}'.format( self._context().__class__.__name__, self._name, name)) fullName = self.__saltListenerName(name) prior = self._changeListeners.get(fullName, None) if weak: callback = weakfuncref.WeakFunctionRef(callback) if (prior is not None) and (not overwrite): raise RuntimeError('Listener {} already exists'.format(name)) elif prior is not None: prior.function = callback prior.immediate = immediate else: self._changeListeners[fullName] = Listener(self, fullName, callback, True, immediate)