use better color detection methods and add color support on windows

Makes color detection a little more intuitive and adds proper Windows support via colorama (only installed on Windows).
This commit is contained in:
Josh 2017-03-22 18:41:02 -07:00 committed by GitHub
parent 222d871323
commit 87413759cc
4 changed files with 84 additions and 8 deletions

View File

@ -22,13 +22,13 @@ import re
import sys
import traceback
from better_exceptions.color import STREAM, SUPPORTS_COLOR
def isast(v):
return inspect.isclass(v) and issubclass(v, ast.AST)
NOCOLOR = not os.isatty(2) or os.name == 'nt' or os.getenv('TERM', '')[:5] != 'xterm'
ENCODING = locale.getpreferredencoding()
PIPE_CHAR = u'\u2502'
@ -52,7 +52,7 @@ THEME = {
'keyword': lambda s: '\x1b[33;1m{}\x1b[m'.format(s),
'builtin': lambda s: '\x1b[35;1m{}\x1b[m'.format(s),
'literal': lambda s: '\x1b[31m{}\x1b[m'.format(s),
'inspect': lambda s: s if NOCOLOR else u'\x1b[36m{}\x1b[m'.format(s),
'inspect': lambda s: s if not SUPPORTS_COLOR else u'\x1b[36m{}\x1b[m'.format(s),
}
MAX_LENGTH = 128
@ -66,7 +66,7 @@ def colorize_comment(source):
def colorize_tree(tree, source):
if NOCOLOR:
if not SUPPORTS_COLOR:
# quick fail
return source
@ -193,13 +193,13 @@ def format_traceback(tb=None):
return ''.join(lines), final_source
def write_stderr(data):
def write_stream(data):
data = data.encode(ENCODING)
if sys.version_info[0] < 3:
sys.stderr.write(data)
STREAM.write(data)
else:
sys.stderr.buffer.write(data)
STREAM.buffer.write(data)
def excepthook(exc, value, tb):
@ -210,7 +210,7 @@ def excepthook(exc, value, tb):
title = traceback.format_exception_only(exc, value)
full_trace = u'Traceback (most recent call last):\n{}{}\n'.format(formatted, title[0].strip())
write_stderr(full_trace)
write_stream(full_trace)
sys.excepthook = excepthook

View File

@ -0,0 +1,70 @@
"""Checks if the current terminal supports colors.
Also specifies the stream to write to. On Windows, this is a wrapped
stream.
"""
import errno
import os
import struct
import sys
STREAM = sys.stderr
SUPPORTS_COLOR = False
def get_terminfo_file():
term = os.getenv('TERM', None)
if term is None:
return None
terminfo_path = os.path.join('/usr/share/terminfo', ('%0.2X' % ord(term[0])), term)
try:
f = open(terminfo_path, 'rb')
except IOError as e:
if e.errno != errno.ENOENT:
raise
terminfo_path = os.path.join('/usr/share/terminfo', term[0], term)
try:
f = open(terminfo_path, 'rb')
except IOError as e:
if e.errno != errno.ENOENT:
raise
return None
return f
if os.name == 'nt':
from colorama import init as init_colorama, AnsiToWin32
init_colorama(wrap=False)
STREAM = AnsiToWin32(sys.stderr).stream
SUPPORTS_COLOR = True
else:
if os.getenv('FORCE_COLOR', None) == '1':
SUPPORTS_COLOR = True
else:
f = get_terminfo_file()
if f is not None:
with f:
# f is a valid terminfo; seek and read!
magic_number = struct.unpack('<h', f.read(2))[0]
if magic_number == 0x11A:
# the opened terminfo file is valid.
offset = 2 + 10 # magic number + size section (the next thing we read from)
offset += struct.unpack('<h', f.read(2))[0] # skip over names section
offset += struct.unpack('<h', f.read(2))[0] # skip over bool section
offset += offset % 2 # align to short boundary
offset += 13 * 2 # maxColors is the 13th numeric value
f.seek(offset)
max_colors = struct.unpack('<h', f.read(2))[0]
if max_colors >= 8:
SUPPORTS_COLOR = True

View File

@ -13,4 +13,7 @@ setup(
download_url = 'https://github.com/qix-/better-exceptions/archive/{}.tar.gz'.format(VERSION),
keywords = ['pretty', 'better', 'exceptions', 'exception', 'error', 'local', 'debug', 'debugging', 'locals'],
classifiers = [],
extras_require = {
':sys_platform=="win32"': ['colorama']
}
)

3
test_color.py Normal file
View File

@ -0,0 +1,3 @@
from __future__ import print_function
from better_exceptions import color
print(color.SUPPORTS_COLOR)