def __init__(self, interval):
     """
     Set up the ticker
     """
     self.interval = interval
     self.subscriptions = {}
     # set up a twisted asynchronous repeat call
     self.task = ExtendedLoopingCall(self._callback)
    def __init__(self, interval):
        """
        Set up the ticker

        Args:
            interval (int): The stepping interval.

        """
        self.interval = interval
        self.subscriptions = {}
        self._is_ticking = False
        self._to_remove = []
        self._to_add = []
        # set up a twisted asynchronous repeat call
        self.task = ExtendedLoopingCall(self._callback)
Example #3
0
 def __init__(self, interval):
     """
     Set up the ticker
     """
     self.interval = interval
     self.subscriptions = {}
     # set up a twisted asynchronous repeat call
     self.task = ExtendedLoopingCall(self._callback)
Example #4
0
    def __init__(self, interval):
        """
        Set up the ticker

        Args:
            interval (int): The stepping interval.

        """
        self.interval = interval
        self.subscriptions = {}
        self._is_ticking = False
        self._to_remove = []
        self._to_add = []
        # set up a twisted asynchronous repeat call
        self.task = ExtendedLoopingCall(self._callback)
class Ticker(object):
    """
    Represents a repeatedly running task that calls
    hooks repeatedly. Overload `_callback` to change the
    way it operates.
    """
    @inlineCallbacks
    def _callback(self):
        """
        This will be called repeatedly every `self.interval` seconds.
        `self.subscriptions` contain tuples of (obj, args, kwargs) for
        each subscribing object.

        If overloading, this callback is expected to handle all
        subscriptions when it is triggered. It should not return
        anything and should not traceback on poorly designed hooks.
        The callback should ideally work under @inlineCallbacks so it
        can yield appropriately.

        The _hook_key, which is passed down through the handler via
        kwargs is used here to identify which hook method to call.

        """
        self._to_add = []
        self._to_remove = []
        self._is_ticking = True
        for store_key, (args, kwargs) in self.subscriptions.iteritems():
            callback = yield kwargs.pop("_callback", "at_tick")
            obj = yield kwargs.pop("_obj", None)
            try:
                if callable(callback):
                    # call directly
                    yield callback(*args, **kwargs)
                    continue
                # try object method
                if not obj or not obj.pk:
                    # object was deleted between calls
                    self._to_remove.append(store_key)
                    continue
                else:
                    yield _GA(obj, callback)(*args, **kwargs)
            except ObjectDoesNotExist:
                log_trace("Removing ticker.")
                self._to_remove.append(store_key)
            except Exception:
                log_trace()
            finally:
                # make sure to re-store
                kwargs["_callback"] = callback
                kwargs["_obj"] = obj
        # cleanup - we do this here to avoid changing the subscription dict while it loops
        self._is_ticking = False
        for store_key in self._to_remove:
            self.remove(store_key)
        for store_key, (args, kwargs) in self._to_add:
            self.add(store_key, *args, **kwargs)
        self._to_remove = []
        self._to_add = []

    def __init__(self, interval):
        """
        Set up the ticker

        Args:
            interval (int): The stepping interval.

        """
        self.interval = interval
        self.subscriptions = {}
        self._is_ticking = False
        self._to_remove = []
        self._to_add = []
        # set up a twisted asynchronous repeat call
        self.task = ExtendedLoopingCall(self._callback)

    def validate(self, start_delay=None):
        """
        Start/stop the task depending on how many subscribers we have
        using it.

        Args:
            start_delay (int): Time to way before starting.

        """
        subs = self.subscriptions
        if self.task.running:
            if not subs:
                self.task.stop()
        elif subs:
            self.task.start(self.interval, now=False, start_delay=start_delay)

    def add(self, store_key, *args, **kwargs):
        """
        Sign up a subscriber to this ticker.
        Args:
            store_key (str): Unique storage hash for this ticker subscription.
            args (any, optional): Arguments to call the hook method with.

        Kwargs:
            _start_delay (int): If set, this will be
                used to delay the start of the trigger instead of
                `interval`.

        """
        if self._is_ticking:
            # protects the subscription dict from
            # updating while it is looping
            self._to_add.append((store_key, (args, kwargs)))
        else:
            start_delay = kwargs.pop("_start_delay", None)
            self.subscriptions[store_key] = (args, kwargs)
            self.validate(start_delay=start_delay)

    def remove(self, store_key):
        """
        Unsubscribe object from this ticker

        Args:
            store_key (str): Unique store key.

        """
        if self._is_ticking:
            # this protects the subscription dict from
            # updating while it is looping
            self._to_remove.append(store_key)
        else:
            self.subscriptions.pop(store_key, False)
            self.validate()

    def stop(self):
        """
        Kill the Task, regardless of subscriptions.

        """
        self.subscriptions = {}
        self.validate()
Example #6
0
class Ticker(object):
    """
    Represents a repeatedly running task that calls
    hooks repeatedly. Overload `_callback` to change the
    way it operates.
    """

    @inlineCallbacks
    def _callback(self):
        """
        This will be called repeatedly every `self.interval` seconds.
        `self.subscriptions` contain tuples of (obj, args, kwargs) for
        each subscribing object.

        If overloading, this callback is expected to handle all
        subscriptions when it is triggered. It should not return
        anything and should not traceback on poorly designed hooks.
        The callback should ideally work under @inlineCallbacks so it
        can yield appropriately.

        The _hook_key, which is passed down through the handler via
        kwargs is used here to identify which hook method to call.

        """
        self._to_add = []
        self._to_remove = []
        self._is_ticking = True
        for store_key, (args, kwargs) in self.subscriptions.iteritems():
            callback = yield kwargs.pop("_callback", "at_tick")
            obj = yield kwargs.pop("_obj", None)
            try:
                if callable(callback):
                    # call directly
                    yield callback(*args, **kwargs)
                    continue
                # try object method
                if not obj or not obj.pk:
                    # object was deleted between calls
                    self._to_remove.append(store_key)
                    continue
                else:
                    yield _GA(obj, callback)(*args, **kwargs)
            except ObjectDoesNotExist:
                log_trace("Removing ticker.")
                self._to_remove.append(store_key)
            except Exception:
                log_trace()
            finally:
                # make sure to re-store
                kwargs["_callback"] = callback
                kwargs["_obj"] = obj
        # cleanup - we do this here to avoid changing the subscription dict while it loops
        self._is_ticking = False
        for store_key in self._to_remove:
            self.remove(store_key)
        for store_key, (args, kwargs) in self._to_add:
            self.add(store_key, *args, **kwargs)
        self._to_remove = []
        self._to_add = []


    def __init__(self, interval):
        """
        Set up the ticker

        Args:
            interval (int): The stepping interval.

        """
        self.interval = interval
        self.subscriptions = {}
        self._is_ticking = False
        self._to_remove = []
        self._to_add = []
        # set up a twisted asynchronous repeat call
        self.task = ExtendedLoopingCall(self._callback)

    def validate(self, start_delay=None):
        """
        Start/stop the task depending on how many subscribers we have
        using it.

        Args:
            start_delay (int): Time to way before starting.

        """
        subs = self.subscriptions
        if self.task.running:
            if not subs:
                self.task.stop()
        elif subs:
            self.task.start(self.interval, now=False, start_delay=start_delay)

    def add(self, store_key, *args, **kwargs):
        """
        Sign up a subscriber to this ticker.
        Args:
            store_key (str): Unique storage hash for this ticker subscription.
            args (any, optional): Arguments to call the hook method with.

        Kwargs:
            _start_delay (int): If set, this will be
                used to delay the start of the trigger instead of
                `interval`.

        """
        if self._is_ticking:
            # protects the subscription dict from
            # updating while it is looping
            self._to_add.append((store_key, (args, kwargs)))
        else:
            start_delay = kwargs.pop("_start_delay", None)
            self.subscriptions[store_key] = (args, kwargs)
            self.validate(start_delay=start_delay)

    def remove(self, store_key):
        """
        Unsubscribe object from this ticker

        Args:
            store_key (str): Unique store key.

        """
        if self._is_ticking:
            # this protects the subscription dict from
            # updating while it is looping
            self._to_remove.append(store_key)
        else:
            self.subscriptions.pop(store_key, False)
            self.validate()

    def stop(self):
        """
        Kill the Task, regardless of subscriptions.

        """
        self.subscriptions = {}
        self.validate()
Example #7
0
class Ticker(object):
    """
    Represents a repeatedly running task that calls
    hooks repeatedly. Overload `_callback` to change the
    way it operates.
    """

    @inlineCallbacks
    def _callback(self):
        """
        This will be called repeatedly every `self.interval` seconds.
        `self.subscriptions` contain tuples of (obj, args, kwargs) for
        each subscribing object.

        If overloading, this callback is expected to handle all
        subscriptions when it is triggered. It should not return
        anything and should not traceback on poorly designed hooks.
        The callback should ideally work under @inlineCallbacks so it
        can yield appropriately.

        The _hook_key, which is passed down through the handler via
        kwargs is used here to identify which hook method to call.

        """
        for store_key, (obj, args, kwargs) in self.subscriptions.items():
            hook_key = yield kwargs.pop("_hook_key", "at_tick")
            if not obj or not obj.pk:
                # object was deleted between calls
                self.remove(store_key)
                continue
            try:
                yield _GA(obj, hook_key)(*args, **kwargs)
            except ObjectDoesNotExist:
                log_trace()
                self.remove(store_key)
            except Exception:
                log_trace()
            finally:
                # make sure to re-store
                kwargs["_hook_key"] = hook_key

    def __init__(self, interval):
        """
        Set up the ticker

        Args:
            interval (int): The stepping interval.

        """
        self.interval = interval
        self.subscriptions = {}
        # set up a twisted asynchronous repeat call
        self.task = ExtendedLoopingCall(self._callback)

    def validate(self, start_delay=None):
        """
        Start/stop the task depending on how many subscribers we have
        using it.

        Args:
            start_delay (int): Time to way before starting.

        """
        subs = self.subscriptions
        if None in subs.values():
            # clean out objects that may have been deleted
            subs = dict((store_key, obj) for store_key, obj in subs if obj)
            self.subscriptions = subs
        if self.task.running:
            if not subs:
                self.task.stop()
        elif subs:
            self.task.start(self.interval, now=False, start_delay=start_delay)

    def add(self, store_key, obj, *args, **kwargs):
        """
        Sign up a subscriber to this ticker.
        Args:
            store_key (str): Unique storage hash for this ticker subscription.
            obj (Object): Object subscribing to this ticker.
            args (any, optional): Arguments to call the hook method with.

        Kwargs:
            _start_delay (int): If set, this will be
                used to delay the start of the trigger instead of
                `interval`.
            _hooK_key (str): This carries the name of the hook method
                to call. It is passed on as-is from this method.

        """
        start_delay = kwargs.pop("_start_delay", None)
        self.subscriptions[store_key] = (obj, args, kwargs)
        self.validate(start_delay=start_delay)

    def remove(self, store_key):
        """
        Unsubscribe object from this ticker

        Args:
            store_key (str): Unique store key.

        """
        self.subscriptions.pop(store_key, False)
        self.validate()

    def stop(self):
        """
        Kill the Task, regardless of subscriptions.

        """
        self.subscriptions = {}
        self.validate()
class Ticker(object):
    """
    Represents a repeatedly running task that calls
    hooks repeatedly. Overload `_callback` to change the
    way it operates.
    """
    @inlineCallbacks
    def _callback(self):
        """
        This will be called repeatedly every `self.interval` seconds.
        `self.subscriptions` contain tuples of (obj, args, kwargs) for
        each subscribing object.

        If overloading, this callback is expected to handle all
        subscriptions when it is triggered. It should not return
        anything and should not traceback on poorly designed hooks.
        The callback should ideally work under @inlineCallbacks so it can yield
        appropriately.
        """
        for store_key, (obj, args, kwargs) in self.subscriptions.items():
            hook_key = yield kwargs.get("_hook_key", "at_tick")
            if not obj or not obj.pk:
                # object was deleted between calls
                self.remove(store_key)
                continue
            try:
                yield _GA(obj, hook_key)(*args, **kwargs)
            except ObjectDoesNotExist:
                log_trace()
                self.remove(store_key)
            except Exception:
                log_trace()

    def __init__(self, interval):
        """
        Set up the ticker
        """
        self.interval = interval
        self.subscriptions = {}
        # set up a twisted asynchronous repeat call
        self.task = ExtendedLoopingCall(self._callback)

    def validate(self, start_delay=None):
        """
        Start/stop the task depending on how many
        subscribers we have using it.
        """
        subs = self.subscriptions
        if None in subs.values():
            # clean out objects that may have been deleted
            subs = dict((store_key, obj) for store_key, obj in subs if obj)
            self.subscriptions = subs
        if self.task.running:
            if not subs:
                self.task.stop()
        elif subs:
            self.task.start(self.interval, now=False, start_delay=start_delay)

    def add(self, store_key, obj, *args, **kwargs):
        """
        Sign up a subscriber to this ticker. If kwargs contains
        a keyword _start_delay, this will be used to delay the start
        of the trigger instead of interval.
        """
        start_delay = kwargs.pop("_start_delay", None)
        self.subscriptions[store_key] = (obj, args, kwargs)
        self.validate(start_delay=start_delay)

    def remove(self, store_key):
        """
        Unsubscribe object from this ticker
        """
        self.subscriptions.pop(store_key, False)
        self.validate()

    def stop(self):
        """
        Kill the Task, regardless of subscriptions
        """
        self.subscriptions = {}
        self.validate()
Example #9
0
class Ticker(object):
    """
    Represents a repeatedly running task that calls
    hooks repeatedly. Overload `_callback` to change the
    way it operates.
    """
    @inlineCallbacks
    def _callback(self):
        """
        This will be called repeatedly every `self.interval` seconds.
        `self.subscriptions` contain tuples of (obj, args, kwargs) for
        each subscribing object.

        If overloading, this callback is expected to handle all
        subscriptions when it is triggered. It should not return
        anything and should not traceback on poorly designed hooks.
        The callback should ideally work under @inlineCallbacks so it
        can yield appropriately.

        The _hook_key, which is passed down through the handler via
        kwargs is used here to identify which hook method to call.

        """
        for store_key, (obj, args, kwargs) in self.subscriptions.items():
            hook_key = yield kwargs.pop("_hook_key", "at_tick")
            if not obj or not obj.pk:
                # object was deleted between calls
                self.remove(store_key)
                continue
            try:
                yield _GA(obj, hook_key)(*args, **kwargs)
            except ObjectDoesNotExist:
                log_trace()
                self.remove(store_key)
            except Exception:
                log_trace()
            finally:
                # make sure to re-store
                kwargs["_hook_key"] = hook_key

    def __init__(self, interval):
        """
        Set up the ticker

        Args:
            interval (int): The stepping interval.

        """
        self.interval = interval
        self.subscriptions = {}
        # set up a twisted asynchronous repeat call
        self.task = ExtendedLoopingCall(self._callback)

    def validate(self, start_delay=None):
        """
        Start/stop the task depending on how many subscribers we have
        using it.

        Args:
            start_delay (int): Time to way before starting.

        """
        subs = self.subscriptions
        if None in subs.values():
            # clean out objects that may have been deleted
            subs = dict((store_key, obj) for store_key, obj in subs if obj)
            self.subscriptions = subs
        if self.task.running:
            if not subs:
                self.task.stop()
        elif subs:
            self.task.start(self.interval, now=False, start_delay=start_delay)

    def add(self, store_key, obj, *args, **kwargs):
        """
        Sign up a subscriber to this ticker.
        Args:
            store_key (str): Unique storage hash for this ticker subscription.
            obj (Object): Object subscribing to this ticker.
            args (any, optional): Arguments to call the hook method with.

        Kwargs:
            _start_delay (int): If set, this will be
                used to delay the start of the trigger instead of
                `interval`.
            _hooK_key (str): This carries the name of the hook method
                to call. It is passed on as-is from this method.

        """
        start_delay = kwargs.pop("_start_delay", None)
        self.subscriptions[store_key] = (obj, args, kwargs)
        self.validate(start_delay=start_delay)

    def remove(self, store_key):
        """
        Unsubscribe object from this ticker

        Args:
            store_key (str): Unique store key.

        """
        self.subscriptions.pop(store_key, False)
        self.validate()

    def stop(self):
        """
        Kill the Task, regardless of subscriptions.

        """
        self.subscriptions = {}
        self.validate()
Example #10
0
class Ticker(object):
    """
    Represents a repeatedly running task that calls
    hooks repeatedly. Overload `_callback` to change the
    way it operates.
    """

    @inlineCallbacks
    def _callback(self):
        """
        This will be called repeatedly every `self.interval` seconds.
        `self.subscriptions` contain tuples of (obj, args, kwargs) for
        each subscribing object.

        If overloading, this callback is expected to handle all
        subscriptions when it is triggered. It should not return
        anything and should not traceback on poorly designed hooks.
        The callback should ideally work under @inlineCallbacks so it can yield
        appropriately.
        """
        for store_key, (obj, args, kwargs) in self.subscriptions.items():
            hook_key = yield kwargs.get("_hook_key", "at_tick")
            if not obj or not obj.pk:
                # object was deleted between calls
                self.remove(store_key)
                continue
            try:
                yield _GA(obj, hook_key)(*args, **kwargs)
            except ObjectDoesNotExist:
                log_trace()
                self.remove(store_key)
            except Exception:
                log_trace()

    def __init__(self, interval):
        """
        Set up the ticker
        """
        self.interval = interval
        self.subscriptions = {}
        # set up a twisted asynchronous repeat call
        self.task = ExtendedLoopingCall(self._callback)

    def validate(self, start_delay=None):
        """
        Start/stop the task depending on how many
        subscribers we have using it.
        """
        subs = self.subscriptions
        if None in subs.values():
            # clean out objects that may have been deleted
            subs = dict((store_key, obj) for store_key, obj in subs if obj)
            self.subscriptions = subs
        if self.task.running:
            if not subs:
                self.task.stop()
        elif subs:
            self.task.start(self.interval, now=False, start_delay=start_delay)

    def add(self, store_key, obj, *args, **kwargs):
        """
        Sign up a subscriber to this ticker. If kwargs contains
        a keyword _start_delay, this will be used to delay the start
        of the trigger instead of interval.
        """
        start_delay = kwargs.pop("_start_delay", None)
        self.subscriptions[store_key] = (obj, args, kwargs)
        self.validate(start_delay=start_delay)

    def remove(self, store_key):
        """
        Unsubscribe object from this ticker
        """
        self.subscriptions.pop(store_key, False)
        self.validate()

    def stop(self):
        """
        Kill the Task, regardless of subscriptions
        """
        self.subscriptions = {}
        self.validate()