Passed
Push — main ( a79885...50e5ea )
by Douglas
02:25
created

pocketutils.misc.console   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 165
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 125
dl 0
loc 165
rs 10
c 0
b 0
f 0
wmc 23

19 Methods

Rating   Name   Duplication   Size   Complexity  
A ColorConsole._stream() 0 3 1
A ColorConsoleBuilder.build() 0 17 2
A ColorConsoleBuilder.top() 0 3 1
A ColorConsoles.default() 0 13 2
A AbstractColorConsole.format() 0 2 1
A ColorConsoleBuilder.pad_bottom() 0 3 1
A ColorConsoleBuilder.bottom() 0 3 1
A ColorConsole.__init__() 0 17 1
A ColorConsoleBuilder.pad_top() 0 3 1
A AbstractColorConsole._reset() 0 3 1
A ColorConsoleBuilder.right() 0 3 1
A ColorConsoleBuilder.__init__() 0 6 1
A AbstractColorConsole._stream() 0 3 1
A ColorConsoleBuilder.left() 0 3 1
A ColorConsoleBuilder.width() 0 3 1
A ColorConsole.format() 0 21 2
A ColorConsoleBuilder.add() 0 3 1
A AbstractColorConsole.print() 0 3 2
A ColorConsoles.new() 0 3 1
1
"""
2
Experimental replacement for fancy consoles.
3
"""
4
import abc
5
import logging
6
import sys
7
from typing import Callable, Optional, TypeVar, Generic, Sequence
8
9
from colorama import Style, Fore
0 ignored issues
show
introduced by
Unable to import 'colorama'
Loading history...
10
11
from pocketutils.core.input_output import Writeable
12
from pocketutils.misc.messages import *
0 ignored issues
show
Unused Code introduced by
Mapping was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
SmartEnum was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
MsgFormatter was imported with wildcard, but is not used.
Loading history...
Coding Style introduced by
The usage of wildcard imports like pocketutils.misc.messages should generally be avoided.
Loading history...
Unused Code introduced by
MsgFormatterSimple was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
Enum was imported with wildcard, but is not used.
Loading history...
13
14
15
logger = logging.getLogger("pocketutils")
16
L = TypeVar("L", covariant=True)
0 ignored issues
show
Coding Style Naming introduced by
Class name "L" doesn't conform to PascalCase naming style ('[^\\W\\da-z][^\\W_]+$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
17
M = TypeVar("M", covariant=True)
0 ignored issues
show
Coding Style Naming introduced by
Class name "M" doesn't conform to PascalCase naming style ('[^\\W\\da-z][^\\W_]+$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
18
19
20
class AbstractColorConsole(Generic[L, M], metaclass=abc.ABCMeta):
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
21
    def print(self, *lines: str, level: L, mod: Optional[M] = None) -> None:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
22
        for line in self.format(*lines, level=level, mod=mod):
23
            self._stream.write(line)
24
25
    @property
26
    def _stream(self) -> Writeable:
27
        raise NotImplementedError()
28
29
    @property
30
    def _reset(self) -> int:
31
        return Style.RESET_ALL
32
33
    def format(self, *lines: str, level: L, mod: Optional[M] = None) -> Sequence[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
34
        raise NotImplementedError()
35
36
37
class ColorConsole(AbstractColorConsole[MsgLevel, bool]):
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
best-practice introduced by
Too many instance attributes (9/7)
Loading history...
introduced by
Value 'AbstractColorConsole' is unsubscriptable
Loading history...
38
    def __init__(
0 ignored issues
show
best-practice introduced by
Too many arguments (10/5)
Loading history...
39
        self,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
40
        stream: Writeable,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
41
        top: str,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
42
        bottom: str,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
43
        left: str,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
44
        right: str,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
45
        pad_top: int,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
46
        pad_bottom: int,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
47
        width: int,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
48
        mapping: Callable[[MsgLevel], int],
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
49
    ):
50
        self._the_stream = stream
51
        self._top, self._bottom, self._left, self._right = top, bottom, left, right
52
        self._pad_top, self._pad_bottom = pad_top, pad_bottom
53
        self._width = width
54
        self._mapping = mapping
55
56
    def format(self, *lines: str, level: MsgLevel, mod: Optional[bool] = None) -> Sequence[str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
57
        color = str(self._mapping(level))
58
        width = self._width
59
        reset = str(self._reset)
60
        if mod:
61
            top, bottom, left, right = self._top, self._bottom, self._left, self._right
62
            pad_top = ["" for _ in range(self._pad_top)]
63
            pad_bottom = ["" for _ in range(self._pad_bottom)]
64
        else:
65
            top, bottom, left, right = "", "", "", ""
66
            pad_top, pad_bottom = [], []
67
68
        def cl(text: str):
0 ignored issues
show
Coding Style Naming introduced by
Function name "cl" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
69
            return color + left + text.center(width - len(left) - len(right)) + right + reset
70
71
        return [
72
            *pad_top,
73
            color + top * width + reset,
74
            *[cl(line) for line in lines],
75
            color + bottom * width + reset,
76
            *pad_bottom,
77
        ]
78
79
    @property
80
    def _stream(self) -> Writeable:
81
        return self._the_stream
82
83
84
class ColorConsoleBuilder:
0 ignored issues
show
best-practice introduced by
Too many instance attributes (8/7)
Loading history...
introduced by
Missing class docstring
Loading history...
85
    def __init__(self):
86
        self._mapping = {}
87
        self._width = 100
88
        self._top, self._bottom = "-", "-"
89
        self._left, self._right = "", ""
90
        self._pad_top, self._pad_bottom = 1, 1
91
92
    def add(self, level: MsgLevel, color: int) -> __qualname__:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
Comprehensibility Best Practice introduced by
Undefined variable '__qualname__'
Loading history...
93
        self._mapping[level] = color
94
        return self
95
96
    def width(self, w: int) -> __qualname__:
0 ignored issues
show
Coding Style Naming introduced by
Argument name "w" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
introduced by
Missing function or method docstring
Loading history...
97
        self._width = w
98
        return self
99
100
    def top(self, top: str) -> __qualname__:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
101
        self._top = top
102
        return self
103
104
    def bottom(self, bottom: str) -> __qualname__:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
105
        self._bottom = bottom
106
        return self
107
108
    def left(self, left: str) -> __qualname__:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
109
        self._left = left
110
        return self
111
112
    def right(self, right: str) -> __qualname__:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
113
        self._right = right
114
        return self
115
116
    def pad_top(self, i: int) -> __qualname__:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
117
        self._pad_top = i
118
        return self
119
120
    def pad_bottom(self, i: int) -> __qualname__:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
121
        self._pad_bottom = i
122
        return self
123
124
    def build(self, sink: Optional[Writeable] = None) -> ColorConsole:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
125
        if sink is None:
126
            sink = sys.stdout
127
128
        def fn(level: MsgLevel):
0 ignored issues
show
Coding Style Naming introduced by
Function name "fn" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
129
            return self._mapping[level]
130
131
        return ColorConsole(
132
            sink,
133
            self._top,
134
            self._bottom,
135
            self._left,
136
            self._right,
137
            self._pad_top,
138
            self._pad_bottom,
139
            self._width,
140
            fn,
141
        )
142
143
144
class ColorConsoles:
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
145
    @classmethod
146
    def new(cls) -> ColorConsoleBuilder:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
147
        return ColorConsoleBuilder()
148
149
    @classmethod
150
    def default(cls) -> ColorConsoleBuilder:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
151
        mapping = {
152
            MsgLevel.INFO: Style.BRIGHT,
153
            MsgLevel.NOTICE: Fore.BLUE,
154
            MsgLevel.SUCCESS: Fore.GREEN,
155
            MsgLevel.WARNING: Fore.MAGENTA,
156
            MsgLevel.FAILURE: Fore.RED,
157
        }
158
        builder = ColorConsoleBuilder()
159
        for k, v in mapping.items():
0 ignored issues
show
Coding Style Naming introduced by
Variable name "v" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
160
            builder.add(k, v)
161
        return builder
162
163
164
__all__ = ["AbstractColorConsole", "ColorConsole", "ColorConsoles"]
165