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)
  • Simon King (some extension for Cython, generalisation of SageArgSpecVisitor)

EXAMPLES:

sage: from sage.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: sage_getfile(sage.misc.sageinspect)
'.../sageinspect.py'

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

sage: sage_getsource(sage.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: sage_getfile(BlockFinder)
'.../sage/misc/sageinspect.py'

sage: sage_getdoc(BlockFinder).lstrip()
'Provide a tokeneater() method to detect the...'

sage: sage_getsource(BlockFinder)
'class BlockFinder:...'

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)[4:]
'make_rational(s):...'

Python functions:

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

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

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

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

Unfortunately, no argspec is extractable from builtins. Hence, we use a generic argspec:

sage: sage_getdef(''.find, 'find')
'find(*args, **kwds)'

sage: sage_getdef(str.find, 'find')
'find(*args, **kwds)'

By trac ticket #9976 and trac ticket #14017, introspection also works for interactively defined Cython code, and with rather tricky argument lines:

sage: cython('def foo(unsigned int x=1, a=\')"\', b={not (2+1==3):\'bar\'}, *args, **kwds): return')
sage: print(sage_getsource(foo))
def foo(unsigned int x=1, a=')"', b={not (2+1==3):'bar'}, *args, **kwds): return
sage: sage_getargspec(foo)
ArgSpec(args=['x', 'a', 'b'], varargs='args', keywords='kwds', defaults=(1, ')"', {False: 'bar'}))
class sage.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 sage.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, sage.misc.sageinspect as sms
sage: visitor = sms.SageArgSpecVisitor()
sage: visitor.visit(ast.parse('[1,2,3]').body[0].value)
[1, 2, 3]
sage: v = visitor.visit(ast.parse("{'a':('e',2,[None,({False:True},'pi')]), 37.0:'temp'}").body[0].value)
sage: sorted(v.items(), key=lambda x: str(x[0]))
[(37.0, 'temp'), ('a', ('e', 2, [None, ({False: True}, 'pi')]))]
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_BinOp(node)

Visit a Python AST ast.BinOp node.

INPUT:

  • node - the node instance to visit

OUTPUT:

  • The result that node represents

AUTHOR:

  • Simon King

EXAMPLES:

sage: import ast, sage.misc.sageinspect as sms
sage: visitor = sms.SageArgSpecVisitor()
sage: vis = lambda x: visitor.visit(ast.parse(x).body[0].value)
sage: [vis(d) for d in ['(3+(2*4))', '7|8', '5^3', '7/3', '7//3', '3<<4']] #indirect doctest # py2
[11, 15, 6, 2, 2, 48]
sage: [vis(d) for d in ['(3+(2*4))', '7|8', '5^3', '7/3', '7//3', '3<<4']] #indirect doctest # py3
[11, 15, 6, 2.3333333333333335, 2, 48]
visit_BoolOp(node)

Visit a Python AST ast.BoolOp node.

INPUT:

  • node - the node instance to visit

OUTPUT:

  • The result that node represents

AUTHOR:

  • Simon King

EXAMPLES:

sage: import ast, sage.misc.sageinspect as sms
sage: visitor = sms.SageArgSpecVisitor()
sage: vis = lambda x: visitor.visit(ast.parse(x).body[0].value)
sage: [vis(d) for d in ['True and 1', 'False or 3 or None', '3 and 4']] #indirect doctest
[1, 3, 4]
visit_Compare(node)

Visit a Python AST ast.Compare node.

INPUT:

  • node - the node instance to visit

OUTPUT:

  • The result that node represents

AUTHOR:

  • Simon King

EXAMPLES:

sage: import ast, sage.misc.sageinspect as sms
sage: visitor = sms.SageArgSpecVisitor()
sage: vis = lambda x: visitor.visit_Compare(ast.parse(x).body[0].value)
sage: [vis(d) for d in ['1<2==2!=3', '1==1>2', '1<2>1', '1<3<2<4']]
[True, False, True, False]
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, sage.misc.sageinspect as sms
sage: visitor = sms.SageArgSpecVisitor()
sage: vis = lambda x: visitor.visit_Dict(ast.parse(x).body[0].value)
sage: v = [vis(d) for d in ['{}', "{1:one, 'two':2, other:bother}"]]
sage: [sorted(d.items(), key=lambda x: str(x[0])) for d in v]
[[], [(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, sage.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, sage.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']]  # py2
[True, False, None, 'foo', 'bar']
sage: [type(vis(n)) for n in ['True', 'False', 'None', 'foo', 'bar']]  # py2
[<type 'bool'>, <type 'bool'>, <type 'NoneType'>, <type 'str'>, <type 'str'>]
sage: [vis(n) for n in ['foo', 'bar']]  # py3
['foo', 'bar']
sage: [type(vis(n)) for n in ['foo', 'bar']]  # py3
[<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, sage.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())]]  # py2
[123, 0.0, -3.14159265358979]
sage: [vis(n) for n in ['123', '0.0']]  # py3
[123, 0.0]

Note

On Python 3 negative numbers are parsed first, for some reason, as a UnaryOp node.

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, sage.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'''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, sage.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')]
visit_UnaryOp(node)

Visit a Python AST ast.BinOp node.

INPUT:

  • node - the node instance to visit

OUTPUT:

  • The result that node represents

AUTHOR:

  • Simon King

EXAMPLES:

sage: import ast, sage.misc.sageinspect as sms
sage: visitor = sms.SageArgSpecVisitor()
sage: vis = lambda x: visitor.visit_UnaryOp(ast.parse(x).body[0].value)
sage: [vis(d) for d in ['+(3*2)', '-(3*2)']]
[6, -6]
sage.misc.sageinspect.isclassinstance(obj)

Checks if argument is instance of non built-in class

INPUT: obj - object

EXAMPLES:

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

Return the filename extension of loadable modules, including the dot. It is ‘.dll’ on cygwin, ‘.so’ otherwise.

EXAMPLES:

sage: from sage.misc.sageinspect import loadable_module_extension
sage: sage.structure.sage_object.__file__.endswith(loadable_module_extension())
True
sage.misc.sageinspect.sage_getargspec(obj)

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

INPUT:

obj, any callable object

OUTPUT:

An ArgSpec is returned. This is a named tuple (args, varargs, keywords, defaults).

  • args is a list of the argument names (it may contain nested lists).
  • varargs and keywords are the names of the * and ** arguments or None.
  • defaults is an \(n\)-tuple of the default values of the last \(n\) arguments.

NOTE:

If the object has a method _sage_argspec_ then the output of that method is transformed into a named tuple and then returned.

If a class instance has a method _sage_src_ then its output is studied to determine the argspec. This is because currently the CachedMethod decorator has no _sage_argspec_ method.

EXAMPLES:

sage: from sage.misc.sageinspect import sage_getargspec
sage: def f(x, y, z=1, t=2, *args, **keywords):
....:     pass
sage: sage_getargspec(f)
ArgSpec(args=['x', 'y', 'z', 't'], varargs='args', keywords='keywords', defaults=(1, 2))

We now run sage_getargspec on some functions from the Sage library:

sage: sage_getargspec(identity_matrix)
ArgSpec(args=['ring', 'n', 'sparse'], varargs=None, keywords=None, defaults=(0, False))
sage: sage_getargspec(factor)
ArgSpec(args=['n', 'proof', 'int_', 'algorithm', 'verbose'], varargs=None, keywords='kwds', defaults=(None, False, 'pari', 0))

In the case of a class or a class instance, the ArgSpec of the __new__, __init__ or __call__ method is returned:

sage: P.<x,y> = QQ[]
sage: sage_getargspec(P)
ArgSpec(args=['base_ring', 'n', 'names', 'order'], varargs=None, keywords=None, defaults=('degrevlex',))
sage: sage_getargspec(P.__class__)
ArgSpec(args=['self', 'x'], varargs='args', keywords='kwds', defaults=(0,))

The following tests against various bugs that were fixed in trac ticket #9976:

sage: from sage.rings.polynomial.real_roots import bernstein_polynomial_factory_ratlist
sage: sage_getargspec(bernstein_polynomial_factory_ratlist.coeffs_bitsize)
ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None)
sage: from sage.rings.polynomial.pbori import BooleanMonomialMonoid
sage: sage_getargspec(BooleanMonomialMonoid.gen)
ArgSpec(args=['self', 'i'], varargs=None, keywords=None, defaults=(0,))
sage: I = P*[x,y]
sage: sage_getargspec(I.groebner_basis)
ArgSpec(args=['self', 'algorithm', 'deg_bound', 'mult_bound', 'prot'],
varargs='args', keywords='kwds', defaults=('', None, None, False))
sage: cython("cpdef int foo(x,y) except -1: return 1")
sage: sage_getargspec(foo)
ArgSpec(args=['x', 'y'], varargs=None, keywords=None, defaults=None)

If a functools.partial instance is involved, we see no other meaningful solution than to return the argspec of the underlying function:

sage: def f(a,b,c,d=1):
....:     return a+b+c+d
sage: import functools
sage: f1 = functools.partial(f, 1,c=2)
sage: sage_getargspec(f1)
ArgSpec(args=['a', 'b', 'c', 'd'], varargs=None, keywords=None, defaults=(1,))
sage: cython('def foo(x, a=\'\\\')"\', b={not (2+1==3):\'bar\'}): return')
sage: print(sage.misc.sageinspect.sage_getsource(foo))
def foo(x, a='\')"', b={not (2+1==3):'bar'}): return

sage: sage.misc.sageinspect.sage_getargspec(foo)
ArgSpec(args=['x', 'a', 'b'], varargs=None, keywords=None, defaults=('\')"', {False: 'bar'}))

The following produced a syntax error before the patch at trac ticket #11913, see also trac ticket #26906:

sage: sage.misc.sageinspect.sage_getargspec(r.lm)
ArgSpec(args=['self'], varargs='args', keywords='kwds', defaults=None)

The following was fixed in trac ticket #16309:

sage: cython('''
....: class Foo:
....:     @staticmethod
....:     def join(categories, bint as_list = False, tuple ignore_axioms=(), tuple axioms=()): pass
....: cdef class Bar:
....:     @staticmethod
....:     def join(categories, bint as_list = False, tuple ignore_axioms=(), tuple axioms=()): pass
....:     cpdef meet(categories, bint as_list = False, tuple ignore_axioms=(), tuple axioms=()): pass
....: ''')
sage: sage_getargspec(Foo.join)
ArgSpec(args=['categories', 'as_list', 'ignore_axioms', 'axioms'], varargs=None, keywords=None, defaults=(False, (), ()))
sage: sage_getargspec(Bar.join)
ArgSpec(args=['categories', 'as_list', 'ignore_axioms', 'axioms'], varargs=None, keywords=None, defaults=(False, (), ()))
sage: sage_getargspec(Bar.meet)
ArgSpec(args=['categories', 'as_list', 'ignore_axioms', 'axioms'], varargs=None, keywords=None, defaults=(False, (), ()))

Test that trac ticket #17009 is fixed:

sage: sage_getargspec(gap)
ArgSpec(args=['self', 'x', 'name'], varargs=None, keywords=None, defaults=(None,))

By trac ticket #17814, the following gives the correct answer (previously, the defaults would have been found None):

sage: from sage.misc.nested_class import MainClass
sage: sage_getargspec(MainClass.NestedClass.NestedSubClass.dummy)
ArgSpec(args=['self', 'x', 'r'], varargs='args', keywords='kwds', defaults=((1, 2, 3.4),))

In trac ticket #18249 was decided to return a generic signature for Python builtin functions, rather than to raise an error (which is what Python’s inspect module does):

sage: import inspect
sage: inspect.getargspec(range)  # py2
Traceback (most recent call last):
...
TypeError: <built-in function range> is not a Python function
sage: sage_getargspec(range)
ArgSpec(args=[], varargs='args', keywords='kwds', defaults=None)

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
  • Simon King: Return an ArgSpec, fix some bugs.
sage.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 sage.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
sage.misc.sageinspect.sage_getdoc(obj, obj_name='', embedded_override=False)

Return the docstring associated to obj as a string.

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.

INPUT:

  • obj – a function, module, etc.: something with a docstring.

EXAMPLES:

sage: from sage.misc.sageinspect import sage_getdoc
sage: sage_getdoc(identity_matrix)[87:124]
'Return the n x n identity matrix over'
sage: def f(a,b,c,d=1): return a+b+c+d
...
sage: import functools
sage: f1 = functools.partial(f, 1,c=2)
sage: f.__doc__ = "original documentation"
sage: f1.__doc__ = "specialised documentation"
sage: sage_getdoc(f)
'original documentation\n'
sage: sage_getdoc(f1)
'specialised documentation\n'

AUTHORS:

  • William Stein
  • extensions by Nick Alexander
sage.misc.sageinspect.sage_getdoc_original(obj)

Return the unformatted docstring associated to obj as a string.

If obj is a Cython object with an embedded position or signature in its docstring, the embedded information is stripped. If the stripped docstring is empty, then the stripped docstring of obj.__init__ is returned instead.

Feed the results from this into the function sage.misc.sagedoc.format() for printing to the screen.

INPUT:

  • obj – a function, module, etc.: something with a docstring.

EXAMPLES:

sage: from sage.misc.sageinspect import sage_getdoc_original

Here is a class that has its own docstring:

sage: print(sage_getdoc_original(sage.rings.integer.Integer))

    The ``Integer`` class represents arbitrary precision
    integers. It derives from the ``Element`` class, so
    integers can be used as ring elements anywhere in Sage.
...

If the class does not have a docstring, the docstring of the __init__ method is used, but not the __init__ method of the base class (this was fixed in trac ticket #24936):

sage: from sage.categories.category import Category
sage: class A(Category):
....:     def __init__(self):
....:         '''The __init__ docstring'''
sage: sage_getdoc_original(A)
'The __init__ docstring'
sage: class B(Category):
....:     pass
sage: sage_getdoc_original(B)
''

Old-style classes are supported:

sage: class OldStyleClass:
....:     def __init__(self):
....:         '''The __init__ docstring'''
....:         pass
sage: print(sage_getdoc_original(OldStyleClass))
The __init__ docstring

When there is no __init__ method, we just get an empty string:

sage: class OldStyleClass:
....:     pass
sage: sage_getdoc_original(OldStyleClass)
''

If an instance of a class does not have its own docstring, the docstring of its class results:

sage: sage_getdoc_original(sage.plot.colors.aliceblue) == sage_getdoc_original(sage.plot.colors.Color)
True
sage.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 sage.misc.sageinspect import sage_getfile
sage: sage_getfile(sage.rings.rational)[-23:]
'sage/rings/rational.pyx'
sage: sage_getfile(Sq)[-42:]
'sage/algebras/steenrod/steenrod_algebra.py'

The following tests against some bugs fixed in trac ticket #9976:

sage: obj = sage.combinat.partition_algebra.SetPartitionsAk
sage: obj = sage.combinat.partition_algebra.SetPartitionsAk
sage: sage_getfile(obj)
'...sage/combinat/partition_algebra.py'

And here is another bug, fixed in trac ticket #11298:

sage: P.<x,y> = QQ[]
sage: sage_getfile(P)
'...sage/rings/polynomial/multi_polynomial_libsingular...'

A problem fixed in trac ticket #16309:

sage: cython('''
....: class Bar: pass
....: cdef class Foo: pass
....: ''')
sage: sage_getfile(Bar)
'...pyx'
sage: sage_getfile(Foo)
'...pyx'

By trac ticket #18249, we return an empty string for Python builtins. In that way, there is no error when the user types, for example, range?:

sage: sage_getfile(range)
''

AUTHORS:

  • Nick Alexander
  • Simon King
sage.misc.sageinspect.sage_getsource(obj)

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

INPUT:

  • obj – function, etc.

EXAMPLES:

sage: from sage.misc.sageinspect import sage_getsource
sage: sage_getsource(identity_matrix)[19:60]
'identity_matrix(ring, n=0, sparse=False):'
sage: sage_getsource(identity_matrix)[19:60]
'identity_matrix(ring, n=0, sparse=False):'

AUTHORS:

  • William Stein
  • extensions by Nick Alexander
sage.misc.sageinspect.sage_getsourcelines(obj)

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

INPUT:

  • obj – function, etc.

OUTPUT:

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

EXAMPLES:

sage: from sage.misc.sageinspect import sage_getsourcelines
sage: sage_getsourcelines(matrix)[1]
22
sage: sage_getsourcelines(matrix)[0][0]
'def matrix(*args, **kwds):\n'

Some classes customize this using a _sage_src_lines_ method, which gives the source lines of a class instance, but not the class itself. We demonstrate this for CachedFunction:

sage: cachedfib = cached_function(fibonacci)
sage: sage_getsourcelines(cachedfib)[0][0]
'def fibonacci(n, algorithm="pari"):\n'
sage: sage_getsourcelines(type(cachedfib))[0][0]
'cdef class CachedFunction(object):\n'

AUTHORS:

  • William Stein
  • Extensions by Nick Alexander
  • Extension to interactive Cython code by Simon King
  • Simon King: If a class has no docstring then let the class definition be found starting from the __init__ method.
  • Simon King: Get source lines for dynamic classes.
sage.misc.sageinspect.sage_getvariablename(self, omit_underscore_names=True)

Attempt to get the name of a Sage object.

INPUT:

  • self – any object.
  • omit_underscore_names – boolean, default True.

OUTPUT:

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 sorted 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 sage.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))
[]