mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-02-26 19:34:41 +00:00
127 lines
4.7 KiB
Python
127 lines
4.7 KiB
Python
"""
|
|
Utilities for turning objects into human-readable strings.
|
|
|
|
This module has been ported to Python 3.
|
|
"""
|
|
|
|
from __future__ import division
|
|
from __future__ import absolute_import
|
|
from __future__ import print_function
|
|
from __future__ import unicode_literals
|
|
|
|
from future.utils import PY2
|
|
if PY2:
|
|
from builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, int, list, object, range, str, max, min # noqa: F401
|
|
|
|
import os
|
|
from reprlib import Repr
|
|
|
|
class BetterRepr(Repr, object):
|
|
def __init__(self):
|
|
Repr.__init__(self)
|
|
|
|
# Note: These levels can get adjusted dynamically! My goal is to get more info when printing important debug stuff like exceptions and stack traces and less info when logging normal events. --Zooko 2000-10-14
|
|
self.maxlevel = 6
|
|
self.maxdict = 6
|
|
self.maxlist = 6
|
|
self.maxtuple = 6
|
|
self.maxstring = 300
|
|
self.maxother = 300
|
|
|
|
def repr_function(self, obj, level):
|
|
if hasattr(obj, '__code__'):
|
|
return '<' + obj.__name__ + '() at ' + os.path.basename(obj.__code__.co_filename) + ':' + str(obj.__code__.co_firstlineno) + '>'
|
|
else:
|
|
return '<' + obj.__name__ + '() at (builtin)'
|
|
|
|
def repr_instance_method(self, obj, level):
|
|
if hasattr(obj, '__code__'):
|
|
return '<' + obj.__self__.__class__.__name__ + '.' + obj.__func__.__name__ + '() at ' + os.path.basename(obj.__func__.__code__.co_filename) + ':' + str(obj.__func__.__code__.co_firstlineno) + '>'
|
|
else:
|
|
return '<' + obj.__self__.__class__.__name__ + '.' + obj.__func__.__name__ + '() at (builtin)'
|
|
|
|
def repr_long(self, obj, level):
|
|
s = repr(obj) # XXX Hope this isn't too slow...
|
|
if len(s) > self.maxlong:
|
|
i = max(0, (self.maxlong-3) // 2)
|
|
j = max(0, self.maxlong-3-i)
|
|
s = s[:i] + '...' + s[len(s)-j:]
|
|
if s[-1] == 'L':
|
|
return s[:-1]
|
|
return s
|
|
|
|
def repr_instance(self, obj, level):
|
|
"""
|
|
If it is an instance of Exception, format it nicely (trying to emulate
|
|
the format that you see when an exception is actually raised, plus
|
|
bracketing '<''s). If it is an instance of dict call self.repr_dict()
|
|
on it. If it is an instance of list call self.repr_list() on it. Else
|
|
call Repr.repr_instance().
|
|
"""
|
|
if isinstance(obj, Exception):
|
|
# Don't cut down exception strings so much.
|
|
tms = self.maxstring
|
|
self.maxstring = max(512, tms * 4)
|
|
tml = self.maxlist
|
|
self.maxlist = max(12, tml * 4)
|
|
try:
|
|
if hasattr(obj, 'args'):
|
|
if len(obj.args) == 1:
|
|
return '<' + obj.__class__.__name__ + ': ' + self.repr1(obj.args[0], level-1) + '>'
|
|
else:
|
|
return '<' + obj.__class__.__name__ + ': ' + self.repr1(obj.args, level-1) + '>'
|
|
else:
|
|
return '<' + obj.__class__.__name__ + '>'
|
|
finally:
|
|
self.maxstring = tms
|
|
self.maxlist = tml
|
|
|
|
if isinstance(obj, dict):
|
|
return self.repr_dict(obj, level)
|
|
|
|
if isinstance(obj, list):
|
|
return self.repr_list(obj, level)
|
|
|
|
return Repr.repr_instance(self, obj, level)
|
|
|
|
def repr_list(self, obj, level):
|
|
"""
|
|
copied from standard repr.py and fixed to work on multithreadedly mutating lists.
|
|
"""
|
|
if level <= 0: return '[...]'
|
|
n = len(obj)
|
|
myl = obj[:min(n, self.maxlist)]
|
|
s = ''
|
|
for item in myl:
|
|
entry = self.repr1(item, level-1)
|
|
if s: s = s + ', '
|
|
s = s + entry
|
|
if n > self.maxlist: s = s + ', ...'
|
|
return '[' + s + ']'
|
|
|
|
def repr_dict(self, obj, level):
|
|
"""
|
|
copied from standard repr.py and fixed to work on multithreadedly mutating dicts.
|
|
"""
|
|
if level <= 0: return '{...}'
|
|
s = ''
|
|
n = len(obj)
|
|
items = list(obj.items())[:min(n, self.maxdict)]
|
|
items.sort()
|
|
for key, val in items:
|
|
entry = self.repr1(key, level-1) + ':' + self.repr1(val, level-1)
|
|
if s: s = s + ', '
|
|
s = s + entry
|
|
if n > self.maxdict: s = s + ', ...'
|
|
return '{' + s + '}'
|
|
|
|
# This object can be changed by other code updating this module's "brepr"
|
|
# variables. This is so that (a) code can use humanreadable with
|
|
# "from humanreadable import hr; hr(mything)", and (b) code can override
|
|
# humanreadable to provide application-specific human readable output
|
|
# (e.g. libbase32's base32id.AbbrevRepr).
|
|
brepr = BetterRepr()
|
|
|
|
def hr(x):
|
|
return brepr.repr(x)
|