Restore better_exchook2.py and colorama.py to pre-Black state

These files are based on published packages.

better_exchook2.py was derived from better_exchook.py in:
https://pypi.org/project/better_exchook/

colorama.py was derived from win32.py in:
https://pypi.org/project/colorama/

Files modified in:
a92a684a ("Run black on linkcheck/", 2020-05-30)
This commit is contained in:
Chris Mayo 2020-06-03 20:06:36 +01:00
parent b974ec3262
commit 6b3cb18546
3 changed files with 210 additions and 311 deletions

View file

@ -5,14 +5,14 @@
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@ -25,7 +25,7 @@
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# This is a replacement for the standard Python exception handler (sys.excepthook).
# This is a simple replacement for the standard Python exception handler (sys.excepthook).
# In addition to what the standard handler does, it also prints all referenced variables
# (no matter if local, global or builtin) of the code line of each stack frame.
# See below for some examples and some example output.
@ -40,283 +40,201 @@ pykeywords = set(keyword.kwlist)
def parse_py_statement(line):
state = 0
curtoken = ""
spaces = " \t\n"
ops = ".,;:+-*/%&=|(){}[]^<>"
i = 0
def _escape_char(c):
if c == "n":
return "\n"
elif c == "t":
return "\t"
else:
return c
while i < len(line):
c = line[i]
i += 1
if state == 0:
if c in spaces:
pass
elif c in ops:
yield ("op", c)
elif c == "#":
state = 6
elif c == "\"":
state = 1
elif c == "'":
state = 2
else:
curtoken = c
state = 3
elif state == 1: # string via "
if c == "\\":
state = 4
elif c == "\"":
yield ("str", curtoken)
curtoken = ""
state = 0
else:
curtoken += c
elif state == 2: # string via '
if c == "\\":
state = 5
elif c == "'":
yield ("str", curtoken)
curtoken = ""
state = 0
else:
curtoken += c
elif state == 3: # identifier
if c in spaces + ops + "#\"'":
yield ("id", curtoken)
curtoken = ""
state = 0
i -= 1
else:
curtoken += c
elif state == 4: # escape in "
curtoken += _escape_char(c)
state = 1
elif state == 5: # escape in '
curtoken += _escape_char(c)
state = 2
elif state == 6: # comment
curtoken += c
if state == 3:
yield ("id", curtoken)
elif state == 6:
yield ("comment", curtoken)
state = 0
curtoken = ""
spaces = " \t\n"
ops = ".,;:+-*/%&=|(){}[]^<>"
i = 0
def _escape_char(c):
if c == "n": return "\n"
elif c == "t": return "\t"
else: return c
while i < len(line):
c = line[i]
i += 1
if state == 0:
if c in spaces: pass
elif c in ops: yield ("op", c)
elif c == "#": state = 6
elif c == "\"": state = 1
elif c == "'": state = 2
else:
curtoken = c
state = 3
elif state == 1: # string via "
if c == "\\": state = 4
elif c == "\"":
yield ("str", curtoken)
curtoken = ""
state = 0
else: curtoken += c
elif state == 2: # string via '
if c == "\\": state = 5
elif c == "'":
yield ("str", curtoken)
curtoken = ""
state = 0
else: curtoken += c
elif state == 3: # identifier
if c in spaces + ops + "#\"'":
yield ("id", curtoken)
curtoken = ""
state = 0
i -= 1
else: curtoken += c
elif state == 4: # escape in "
curtoken += _escape_char(c)
state = 1
elif state == 5: # escape in '
curtoken += _escape_char(c)
state = 2
elif state == 6: # comment
curtoken += c
if state == 3: yield ("id", curtoken)
elif state == 6: yield ("comment", curtoken)
def grep_full_py_identifiers(tokens):
global pykeywords
tokens = list(tokens)
i = 0
while i < len(tokens):
tokentype, token = tokens[i]
i += 1
if tokentype != "id":
continue
while (
i + 1 < len(tokens)
and tokens[i] == ("op", ".")
and tokens[i + 1][0] == "id"
):
token += "." + tokens[i + 1][1]
i += 2
if token == "":
continue
if token in pykeywords:
continue
if token[0] in ".0123456789":
continue
yield token
def output(s, out=sys.stdout):
print(s, file=out)
global pykeywords
tokens = list(tokens)
i = 0
while i < len(tokens):
tokentype, token = tokens[i]
i += 1
if tokentype != "id": continue
while i+1 < len(tokens) and tokens[i] == ("op", ".") and tokens[i+1][0] == "id":
token += "." + tokens[i+1][1]
i += 2
if token == "": continue
if token in pykeywords: continue
if token[0] in ".0123456789": continue
yield token
def output(s, out=sys.stdout): print(s, file=out)
def output_limit():
return 300
def pp_extra_info(obj, depthlimit=3):
s = []
if hasattr(obj, "__len__"):
try:
if type(obj) in (bytes, str, list, tuple, dict) and len(obj) <= 5:
pass # don't print len in this case
else:
s += ["len = " + str(obj.__len__())]
except Exception:
pass
if depthlimit > 0 and hasattr(obj, "__getitem__"):
try:
if type(obj) in (bytes, str):
pass # doesn't make sense to get subitems here
else:
subobj = obj.__getitem__(0)
extra_info = pp_extra_info(subobj, depthlimit - 1)
if extra_info != "":
s += ["_[0]: {" + extra_info + "}"]
except Exception:
pass
return ", ".join(s)
return 300
def pp_extra_info(obj, depthlimit = 3):
s = []
if hasattr(obj, "__len__"):
try:
if type(obj) in (bytes,str,list,tuple,dict) and len(obj) <= 5:
pass # don't print len in this case
else:
s += ["len = " + str(obj.__len__())]
except: pass
if depthlimit > 0 and hasattr(obj, "__getitem__"):
try:
if type(obj) in (bytes,str):
pass # doesn't make sense to get subitems here
else:
subobj = obj.__getitem__(0)
extra_info = pp_extra_info(subobj, depthlimit - 1)
if extra_info != "":
s += ["_[0]: {" + extra_info + "}"]
except: pass
return ", ".join(s)
def pretty_print(obj):
s = repr(obj)
limit = output_limit()
if len(s) > limit:
s = s[: limit - 3] + "..."
extra_info = pp_extra_info(obj)
if extra_info != "":
s += ", " + extra_info
return s
s = repr(obj)
limit = output_limit()
if len(s) > limit:
s = s[:limit - 3] + "..."
extra_info = pp_extra_info(obj)
if extra_info != "": s += ", " + extra_info
return s
def fallback_findfile(filename):
mods = [
m
for m in sys.modules.values()
if m and hasattr(m, "__file__") and filename in m.__file__
]
if len(mods) == 0:
return None
altfn = mods[0].__file__
if altfn[-4:-1] == ".py":
altfn = altfn[:-1] # *.pyc or whatever
return altfn
mods = [ m for m in sys.modules.values() if m and hasattr(m, "__file__") and filename in m.__file__ ]
if len(mods) == 0: return None
altfn = mods[0].__file__
if altfn[-4:-1] == ".py": altfn = altfn[:-1] # *.pyc or whatever
return altfn
def better_exchook(etype, value, tb, out=sys.stdout):
output('Traceback (most recent call last):', out=out)
allLocals, allGlobals = {}, {}
try:
import linecache
output('Traceback (most recent call last):', out=out)
allLocals,allGlobals = {},{}
try:
import linecache
limit = None
if hasattr(sys, 'tracebacklimit'):
limit = sys.tracebacklimit
n = 0
_tb = tb
def _resolveIdentifier(namespace, id):
obj = namespace[id[0]]
for part in id[1:]:
obj = getattr(obj, part)
return obj
def _trySet(old, prefix, func):
if old is not None: return old
try: return prefix + func()
except KeyError: return old
except Exception as e:
return prefix + "!" + e.__class__.__name__ + ": " + str(e)
while _tb is not None and (limit is None or n < limit):
f = _tb.tb_frame
allLocals.update(f.f_locals)
allGlobals.update(f.f_globals)
lineno = _tb.tb_lineno
co = f.f_code
filename = co.co_filename
name = co.co_name
output(' File "%s", line %d, in %s' % (filename,lineno,name), out=out)
if not os.path.isfile(filename):
altfn = fallback_findfile(filename)
if altfn:
output(" -- couldn't find file, trying this instead: " + altfn, out=out)
filename = altfn
linecache.checkcache(filename)
line = linecache.getline(filename, lineno, f.f_globals)
if line:
line = line.strip()
output(' line: ' + line, out=out)
output(' locals:', out=out)
alreadyPrintedLocals = set()
for tokenstr in grep_full_py_identifiers(parse_py_statement(line)):
splittedtoken = tuple(tokenstr.split("."))
for token in map(lambda i: splittedtoken[0:i], range(1, len(splittedtoken) + 1)):
if token in alreadyPrintedLocals: continue
tokenvalue = None
tokenvalue = _trySet(tokenvalue, "<local> ", lambda: pretty_print(_resolveIdentifier(f.f_locals, token)))
tokenvalue = _trySet(tokenvalue, "<global> ", lambda: pretty_print(_resolveIdentifier(f.f_globals, token)))
tokenvalue = _trySet(tokenvalue, "<builtin> ", lambda: pretty_print(_resolveIdentifier(f.f_builtins, token)))
tokenvalue = tokenvalue or "<not found>"
output(' ' + ".".join(token) + " = " + tokenvalue, out=out)
alreadyPrintedLocals.add(token)
if len(alreadyPrintedLocals) == 0: output(" no locals", out=out)
else:
output(' -- code not available --', out=out)
_tb = _tb.tb_next
n += 1
limit = None
if hasattr(sys, 'tracebacklimit'):
limit = sys.tracebacklimit
n = 0
_tb = tb
def _resolveIdentifier(namespace, id):
obj = namespace[id[0]]
for part in id[1:]:
obj = getattr(obj, part)
return obj
def _trySet(old, prefix, func):
if old is not None:
return old
try:
return prefix + func()
except KeyError:
return old
except Exception as e:
return prefix + "!" + e.__class__.__name__ + ": " + str(e)
while _tb is not None and (limit is None or n < limit):
f = _tb.tb_frame
allLocals.update(f.f_locals)
allGlobals.update(f.f_globals)
lineno = _tb.tb_lineno
co = f.f_code
filename = co.co_filename
name = co.co_name
output(' File "%s", line %d, in %s' % (filename, lineno, name), out=out)
if not os.path.isfile(filename):
altfn = fallback_findfile(filename)
if altfn:
output(
" -- couldn't find file, trying this instead: " + altfn,
out=out,
)
filename = altfn
linecache.checkcache(filename)
line = linecache.getline(filename, lineno, f.f_globals)
if line:
line = line.strip()
output(' line: ' + line, out=out)
output(' locals:', out=out)
alreadyPrintedLocals = set()
for tokenstr in grep_full_py_identifiers(parse_py_statement(line)):
splittedtoken = tuple(tokenstr.split("."))
for token in map(
lambda i: splittedtoken[0:i], range(1, len(splittedtoken) + 1)
):
if token in alreadyPrintedLocals:
continue
tokenvalue = None
tokenvalue = _trySet(
tokenvalue,
"<local> ",
lambda: pretty_print(_resolveIdentifier(f.f_locals, token)),
)
tokenvalue = _trySet(
tokenvalue,
"<global> ",
lambda: pretty_print(
_resolveIdentifier(f.f_globals, token)
),
)
tokenvalue = _trySet(
tokenvalue,
"<builtin> ",
lambda: pretty_print(
_resolveIdentifier(f.f_builtins, token)
),
)
tokenvalue = tokenvalue or "<not found>"
output(' ' + ".".join(token) + " = " + tokenvalue, out=out)
alreadyPrintedLocals.add(token)
if len(alreadyPrintedLocals) == 0:
output(" no locals", out=out)
else:
output(' -- code not available --', out=out)
_tb = _tb.tb_next
n += 1
except Exception:
output("ERROR: cannot get more detailed exception info because:", out=out)
import traceback
for line in traceback.format_exc().split("\n"):
output(" " + line, out=out)
output("simple traceback:", out=out)
traceback.print_tb(tb, None, out)
import types
def _some_str(value):
try:
return str(value)
except Exception:
return '<unprintable %s object>' % type(value).__name__
def _format_final_exc_line(etype, value):
valuestr = _some_str(value)
if value is None or not valuestr:
line = "%s" % etype
else:
line = "%s: %s" % (etype, valuestr)
return line
if (
isinstance(etype, BaseException)
or (hasattr(types, "InstanceType") and isinstance(etype, types.InstanceType))
or etype is None
or type(etype) is str
):
output(_format_final_exc_line(etype, value), out=out)
else:
output(_format_final_exc_line(etype.__name__, value), out=out)
except Exception:
output("ERROR: cannot get more detailed exception info because:", out=out)
import traceback
for l in traceback.format_exc().split("\n"): output(" " + l, out=out)
output("simple traceback:", out=out)
traceback.print_tb(tb, None, out)
import types
def _some_str(value):
try: return str(value)
except: return '<unprintable %s object>' % type(value).__name__
def _format_final_exc_line(etype, value):
valuestr = _some_str(value)
if value is None or not valuestr:
line = "%s" % etype
else:
line = "%s: %s" % (etype, valuestr)
return line
if (isinstance(etype, BaseException) or
(hasattr(types, "InstanceType") and isinstance(etype, types.InstanceType)) or
etype is None or type(etype) is str):
output(_format_final_exc_line(etype, value), out=out)
else:
output(_format_final_exc_line(etype.__name__, value), out=out)
def install():
sys.excepthook = better_exchook
sys.excepthook = better_exchook

View file

@ -26,17 +26,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from ctypes import (
windll,
byref,
Structure,
c_char,
c_short,
c_uint32,
c_ushort,
ArgumentError,
WinError,
)
from ctypes import (windll, byref, Structure, c_char, c_short, c_uint32,
c_ushort, ArgumentError, WinError)
# from winbase.h
STDOUT = -11
@ -52,19 +43,15 @@ WORD = c_ushort
DWORD = c_uint32
TCHAR = c_char
class COORD(Structure):
"""struct in wincon.h"""
_fields_ = [
('X', SHORT),
('Y', SHORT),
]
class SMALL_RECT(Structure):
class SMALL_RECT(Structure):
"""struct in wincon.h."""
_fields_ = [
("Left", SHORT),
("Top", SHORT),
@ -72,10 +59,8 @@ class SMALL_RECT(Structure):
("Bottom", SHORT),
]
class CONSOLE_SCREEN_BUFFER_INFO(Structure):
"""struct in wincon.h."""
_fields_ = [
("dwSize", COORD),
("dwCursorPosition", COORD),
@ -83,29 +68,22 @@ class CONSOLE_SCREEN_BUFFER_INFO(Structure):
("srWindow", SMALL_RECT),
("dwMaximumWindowSize", COORD),
]
def __str__(self):
"""Get string representation of console screen buffer info."""
return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % (
self.dwSize.Y,
self.dwSize.X,
self.dwCursorPosition.Y,
self.dwCursorPosition.X,
self.wAttributes,
self.srWindow.Top,
self.srWindow.Left,
self.srWindow.Bottom,
self.srWindow.Right,
self.dwMaximumWindowSize.Y,
self.dwMaximumWindowSize.X,
self.dwSize.Y, self.dwSize.X
, self.dwCursorPosition.Y, self.dwCursorPosition.X
, self.wAttributes
, self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right
, self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X
)
def GetConsoleScreenBufferInfo(stream_id=STDOUT):
"""Get console screen buffer info object."""
handle = handles[stream_id]
csbi = CONSOLE_SCREEN_BUFFER_INFO()
success = windll.kernel32.GetConsoleScreenBufferInfo(handle, byref(csbi))
success = windll.kernel32.GetConsoleScreenBufferInfo(
handle, byref(csbi))
if not success:
raise WinError()
return csbi
@ -118,18 +96,18 @@ def SetConsoleTextAttribute(stream_id, attrs):
# from wincon.h
BLACK = 0
BLUE = 1
GREEN = 2
CYAN = 3
RED = 4
BLACK = 0
BLUE = 1
GREEN = 2
CYAN = 3
RED = 4
MAGENTA = 5
YELLOW = 6
GREY = 7
YELLOW = 6
GREY = 7
# from wincon.h
NORMAL = 0x00 # dim text, dim background
BRIGHT = 0x08 # bright text, dim background
NORMAL = 0x00 # dim text, dim background
BRIGHT = 0x08 # bright text, dim background
_default_foreground = None
_default_background = None

View file

@ -25,6 +25,9 @@ filename =
extend-exclude =
build/
_LinkChecker_configdata.py
# Derived from published packages
linkcheck/better_exchook2.py
linkcheck/colorama.py
builtins =
_
_n