Inspect Python, Sage, and Cython objects.

This module extends parts of Python’s inspect module to Cython objects.

AUTHORS:

  • originally taken from Fernando Perez’s IPython
  • William Stein (extensive modifications)
  • Nick Alexander (extensions)
  • Nick Alexander (testing)

EXAMPLES:

sage: from sagenb.misc.sageinspect import *

Test introspection of modules defined in Python and Cython files:

Cython modules:

sage: sage_getfile(sage.rings.rational)
'.../rational.pyx'

sage: sage_getdoc(sage.rings.rational).lstrip()
'Rational Numbers...'

sage: sage_getsource(sage.rings.rational)[5:]
'Rational Numbers...'

Python modules:

sage: import sagenb.misc.sageinspect
sage: sage_getfile(sagenb.misc.sageinspect)
'.../sageinspect.py'

sage: print sage_getdoc(sagenb.misc.sageinspect).lstrip()[:40]
Inspect Python, Sage, and Cython objects

sage: sage_getsource(sagenb.misc.sageinspect).lstrip()[5:-1]
'...Inspect Python, Sage, and Cython objects...'

Test introspection of classes defined in Python and Cython files:

Cython classes:

sage: sage_getfile(sage.rings.rational.Rational)
'.../rational.pyx'

sage: sage_getdoc(sage.rings.rational.Rational).lstrip()
'A Rational number...'

sage: sage_getsource(sage.rings.rational.Rational)
'cdef class Rational...'

Python classes:

sage: import sage.misc.attach
sage: sage_getfile(sage.misc.attach.Attach)
'.../attach.py'

sage: sage_getdoc(sage.misc.attach.Attach).lstrip()
'Attach a file to a running instance of Sage...'

sage: sage_getsource(sage.misc.attach.Attach)
'class Attach:...'

Python classes with no docstring, but an __init__ docstring:

sage: class Foo:
...     def __init__(self):
...         'docstring'
...         pass
...
sage: sage_getdoc(Foo)
'docstring\n'

Test introspection of functions defined in Python and Cython files:

Cython functions:

sage: sage_getdef(sage.rings.rational.make_rational, obj_name='mr')
'mr(s)'

sage: sage_getfile(sage.rings.rational.make_rational)
'.../rational.pyx'

sage: sage_getdoc(sage.rings.rational.make_rational).lstrip()
"Make a rational number ..."

sage: sage_getsource(sage.rings.rational.make_rational, True)[4:]
'make_rational(s):...'

Python functions:

sage: sage_getdef(sagenb.misc.sageinspect.sage_getfile, obj_name='sage_getfile')
'sage_getfile(obj)'

sage: sage_getfile(sagenb.misc.sageinspect.sage_getfile)
'.../sageinspect.py'

sage: sage_getdoc(sagenb.misc.sageinspect.sage_getfile).lstrip()
"Get the full file name associated to ``obj`` as a string..."

sage: sage_getsource(sagenb.misc.sageinspect.sage_getfile)[4:]
'sage_getfile(obj):...'

Unfortunately, there is no argspec extractable from builtins:

sage: sage_getdef(''.find, 'find')
'find( [noargspec] )'

sage: sage_getdef(str.find, 'find')
'find( [noargspec] )'
class sagenb.misc.sageinspect.BlockFinder

Provide a tokeneater() method to detect the end of a code block.

This is the Python library’s inspect.BlockFinder modified to recognize Cython definitions.

tokeneater(type, token, srow_scol, erow_ecol, line)
class sagenb.misc.sageinspect.SageArgSpecVisitor

Bases: ast.NodeVisitor

A simple visitor class that walks an abstract-syntax tree (AST) for a Python function’s argspec. It returns the contents of nodes representing the basic Python types: None, booleans, numbers, strings, lists, tuples, and dictionaries. We use this class in _sage_getargspec_from_ast() to extract an argspec from a function’s or method’s source code.

EXAMPLES:

sage: import ast, sagenb.misc.sageinspect as sms
sage: visitor = sms.SageArgSpecVisitor()
sage: visitor.visit(ast.parse('[1,2,3]').body[0].value)
[1, 2, 3]
sage: visitor.visit(ast.parse("{'a':('e',2,[None,({False:True},'pi')]), 37.0:'temp'}").body[0].value)
{'a': ('e', 2, [None, ({False: True}, 'pi')]), 37.0: 'temp'}
sage: v = ast.parse("jc = ['veni', 'vidi', 'vici']").body[0]; v
<_ast.Assign object at ...>
sage: [x for x in dir(v) if not x.startswith('__')]
['_attributes', '_fields', 'col_offset', 'lineno', 'targets', 'value']
sage: visitor.visit(v.targets[0])
'jc'
sage: visitor.visit(v.value)
['veni', 'vidi', 'vici']
visit_Dict(node)

Visit a Python AST ast.Dict node.

INPUT:

  • node - the node instance to visit

OUTPUT:

  • the dictionary the node represents

EXAMPLES:

sage: import ast, sagenb.misc.sageinspect as sms
sage: visitor = sms.SageArgSpecVisitor()
sage: vis = lambda x: visitor.visit_Dict(ast.parse(x).body[0].value)
sage: [vis(d) for d in ['{}', "{1:one, 'two':2, other:bother}"]]
[{}, {1: 'one', 'other': 'bother', 'two': 2}]
visit_List(node)

Visit a Python AST ast.List node.

INPUT:

  • node - the node instance to visit

OUTPUT:

  • the list the node represents

EXAMPLES:

sage: import ast, sagenb.misc.sageinspect as sms
sage: visitor = sms.SageArgSpecVisitor()
sage: vis = lambda x: visitor.visit_List(ast.parse(x).body[0].value)
sage: [vis(l) for l in ['[]', "['s', 't', 'u']", '[[e], [], [pi]]']]
[[], ['s', 't', 'u'], [['e'], [], ['pi']]]
visit_Name(node)

Visit a Python AST ast.Name node.

INPUT:

  • node - the node instance to visit

OUTPUT:

  • None, True, False, or the node‘s name as a string.

EXAMPLES:

sage: import ast, sagenb.misc.sageinspect as sms
sage: visitor = sms.SageArgSpecVisitor()
sage: vis = lambda x: visitor.visit_Name(ast.parse(x).body[0].value)
sage: [vis(n) for n in ['True', 'False', 'None', 'foo', 'bar']]
[True, False, None, 'foo', 'bar']
sage: [type(vis(n)) for n in ['True', 'False', 'None', 'foo', 'bar']]
[<type 'bool'>, <type 'bool'>, <type 'NoneType'>, <type 'str'>, <type 'str'>]
visit_Num(node)

Visit a Python AST ast.Num node.

INPUT:

  • node - the node instance to visit

OUTPUT:

  • the number the node represents

EXAMPLES:

sage: import ast, sagenb.misc.sageinspect as sms
sage: visitor = sms.SageArgSpecVisitor()
sage: vis = lambda x: visitor.visit_Num(ast.parse(x).body[0].value)
sage: [vis(n) for n in ['123', '0.0', str(-pi.n())]]
[123, 0.0, -3.14159265358979]
visit_Str(node)

Visit a Python AST ast.Str node.

INPUT:

  • node - the node instance to visit

OUTPUT:

  • the string the node represents

EXAMPLES:

sage: import ast, sagenb.misc.sageinspect as sms
sage: visitor = sms.SageArgSpecVisitor()
sage: vis = lambda x: visitor.visit_Str(ast.parse(x).body[0].value)
sage: [vis(s) for s in ['"abstract"', "u'syntax'", '''r"tr\ee"''']]
['abstract', u'syntax', 'tr\\ee']
visit_Tuple(node)

Visit a Python AST ast.Tuple node.

INPUT:

  • node - the node instance to visit

OUTPUT:

  • the tuple the node represents

EXAMPLES:

sage: import ast, sagenb.misc.sageinspect as sms
sage: visitor = sms.SageArgSpecVisitor()
sage: vis = lambda x: visitor.visit_Tuple(ast.parse(x).body[0].value)
sage: [vis(t) for t in ['()', '(x,y)', '("Au", "Al", "Cu")']]
[(), ('x', 'y'), ('Au', 'Al', 'Cu')]
sagenb.misc.sageinspect.isclassinstance(obj)

Checks if argument is instance of non built-in class

INPUT: obj - object

EXAMPLES:

sage: from sagenb.misc.sageinspect import isclassinstance
sage: isclassinstance(int)
False
sage: isclassinstance(FreeModule)
True
sage: isclassinstance(SteenrodAlgebra)
True
sage: class myclass: pass
sage: isclassinstance(myclass)
False
sage: class mymetaclass(type): pass
sage: class myclass2:
...       __metaclass__ = mymetaclass
sage: isclassinstance(myclass2)
False
sagenb.misc.sageinspect.sage_getargspec(obj)

Return the names and default values of a function’s arguments.

INPUT: obj, a function

OUTPUT: A tuple of four things is returned: (args, varargs, varkw, defaults). args is a list of the argument names (it may contain nested lists). varargs and varkw are the names of the * and ** arguments or None. defaults is an n-tuple of the default values of the last n arguments.

EXAMPLES:

sage: from sagenb.misc.sageinspect import sage_getargspec
sage: sage_getargspec(identity_matrix)
(['ring', 'n', 'sparse'], None, None, (0, False))
sage: sage_getargspec(Poset)
(['data', 'element_labels', 'cover_relations'], None, None, (None, None, False))
sage: sage_getargspec(factor)
(['n', 'proof', 'int_', 'algorithm', 'verbose'],
 None,
 'kwds',
 (None, False, 'pari', 0))

AUTHORS:

  • William Stein: a modified version of inspect.getargspec from the Python Standard Library, which was taken from IPython for use in Sage.
  • Extensions by Nick Alexander
sagenb.misc.sageinspect.sage_getdef(obj, obj_name='')

Return the definition header for any callable object.

INPUT:

  • obj - function
  • obj_name - string (optional, default ‘’)

obj_name is prepended to the output.

EXAMPLES:

sage: from sagenb.misc.sageinspect import sage_getdef
sage: sage_getdef(identity_matrix)
'(ring, n=0, sparse=False)'
sage: sage_getdef(identity_matrix, 'identity_matrix')
'identity_matrix(ring, n=0, sparse=False)'

Check that trac ticket #6848 has been fixed:

sage: sage_getdef(RDF.random_element)
'(min=-1, max=1)'

If an exception is generated, None is returned instead and the exception is suppressed.

AUTHORS:

  • William Stein
  • extensions by Nick Alexander
sagenb.misc.sageinspect.sage_getdoc(obj, obj_name='', embedded_override=False)

Return the docstring associated to obj as a string.

INPUT: obj, a function, module, etc.: something with a docstring.

If obj is a Cython object with an embedded position in its docstring, the embedded position is stripped.

If optional argument embedded_override is False (its default value), then the string is formatted according to the value of EMBEDDED_MODE. If this argument is True, then it is formatted as if EMBEDDED_MODE were True.

EXAMPLES:

sage: from sagenb.misc.sageinspect import sage_getdoc
sage: sage_getdoc(identity_matrix)[3:39]
'Return the n x n identity matrix ove'

AUTHORS:

  • William Stein
  • extensions by Nick Alexander
sagenb.misc.sageinspect.sage_getfile(obj)

Get the full file name associated to obj as a string.

INPUT: obj, a Sage object, module, etc.

EXAMPLES:

sage: from sagenb.misc.sageinspect import sage_getfile
sage: sage_getfile(sage.rings.rational)[-23:]
'sage/rings/rational.pyx'
sage: sage_getfile(Sq)[-41:]
'sage/algebras/steenrod_algebra_element.py'

AUTHOR: - Nick Alexander

sagenb.misc.sageinspect.sage_getsource(obj, is_binary=False)

Return the source code associated to obj as a string, or None.

INPUT:

  • obj - function, etc.
  • is_binary - boolean, ignored

EXAMPLES:

sage: from sagenb.misc.sageinspect import sage_getsource
sage: sage_getsource(identity_matrix, True)[4:45]
'identity_matrix(ring, n=0, sparse=False):'
sage: sage_getsource(identity_matrix, False)[4:45]
'identity_matrix(ring, n=0, sparse=False):'

AUTHORS:

  • William Stein
  • extensions by Nick Alexander
sagenb.misc.sageinspect.sage_getsourcelines(obj, is_binary=False)

Return a pair ([source_lines], starting line number) of the source code associated to obj, or None.

INPUT:

  • obj - function, etc.
  • is_binary - boolean, ignored

OUTPUT: (source_lines, lineno) or None: source_lines is a list of strings, and lineno is an integer.

At this time we ignore is_binary in favour of a ‘do our best’ strategy.

EXAMPLES:

sage: from sagenb.misc.sageinspect import sage_getsourcelines
sage: sage_getsourcelines(matrix, True)[1]
34
sage: sage_getsourcelines(matrix, False)[0][0][4:]
'matrix(*args, **kwds):\n'

AUTHORS:

  • William Stein
  • Extensions by Nick Alexander
sagenb.misc.sageinspect.sage_getvariablename(obj, omit_underscore_names=True)

Attempt to get the name of a Sage object.

INPUT:

  • obj - an object
  • omit_underscore_names (optional, default True)

If the user has assigned an object obj to a variable name, then return that variable name. If several variables point to obj, return a list of those names. If omit_underscore_names is True (the default) then omit names starting with an underscore “_”.

This is a modified version of code taken from http://pythonic.pocoo.org/2009/5/30/finding-objects-names, written by Georg Brandl.

EXAMPLES:

sage: from sagenb.misc.sageinspect import sage_getvariablename
sage: A = random_matrix(ZZ, 100)
sage: sage_getvariablename(A)
'A'
sage: B = A
sage: sage_getvariablename(A)
['A', 'B']

If an object is not assigned to a variable, an empty list is returned:

sage: sage_getvariablename(random_matrix(ZZ, 60))
[]

Previous topic

Sage Notebook Introspection

Next topic

Process docstrings with Sphinx

This Page