Commit 9c1807b2 authored by Anael Beutot's avatar Anael Beutot
Browse files

Change tag calculation.

Use a timer watcher to refresh the value on the node side.
parent 13bd01f0
Loading
Loading
Loading
Loading
+37 −14
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@ logger = logging.getLogger(__name__)

class Tag(object):
    """``class`` that abstract tags and act as a simple container."""
    def __init__(self, name, valuable, ttl=-1, parent=None):
    def __init__(self, name, valuable, ttl=-1, refresh=None, parent=None):
        """
        :param string name: tag name
        :param valuable: something that gives tag value, string or callable
@@ -19,35 +19,58 @@ class Tag(object):
                * None (means no ttl)
                * -1 (means infinite ttl)
                * positive integer in seconds

            Note: this has absolutely not any importance for the cc-node, only
                for cc-server
        :param None,int refresh: period used to refresh tag value on the node
        :param object obj: parent object the tag is attached to, it may be
            needed for the tag callable to process the tag
        """
        self.name = name
        self.value = None
        self.is_function = False
        self.ttl = ttl
        self.refresh = refresh
        self.parent = parent if parent is None else weakref.proxy(parent)


        if inspect.isfunction(valuable):
            self.is_function = True
            args_count = len(inspect.getargspec(valuable).args)
            if args_count > 1:
                raise Exception('Invalid number of argument for tag function')
                raise TypeError('Tag function take at most 1 argument')
            elif args_count == 1:
                self._value = partial(valuable, self.parent)
                self._calculate_value = partial(valuable, self.parent)
            else:
                self._value = valuable
                self._calculate_value = valuable
        else:
            self._value = lambda: valuable
            self.value = valuable

    @property
    def value(self):
        """Property that return tag value. Just return the provided value or
        call the function.
        self.watcher = None

    def calculate_value(self):
        self._value = self._calculate_value()
        # logger.debug('Calculate Tag(%s) = %s', self.name, self._value)

    def start(self, loop):
        """
        :param loop: pyev loop
        """
        try:
            return self._value()
        except Exception:
            logger.exception('Calculating tag %s failed:', self.name)
            return None
        if not self.is_function:
            return

        if self.refresh is None:
            self._value = self._calculate_value()
            return

        # TODO more sophisticated calculation with event propagation
        self.watcher = loop.timer(.0, float(self.refresh), lambda *args:
                                  self.calculate_value())
        self.watcher.start()

    def stop(self):
        if watcher is not None:
            self.watcher.stop()


def tag_inspector(mod, parent=None):