import dispatch
import types
import inspect
import os
import textwrap
import itertools
from cStringIO import StringIO
import traceback
from webhelpers.util import html_escape
import simplejson
from paste.exceptions.formatter import str2html
py_doc_base = 'http://python.org/doc/current/lib/module-%s.html'
stdlib_dir = os.path.dirname(inspect.__file__)
@dispatch.generic()
def html_repr(obj, context, verbosity, interactive):
"""Return the HTML representation of the object
verbosity is an integer:
0:
very brief (like repr(), but maybe shorter)
1:
normal, but not excessive
2:
pretty verbose/complete
3:
complete, maybe recursively complete
interactive is an boolean
"""
pass
obj_memory = {}
obj_counter = itertools.count()
@html_repr.when("isinstance(obj, object)")
def html_repr_object(obj, context, verbosity, interactive):
if hasattr(obj, '__html_repr__'):
return obj.__html_repr__(verbosity)
try:
concrete_repr = obj.__class__.__repr__
except AttributeError:
concrete_repr = None
if concrete_repr is object.__repr__:
# The default repr, boo!
ob_id = id(obj)
if ob_id in obj_memory:
small_id = obj_memory[ob_id]
else:
small_id = obj_memory[ob_id] = obj_counter.next()
class_name = obj.__class__.__name__
if obj.__class__.__module__ != '__builtin__':
class_name = obj.__class__.__module__ + '.' + class_name
return '''
<%s object
%s>''' % (class_name,
obj.__class__.__name__,
small_id)
return '%s' % html_escape(repr(obj))
@html_repr.when("isinstance(obj, (list, tuple))")
def html_repr_list(obj, context, verbosity, interactive):
if isinstance(obj, list):
sep = '[]'
else:
sep = '()'
content = ''.join([
' %s,
\n' % html_repr(item, context, verbosity-1, interactive)
for item in obj])
return '%s: %s
\n%s%s' % (
type(obj).__name__, sep[0], content, sep[1])
@html_repr.when("isinstance(obj, types.FunctionType)")
def html_repr_func(obj, context, verbosity, interactive):
args = inspect.formatargspec(
*inspect.getargspec(obj))[1:-1]
try:
body = inspect.getsource(obj)
body = ''.join(body.splitlines(True)[1:])
body = textwrap.dedent(body)
except IOError:
if getattr(obj, 'body', None):
body = obj.body
else:
# cannot get source code :(
body = '(code not found)'
name = obj.func_name
obj_id = context.get_id()
uri = context.get_http_callback(obj, _html_set_func)
body = textwrap.dedent(body)
body = str2html(body)
body = '
%s '
'from standard library'
% (obj.__name__,
py_doc_base % obj.__name__))
return (
'Module %s '
'in %s'
% (obj.__name__, obj.__file__))
@html_repr.when("isinstance(obj, basestring)")
def html_repr_string(obj, context, verbosity, interactive):
r = repr(obj)
if len(r) < 50:
return '%s' % html_escape(r)
expand_id = context.get_id()
callback = context.get_js_callback(
obj, _html_repr_string_long, insert_into=expand_id)
return (
'' % expand_id
+ r[:40]
+ '...' % (html_escape(callback), len(r))
+ r[-5:]
+ '')
def _html_repr_string_long(obj, context):
return html_escape(repr(obj))
@html_repr.when("isinstance(obj, (types.ClassType, type))")
def html_repr_class(obj, context, verbosity, interactive):
cls_name = obj.__name__
bases = obj.__bases__
if bases:
bases = ', '.join([c.__name__ for c in bases])
bases = '(%s)' % bases
else:
bases = ''
attrs = {}
methods = {}
special = {}
for name, value in obj.__dict__.items():
if name in ['__doc__', '__module__', '__builtin__']:
special[name] = value
continue
if isinstance(value, types.FunctionType):
methods[name] = value
else:
attrs[name] = value
if special.get('__doc__'):
doc = html_repr(special['__doc__'], context)
doc = '%s = %s'
% (html_escape(name), html_repr(value, context, verbosity-1))
for name, value in attrs])
methods = sorted(methods.items())
methods = 'pass'
else:
extra = ''
return (
'class %(name)s%(bases)s:'
'\n' '%(doc)s %(attrs)s %(methods)s %(extra)s\n' '\n' % dict(name=cls_name, bases=bases, doc=doc or '', extra=extra, attrs=attrs, methods=methods))