Various functions to debug Python internals

sage.cpython.debug.getattr_debug(obj, name, default='_no_default')

A re-implementation of getattr() with lots of debugging info.

This will correctly use __getattr__ if needed. On the other hand, it assumes a generic (not overridden) implementation of __getattribute__. Note that Cython implements __getattr__ for a cdef class using __getattribute__, so this will not detect a __getattr__ in that case.

INPUT:

  • obj – the object whose attribute is requested
  • name – (string) the name of the attribute
  • default – default value to return if attribute was not found

EXAMPLES:

sage: _ = getattr_debug(list, "reverse")
getattr_debug(obj=<type 'list'>, name='reverse'):
  type(obj) = <type 'type'>
  object has __dict__ slot (<type 'dict'>)
  did not find 'reverse' in MRO classes
  found 'reverse' in object __dict__
  returning <method 'reverse' of 'list' objects> (<type 'method_descriptor'>)
sage: _ = getattr_debug([], "reverse")
getattr_debug(obj=[], name='reverse'):
  type(obj) = <type 'list'>
  object does not have __dict__ slot
  found 'reverse' in dict of <type 'list'>
  got <method 'reverse' of 'list' objects> (<type 'method_descriptor'>)
  attribute is ordinary descriptor (has __get__)
  calling __get__()
  returning <built-in method reverse of list object at 0x... (<type 'builtin_function_or_method'>)
sage: _ = getattr_debug([], "__doc__")
getattr_debug(obj=[], name='__doc__'):
  type(obj) = <type 'list'>
  object does not have __dict__ slot
  found '__doc__' in dict of <type 'list'>
  got "list() -> new empty list\nlist(iterable) -> ne~~~ (<type 'str'>)
  returning "list() -> new empty list\nlist(iterable) -> ne~~~ (<type 'str'>)
sage: _ = getattr_debug(gp(1), "log")
getattr_debug(obj=1, name='log'):
  type(obj) = <class 'sage.interfaces.gp.GpElement'>
  object has __dict__ slot (<type 'dict'>)
  did not find 'log' in MRO classes
  object __dict__ does not have 'log'
  calling __getattr__()
  returning log (<class 'sage.interfaces.expect.FunctionElement'>)
sage: from ipywidgets import IntSlider
sage: _ = getattr_debug(IntSlider(), "value")
getattr_debug(obj=IntSlider(value=0), name='value'):
  type(obj) = <class 'ipywidgets.widgets.widget_int.IntSlider'>
  object has __dict__ slot (<type 'dict'>)
  found 'value' in dict of <class 'ipywidgets.widgets.widget_int._Int'>
  got <traitlets.traitlets.CInt object at ... (<class 'traitlets.traitlets.CInt'>)
  attribute is data descriptor (has __get__ and __set__)
  ignoring __dict__ because we have a data descriptor
  calling __get__()
  returning 0 (<type 'int'>)
sage: _ = getattr_debug(1, "foo")
Traceback (most recent call last):
...
AttributeError: 'sage.rings.integer.Integer' object has no attribute 'foo'
sage: _ = getattr_debug(1, "foo", "xyz")
getattr_debug(obj=1, name='foo'):
  type(obj) = <type 'sage.rings.integer.Integer'>
  object does not have __dict__ slot
  did not find 'foo' in MRO classes
  class does not have __getattr__
  attribute not found
  returning default 'xyz'
sage.cpython.debug.shortrepr(obj, max=50)

Return repr(obj) bounded to max characters. If the string is too long, it is truncated and ~~~ is added to the end.

EXAMPLES:

sage: from sage.cpython.debug import shortrepr
sage: print(shortrepr("Hello world!"))
'Hello world!'
sage: print(shortrepr("Hello world!" * 4))
'Hello world!Hello world!Hello world!Hello world!'
sage: print(shortrepr("Hello world!" * 5))
'Hello world!Hello world!Hello world!Hello worl~~~