Skip to content

File: Broken/Core/BrokenLogging.py

Broken.Core.BrokenLogging

console

console = rich.get_console()

BrokenLogging

Bases: BrokenSingleton

Source code in Broken/Core/BrokenLogging.py
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
class BrokenLogging(BrokenSingleton):
    def __init__(self):
        self.reset()

    @staticmethod
    def project() -> str:
        return Environment.get("BROKEN_APP_NAME", "Broken")

    @staticmethod
    def set_project(name: str, *, force: bool=False) -> None:
        if (BrokenLogging.project() == "Broken") or force:
            Environment.set("BROKEN_APP_NAME", name)

    def format(self, data: dict) -> str:
        when = time.absolute()
        data["time"] = f"{int(when//60)}'{(when%60):06.3f}"
        data["project"] = self.project()

        # Simpler logging for non UTF or workflows
        if Runtime.GitHub or Environment.flag("SIMPLE_LOGGING", 0):
            return ("[{project}][{time}][{level:7}] {message}").format(**data)

        elif Environment.flag("PLAIN_LOGGING", 0):
            return ("[{level:7}] {message}").format(**data)

        return (
            f"│[dodger_blue3]{self.project()}[/]├"
            "┤[green]{time}[/]├"
            "┤[{level.icon}]{level:7}[/{level.icon}]│ "
            "▸ {message}"
        ).format(**data)

    @property
    def level(self) -> str:
        return Environment.get("LOGLEVEL", "INFO").upper()

    @level.setter
    def level(self, level: str) -> None:
        Environment.set("LOGLEVEL", level.upper())
        self.reset()

    @property
    def sink(self) -> Callable:
        if Runtime.GitHub:
            return print
        return rich.print

    def reset(self) -> None:
        log.remove()
        log.add(
            sink=self.sink,
            format=self.format,
            level=Environment.get("LOGLEVEL", "INFO").upper(),
            colorize=False,
            backtrace=True,
            diagnose=True,
            catch=True,
        )
        self._make_level("TRACE", None, "dark_turquoise")
        self._make_level("DEBUG", None, "turquoise4")
        self._make_level("INFO", None, "bright_white")
        self._make_level("NOTE", 25, "bright_blue")
        self._make_level("SPECIAL", 25, "bright_blue")
        self._make_level("TIP", 25, "dark_cyan")
        self._make_level("SUCCESS", None, "green")
        self._make_level("MINOR", 25, "grey42")
        self._make_level("SKIP", 25, "grey42")
        self._make_level("FIXME", 25, "cyan")
        self._make_level("TODO", 25, "dark_blue")
        self._make_level("WARNING", None, "yellow")
        self._make_level("ERROR", None, "red")
        self._make_level("CRITICAL", None, "red")

    def _make_level(self, level: str, loglevel: int=0, color: str=None) -> None:
        """Create or update a loglevel `.{name.lower()}` on the logger"""
        def wrapper(
            *args: str,
            dedent: bool=False,
            echo: bool=True,
        ) -> str:
            message = " ".join(map(str, args))
            if dedent:
                message = textwrap.dedent(message)
            if not echo:
                return message
            for line in message.splitlines():
                log.log(level, line)
            return message

        # Assign log function to logger. Workaround to set icon=color
        log.level(level, loglevel, icon=color)
        setattr(log, level.lower(), wrapper)

__init__

__init__()
Source code in Broken/Core/BrokenLogging.py
16
17
def __init__(self):
    self.reset()

project

project() -> str
Source code in Broken/Core/BrokenLogging.py
19
20
21
@staticmethod
def project() -> str:
    return Environment.get("BROKEN_APP_NAME", "Broken")

set_project

set_project(name: str, *, force: bool = False) -> None
Source code in Broken/Core/BrokenLogging.py
23
24
25
26
@staticmethod
def set_project(name: str, *, force: bool=False) -> None:
    if (BrokenLogging.project() == "Broken") or force:
        Environment.set("BROKEN_APP_NAME", name)

format

format(data: dict) -> str
Source code in Broken/Core/BrokenLogging.py
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
def format(self, data: dict) -> str:
    when = time.absolute()
    data["time"] = f"{int(when//60)}'{(when%60):06.3f}"
    data["project"] = self.project()

    # Simpler logging for non UTF or workflows
    if Runtime.GitHub or Environment.flag("SIMPLE_LOGGING", 0):
        return ("[{project}][{time}][{level:7}] {message}").format(**data)

    elif Environment.flag("PLAIN_LOGGING", 0):
        return ("[{level:7}] {message}").format(**data)

    return (
        f"│[dodger_blue3]{self.project()}[/]├"
        "┤[green]{time}[/]├"
        "┤[{level.icon}]{level:7}[/{level.icon}]│ "
        "▸ {message}"
    ).format(**data)

level

level: str

sink

sink: Callable

reset

reset() -> None
Source code in Broken/Core/BrokenLogging.py
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
def reset(self) -> None:
    log.remove()
    log.add(
        sink=self.sink,
        format=self.format,
        level=Environment.get("LOGLEVEL", "INFO").upper(),
        colorize=False,
        backtrace=True,
        diagnose=True,
        catch=True,
    )
    self._make_level("TRACE", None, "dark_turquoise")
    self._make_level("DEBUG", None, "turquoise4")
    self._make_level("INFO", None, "bright_white")
    self._make_level("NOTE", 25, "bright_blue")
    self._make_level("SPECIAL", 25, "bright_blue")
    self._make_level("TIP", 25, "dark_cyan")
    self._make_level("SUCCESS", None, "green")
    self._make_level("MINOR", 25, "grey42")
    self._make_level("SKIP", 25, "grey42")
    self._make_level("FIXME", 25, "cyan")
    self._make_level("TODO", 25, "dark_blue")
    self._make_level("WARNING", None, "yellow")
    self._make_level("ERROR", None, "red")
    self._make_level("CRITICAL", None, "red")