Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support colorscheme with only basic ANSI color sequences #63

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions stackprinter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ def format(thing=None, **kwargs):
style: string
'plaintext' (default): Output just text

'ansi': Enable colors, using basic ansi sequences. It is compatible
with light and dark background, based on terminal settings.

'darkbg', 'darkbg2', 'darkbg3', 'lightbg', 'lightbg2', 'lightbg3':
Enable colors, for use in terminals that support 256 ansi
colors or in jupyter notebooks (or even with `ansi2html`)
Expand Down
199 changes: 114 additions & 85 deletions stackprinter/colorschemes.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,92 @@
import random
import colorsys


__all__ = ['color', 'darkbg', 'darkbg2', 'darkbg3',
__all__ = ['plaintext', 'color',
'darkbg', 'darkbg2', 'darkbg3',
'lightbg', 'lightbg2', 'lightbg3']

class ColorScheme():

def __getitem__(self, name):
raise NotImplemented

def get_random(self):
def get_random(self, seed, highlight):
raise NotImplemented


class plaintext(ColorScheme):

def __getitem__(self, name):
return "%s"

def get_random(self, seed, highlight):
return "%s"


class ansi(ColorScheme):
colors = {
'exception_type': '31',
'exception_msg': '31',
'highlight': '1;31',
'header': '0',
'lineno': '1',
'arrow_lineno': '1',
'dots': '0',
'source_bold': '0',
'source_default': '0',
'source_comment': '0',
'var_invisible': '0',
}

def __init__(self):
self.rng = random.Random()

def __getitem__(self, name):
return self._ansi_tpl(self.colors[name])

def get_random(self, seed, highlight):
self.rng.seed(seed)
random_code = str(self.rng.randint(32, 36))
if self.rng.choice((True, False)):
random_code = "1;" + random_code
return self._ansi_tpl(random_code)

@staticmethod
def _ansi_tpl(color_code):
return f"\u001b[{color_code}m%s\u001b[0m"


class HslScheme(ColorScheme):
colors = {}

def __init__(self):
self.rng = random.Random()

def __getitem__(self, name):
return self._ansi_tpl(*self.colors[name])

def get_random(self, seed, highlight):
self.rng.seed(seed)
return self._ansi_tpl(*self._random_color(highlight))

def _random_color(self, highlight):
raise NotImplemented

@staticmethod
def _ansi_tpl(hue, sat, val, bold=False):
r_, g_, b_ = colorsys.hsv_to_rgb(hue, sat, val)
r = int(round(r_*5))
g = int(round(g_*5))
b = int(round(b_*5))
point = 16 + 36 * r + 6 * g + b

bold_tp = '1;' if bold else ''
code_tpl = ('\u001b[%s38;5;%dm' % (bold_tp, point)) + '%s\u001b[0m'
return code_tpl


class darkbg(ColorScheme):
class darkbg(HslScheme):
# Hue, Sat, Val, Bold
colors = {'exception_type': (0.0, 0.9, 0.6, False),
'exception_msg': (0.0, 0.9, 0.6, True),
Expand All @@ -31,27 +104,17 @@ class darkbg(ColorScheme):
'var_invisible': (0.6, 0.4, 0.4, False)
}

def __init__(self):
self.rng = random.Random()

def __getitem__(self, name):
return self.colors[name]

def get_random(self, seed, highlight):
self.rng.seed(seed)

def _random_color(self, highlight):
hue = self.rng.uniform(0.05,0.7)
# if hue < 0:
# hue = hue + 1
sat = 1. #1. if highlight else 0.5
val = 0.5 #1. if highlight else 0.3
sat = 1.0
val = 0.5
bold = highlight

return hue, sat, val, bold



class darkbg2(ColorScheme):
class darkbg2(HslScheme):
# Hue, Sat, Val, Bold
colors = {'exception_type': (0., 1., 0.8, True),
'exception_msg': (0., 1., 0.8, True),
Expand All @@ -69,26 +132,16 @@ class darkbg2(ColorScheme):
'var_invisible': (0.6, 0.4, 0.4, False)
}

def __init__(self):
self.rng = random.Random()

def __getitem__(self, name):
return self.colors[name]

def get_random(self, seed, highlight):
self.rng.seed(seed)

def _random_color(self, highlight):
hue = self.rng.uniform(0.05,0.7)
# if hue < 0:
# hue = hue + 1
sat = 1. if highlight else 1.
val = 0.8 #if highlight else 0.5
sat = 1.0
val = 0.8
bold = highlight

return hue, sat, val, bold


class darkbg3(ColorScheme):
class darkbg3(HslScheme):
# Hue, Sat, Val, Bold
colors = {'exception_type': (0., 1., 0.8, True),
'exception_msg': (0., 1., 0.8, True),
Expand All @@ -103,26 +156,16 @@ class darkbg3(ColorScheme):
'var_invisible': (0.6, 0.4, 0.4, False)
}

def __init__(self):
self.rng = random.Random()

def __getitem__(self, name):
return self.colors[name]

def get_random(self, seed, highlight):
self.rng.seed(seed)

def _random_color(self, highlight):
hue = self.rng.uniform(0.05,0.7)
# if hue < 0:
# hue = hue + 1
sat = 1. if highlight else 1.
sat = 1.0
val = 0.8 if highlight else 0.5
bold = highlight

return hue, sat, val, bold


class lightbg(ColorScheme):
class lightbg(HslScheme):
# Hue, Sat, Val, Bold
colors = {'exception_type': (0.0, 1., 0.6, False),
'exception_msg': (0.0, 1., 0.6, True),
Expand All @@ -139,26 +182,16 @@ class lightbg(ColorScheme):
'var_invisible': (0.6, 0.4, 0.2, False)
}

def __init__(self):
self.rng = random.Random()

def __getitem__(self, name):
return self.colors[name]

def get_random(self, seed, highlight):
self.rng.seed(seed)

def _random_color(self, highlight):
hue = self.rng.uniform(0.05, 0.7)
# if hue < 0:
# hue = hue + 1
sat = 1.
val = 0.5 #0.5 #0.6 if highlight else 0.2
sat = 1.0
val = 0.5
bold = highlight

return hue, sat, val, bold


class lightbg2(ColorScheme):
class lightbg2(HslScheme):
# Hue, Sat, Val, Bold
colors = {'exception_type': (0.0, 1., 0.6, False),
'exception_msg': (0.0, 1., 0.6, True),
Expand All @@ -176,25 +209,15 @@ class lightbg2(ColorScheme):
'var_invisible': (0.6, 0.4, 0.2, False)
}

def __init__(self):
self.rng = random.Random()

def __getitem__(self, name):
return self.colors[name]

def get_random(self, seed, highlight):
self.rng.seed(seed)

def _random_color(self, highlight):
hue = self.rng.uniform(0.05, 0.7)
# if hue < 0:
# hue = hue + 1
sat = 1.
sat = 1.0
val = 0.5
bold = True

return hue, sat, val, bold

class lightbg3(ColorScheme):
class lightbg3(HslScheme):
# Hue, Sat, Val, Bold
colors = {'exception_type': (0.0, 1., 0.7, False),
'exception_msg': (0.0, 1., 0.7, True),
Expand All @@ -212,19 +235,9 @@ class lightbg3(ColorScheme):
'var_invisible': (0.6, 0.4, 0.2, False)
}

def __init__(self):
self.rng = random.Random()

def __getitem__(self, name):
return self.colors[name]

def get_random(self, seed, highlight):
self.rng.seed(seed)

def _random_color(self, highlight):
hue = self.rng.uniform(0.05, 0.7)
# if hue < 0:
# hue = hue + 1
sat = 1.
sat = 1.0
val = 0.5
bold = True

Expand All @@ -236,15 +249,31 @@ def get_random(self, seed, highlight):


if __name__ == '__main__':
scheme = darkbg3()
for attr in [
'exception_type',
'exception_msg',
'highlight',
'header',
'lineno',
'arrow_lineno',
'dots',
'source_bold',
'source_default',
'source_comment',
'var_invisible',
]:
print(scheme[attr] % attr)
exit()
import numpy as np
from utils import get_ansi_tpl
hsl_scheme = HslScheme()

for hue in np.arange(0,1.05,0.05):
print('\n\nhue %.2f\nsat' % hue)
for sat in np.arange(0,1.05,0.05):
print('%.2f ' % sat, end='')
for val in np.arange(0,1.05,0.05):
tpl = get_ansi_tpl(hue, sat, val)
tpl = hsl_scheme._ansi_tpl(hue, sat, val)
# number = " (%.1f %.1f %.1f)" % (hue, sat, val)
number = ' %.2f' % val
print(tpl % number, end='')
Expand Down
27 changes: 9 additions & 18 deletions stackprinter/formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,12 @@

import stackprinter.extraction as ex
import stackprinter.colorschemes as colorschemes
from stackprinter.utils import match, get_ansi_tpl
from stackprinter.utils import match
from stackprinter.frame_formatting import FrameFormatter, ColorfulFrameFormatter


def get_formatter(style, **kwargs):
if style in ['plaintext', 'plain']:
return FrameFormatter(**kwargs)
else:
return ColorfulFrameFormatter(style, **kwargs)
return ColorfulFrameFormatter(style, **kwargs)


def format_summary(frames, style='plaintext', source_lines=1, reverse=False,
Expand Down Expand Up @@ -155,12 +152,9 @@ def format_exc_info(etype, evalue, tb, style='plaintext', add_summary='auto',
suppressed_vars=suppressed_vars,
**kwargs)

if style == 'plaintext':
msg += chain_hint
else:
sc = getattr(colorschemes, style)
clr = get_ansi_tpl(*sc.colors['exception_type'])
msg += clr % chain_hint
sc = getattr(colorschemes, style)()
clr = sc['exception_type']
msg += clr % chain_hint

# Now, actually do some formatting:
parts = []
Expand Down Expand Up @@ -226,15 +220,12 @@ def format_exception_message(etype, evalue, tb=None, style='plaintext'):
if val_str:
type_str += ": "

if style == 'plaintext':
return type_str + val_str
else:
sc = getattr(colorschemes, style)
sc = getattr(colorschemes, style)()

clr_head = get_ansi_tpl(*sc.colors['exception_type'])
clr_msg = get_ansi_tpl(*sc.colors['exception_msg'])
clr_head = sc['exception_type']
clr_msg = sc['exception_msg']

return clr_head % type_str + clr_msg % val_str
return clr_head % type_str + clr_msg % val_str


def _walk_traceback(tb):
Expand Down
Loading