tobi-wan-kenobi/bumblebee-status

View on GitHub
bumblebee_status/core/decorators.py

Summary

Maintainability
A
2 hrs
Test Coverage
A
100%
import difflib
import logging

import util.format

log = logging.getLogger(__name__)


"""Specifies that a module should never update (i.e. has static content).
This means that its update() method will never be invoked

:param init: The __init__() method of the module

:return: Wrapped method that sets the module's interval to "never"
"""


def never(init):
    def call_init(obj, *args, **kwargs):
        init(obj, *args, **kwargs)
        if obj.parameter("interval") is None:
            obj.set("interval", "never")

    return call_init


"""Specifies the interval for executing the module's update() method

:param hours: Hours between two update() invocations, defaults to 0
:param minutes: Minutes between two update() invocations, defaults to 0
:param seconds: Seconds between two update() invocations, defaults to 0

:return: Wrapped method that sets the module's interval correspondingly
"""


def every(hours=0, minutes=0, seconds=0):
    def decorator_init(init):
        def call_init(obj, *args, **kwargs):
            init(obj, *args, **kwargs)
            if obj.parameter("interval") is None:
                obj.set("interval", hours * 3600 + minutes * 60 + seconds)

        return call_init

    return decorator_init


"""Specifies that the module's content should scroll, if required

The exact behaviour of this method is governed by a number of parameters,
specifically: The module's parameter "scrolling.width"  specifies the width when
scrolling starts, "scrolling.makewide" defines whether the module should be expanded
to "scrolling.width" automatically, if the content is shorter, the parameter
"scrolling.bounce" defines whether it scrolls like a marquee (False) or should bounce
when the end of the content is reached. "scrolling.speed" defines the number of characters
to scroll each iteration.

:param func: Function for which the result should be scrolled
"""


def scrollable(func):
    def wrapper(module, widget):
        text = func(module, widget)
        if not text:
            return text

        if (
            difflib.SequenceMatcher(a=text, b=widget.get("__content__", text)).ratio()
            < 0.9
        ):
            widget.set("scrolling.start", 0)
            widget.set("scrolling.direction", "right")
        widget.set("__content__", text)

        width = util.format.asint(module.parameter("scrolling.width", 30))
        if util.format.asbool(module.parameter("scrolling.makewide", True)):
            widget.set("theme.minwidth", "A" * width)
        if width < 0 or len(text) <= width:
            return text

        start = widget.get("scrolling.start", 0)
        bounce = util.format.asbool(module.parameter("scrolling.bounce", True))
        scroll_speed = util.format.asint(module.parameter("scrolling.speed", 1))
        direction = widget.get("scrolling.direction", "right")

        if direction == "left":
            if start - scroll_speed < 0:  # bounce back
                widget.set("scrolling.direction", "right")
            else:
                scroll_speed = -scroll_speed

        next_start = start + scroll_speed
        if next_start + width > len(text):
            if not bounce:
                next_start = 0
            else:
                next_start = start - scroll_speed
                widget.set("scrolling.direction", "left")

        widget.set("scrolling.start", next_start)

        return text[start : start + width]

    return wrapper


# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4