Skip to content

Commit 9fe3c5b

Browse files
committed
cleanup ansi and colourise arguments
1 parent b806ec2 commit 9fe3c5b

File tree

6 files changed

+75
-66
lines changed

6 files changed

+75
-66
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ htmlcov/
1313
benchmarks/*.json
1414
docs/_build/
1515
old-version/
16+
*.swp

devtools/ansi.py

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -22,30 +22,28 @@ def strip_ansi(value):
2222

2323

2424
class Style(IntEnum):
25-
"""
26-
Heavily borrowed from https://github.com/pallets/click/blob/6.7/click/termui.py
27-
28-
Italic added, multiple ansi codes condensed into one block and generally modernised.
29-
"""
3025
reset = 0
3126

3227
bold = 1
33-
un_bold = 22
28+
not_bold = 22
3429

3530
dim = 2
36-
un_dim = 22
31+
not_dim = 22
3732

3833
italic = 3
39-
un_italic = 23
34+
not_italic = 23
4035

4136
underline = 4
42-
un_underline = 24
37+
not_underline = 24
4338

4439
blink = 5
45-
un_blink = 25
40+
not_blink = 25
4641

4742
reverse = 7
48-
un_reverse = 27
43+
not_reverse = 27
44+
45+
strike_through = 9
46+
not_strike_through = 29
4947

5048
# foreground colours
5149
black = 30
@@ -56,7 +54,6 @@ class Style(IntEnum):
5654
magenta = 35
5755
cyan = 36
5856
white = 37
59-
fg_reset = 38
6057

6158
# background colours
6259
bg_black = 40
@@ -67,55 +64,45 @@ class Style(IntEnum):
6764
bg_magenta = 45
6865
bg_cyan = 46
6966
bg_white = 47
70-
bg_reset = 48
7167

7268
# this is a meta value used for the "Style" instance which is the "style" function
7369
function = -1
7470

75-
def __call__(self, text: Any, *styles, reset: bool=True):
71+
def __call__(self, input: Any, *styles, reset: bool=True, apply: bool=True):
7672
"""
77-
Styles a text with ANSI styles and returns the new string.
73+
Styles text with ANSI styles and returns the new string.
7874
7975
By default the styling is cleared at the end of the string, this can be prevented with``reset=False``.
8076
8177
Examples::
8278
83-
print(style('Hello World!', style.green))
84-
print(style('ATTENTION!', style.bg_magenta))
85-
print(style('Some things', style.reverse, style.bold))
79+
print(sformat('Hello World!', sformat.green))
80+
print(sformat('ATTENTION!', sformat.bg_magenta))
81+
print(sformat('Some things', sformat.reverse, sformat.bold))
8682
87-
Supported color names:
88-
89-
* ``black`` (might be a gray)
90-
* ``red``
91-
* ``green``
92-
* ``yellow`` (might be an orange)
93-
* ``blue``
94-
* ``magenta``
95-
* ``cyan``
96-
* ``white`` (might be light gray)
97-
* ``reset`` (reset the color code only)
98-
99-
:param text: the string to style with ansi codes.
83+
:param input: the object to style with ansi codes.
10084
:param *styles: zero or more styles to apply to the text, should be either style instances or strings
10185
matching style names.
102-
:param reset: by default a reset-all code is added at the end of the
103-
string which means that styles do not carry over. This
104-
can be disabled to compose styles.
86+
:param reset: if False the ansi reset code is not appended to the end of the string
87+
:param: apply: if False no ansi codes are applied
10588
"""
89+
text = str(input)
90+
if not apply:
91+
return text
10692
codes = []
10793
for s in styles:
108-
if not isinstance(s, self.__class__):
94+
# raw ints are allowed
95+
if not isinstance(s, self.__class__) and not isinstance(s, int):
10996
try:
11097
s = self.styles[s]
11198
except KeyError:
11299
raise ValueError('invalid style "{}"'.format(s))
113100
codes.append(str(s.value))
114101

115102
if codes:
116-
r = _ansi_template.format(';'.join(codes)) + str(text)
103+
r = _ansi_template.format(';'.join(codes)) + text
117104
else:
118-
r = str(text)
105+
r = text
119106

120107
if reset:
121108
r += _ansi_template.format(self.reset)
@@ -127,7 +114,7 @@ def styles(self):
127114

128115
def __repr__(self):
129116
if self == self.function:
130-
return '<pseudo function style(text, *styles)>'
117+
return '<pseudo function sformat(text, *styles)>'
131118
else:
132119
return super().__repr__()
133120

@@ -141,7 +128,20 @@ def __str__(self):
141128
sformat = Style(-1)
142129

143130

144-
def sprint(text, *styles, reset=True, flush=True, file=None, **print_kwargs):
145-
if isatty(file):
146-
text = sformat(text, *styles, reset=reset)
147-
print(text, flush=flush, file=file, **print_kwargs)
131+
class StylePrint:
132+
"""
133+
Annoyingly enums do not allow inheritance, this is a lazy design mistake, this is an ugly work around
134+
for that mistake.
135+
"""
136+
def __call__(self, input, *styles, reset=True, flush=True, file=None, **print_kwargs):
137+
text = sformat(input, *styles, reset=reset, apply=isatty(file))
138+
print(text, flush=flush, file=file, **print_kwargs)
139+
140+
def __getattr__(self, item):
141+
return getattr(sformat, item)
142+
143+
def __repr__(self):
144+
return '<pseudo function sprint(text, *styles)>'
145+
146+
147+
sprint = StylePrint()

devtools/debug.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,21 @@ def __init__(self, value, *, name=None, **extra):
3030
self.extra.append(('len', len(value)))
3131
self.extra += [(k, v) for k, v in extra.items() if v is not None]
3232

33-
def __str__(self) -> str:
34-
template = '{value} ({self.value.__class__.__name__}) {extra}'
33+
def str(self, colours=False) -> str:
34+
s = ''
3535
if self.name:
36-
template = '{self.name} = ' + template
37-
return template.format(
38-
self=self,
39-
value=pformat(self.value, indent=2),
40-
extra=' '.join('{}={}'.format(k, v) for k, v in self.extra)
41-
).rstrip(' ') # trailing space if extra is empty
36+
s = sformat(self.name, sformat.blue, apply=colours) + ' = '
37+
s += pformat(self.value, indent=2)
38+
suffix = (
39+
' ({0.value.__class__.__name__}) {1}'
40+
.format(self, ' '.join('{}={}'.format(k, v) for k, v in self.extra))
41+
.rstrip(' ') # trailing space if extra is empty
42+
)
43+
s += sformat(suffix, sformat.dim, apply=colours)
44+
return s
45+
46+
def __str__(self) -> str:
47+
return self.str()
4248

4349

4450
class DebugOutput:
@@ -63,7 +69,7 @@ def str(self, colours=False) -> str:
6369
)
6470
else:
6571
prefix = '{0.filename}:{0.lineno} {0.frame}\n '.format(self)
66-
return prefix + '\n '.join(str(a) for a in self.arguments)
72+
return prefix + '\n '.join(a.str(colours) for a in self.arguments)
6773

6874
def __str__(self) -> str:
6975
return self.str()
@@ -99,7 +105,8 @@ def _env_bool(cls, value, env_name, env_default='TRUE'):
99105

100106
def __call__(self, *args, file_=None, flush_=True, **kwargs) -> None:
101107
d_out = self._process(args, kwargs, r'debug *\(')
102-
s = d_out.str(isatty(file_))
108+
colours_possible = isatty(file_)
109+
s = d_out.str(self._colours and colours_possible)
103110
print(s, file=file_, flush=flush_)
104111

105112
def format(self, *args, **kwargs) -> DebugOutput:

devtools/prettier.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@
2323

2424
class PrettyFormat:
2525
def __init__(self,
26-
colorize=False,
26+
colours=False,
2727
indent_step=4,
2828
indent_char=' ',
2929
repr_strings=False,
3030
simple_cutoff=10,
3131
max_width=120,
3232
yield_from_generators=True):
33-
self._colorize = colorize
33+
self._colours = colours
3434
self._indent_step = indent_step
3535
self._c = indent_char
3636
self._repr_strings = repr_strings
@@ -49,7 +49,7 @@ def __call__(self, value: Any, *, indent: int=0, indent_first: bool=False):
4949
self._stream = io.StringIO()
5050
self._format(value, indent_current=indent, indent_first=indent_first)
5151
s = self._stream.getvalue()
52-
if self._colorize and pyg_lexer:
52+
if self._colours and pyg_lexer:
5353
s = highlight(s, lexer=pyg_lexer, formatter=pyg_formatter)
5454
return s
5555

@@ -145,7 +145,7 @@ def _format_raw(self, value: Any, value_repr: str, indent_current: int, indent_n
145145

146146

147147
pformat = PrettyFormat()
148-
_ppformat = PrettyFormat(colorize=isatty())
148+
_ppformat = PrettyFormat(colours=isatty())
149149

150150

151151
def pprint(s):

tests/test_ansi.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from devtools.ansi import sformat, sprint
66

77

8-
def test_colorize():
8+
def test_colours():
99
v = sformat('hello', sformat.red)
1010
assert v == '\x1b[31mhello\x1b[0m'
1111

@@ -43,7 +43,7 @@ def test_invalid_style_str():
4343

4444
def test_print_not_tty():
4545
stream = io.StringIO()
46-
sprint('hello', sformat.green, file=stream)
46+
sprint('hello', sprint.green, file=stream)
4747
out = stream.getvalue()
4848
assert out == 'hello\n'
4949

@@ -54,7 +54,7 @@ def isatty(self):
5454
return True
5555

5656
stream = TTYStream()
57-
sprint('hello', sformat.green, file=stream)
57+
sprint('hello', sprint.green, file=stream)
5858
out = stream.getvalue()
5959
assert out == '\x1b[32mhello\x1b[0m\n', repr(out)
6060

@@ -72,14 +72,15 @@ def isatty(self):
7272

7373
def test_get_styles():
7474
assert sformat.styles['bold'] == 1
75-
assert sformat.styles['un_bold'] == 22
75+
assert sformat.styles['not_bold'] == 22
7676

7777

78-
def test_repr():
79-
assert repr(sformat) == '<pseudo function style(text, *styles)>'
78+
def test_repr_str():
79+
assert repr(sformat) == '<pseudo function sformat(text, *styles)>'
8080
assert repr(sformat.red) == '<Style.red: 31>'
8181

82-
83-
def test_str():
84-
assert str(sformat) == '<pseudo function style(text, *styles)>'
82+
assert str(sformat) == '<pseudo function sformat(text, *styles)>'
8583
assert str(sformat.red) == 'Style.red'
84+
85+
assert repr(sprint) == '<pseudo function sprint(text, *styles)>'
86+
assert str(sprint) == '<pseudo function sprint(text, *styles)>'

tests/test_prettier.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def test_print(capsys):
2828

2929

3030
def test_colours():
31-
pformat_ = PrettyFormat(colorize=True)
31+
pformat_ = PrettyFormat(colours=True)
3232
v = pformat_({1: 2, 3: 4})
3333
assert v.startswith('\x1b'), repr(v)
3434
v2 = strip_ansi(v)

0 commit comments

Comments
 (0)