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)
'# distutils: ...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()[:50]
'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 github issue #9976 and github issue #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') # optional - sage.misc.cython
sage: print(sage_getsource(foo)) # optional - sage.misc.cython
def foo(unsigned int x=1, a=')"', b={not (2+1==3):'bar'}, *args, **kwds): return
sage: sage_getargspec(foo) # optional - sage.misc.cython
FullArgSpec(args=['x', 'a', 'b'], varargs='args', varkw='kwds', defaults=(1, ')"', {False: 'bar'}), kwonlyargs=[], kwonlydefaults=None, annotations={})
- class sage.misc.sageinspect.BlockFinder#
Bases:
object
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:
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: attrs = [x for x in dir(v) if not x.startswith('__')] sage: '_attributes' in attrs and '_fields' in attrs and 'col_offset' in attrs True 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 [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 ['foo', 'bar']] ['foo', 'bar'] sage: [type(vis(n)) for n in ['foo', 'bar']] [<class 'str'>, <class 'str'>]
- visit_NameConstant(node)#
Visit a Python AST
ast.NameConstant
node.This is an optimization added in Python 3.4 for the special cases of True, False, and None.
INPUT:
node
- the node instance to visit
OUTPUT:
None, True, False.
EXAMPLES:
sage: import ast, sage.misc.sageinspect as sms sage: visitor = sms.SageArgSpecVisitor() sage: vis = lambda x: visitor.visit_NameConstant(ast.parse(x).body[0].value) sage: [vis(n) for n in ['True', 'False', 'None']] [True, False, None] sage: [type(vis(n)) for n in ['True', 'False', 'None']] [<class 'bool'>, <class 'bool'>, <class 'NoneType'>]
- 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']] [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"', "'syntax'", r'''r"tr\ee"''']] ['abstract', '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]
- visit_arg(node)#
Visit a Python AST
ast.arg
node.This node type is only on Python 3, where function arguments are more complex than just an identifier (e.g. they may also include annotations).
For now we simply return the argument identifier as a string.
INPUT:
node
– the node instance to visit
OUTPUT:
the argument name
EXAMPLES:
sage: import ast, sage.misc.sageinspect as sms sage: s = "def f(a, b=2, c={'a': [4, 5.5, False]}, d=(None, True)):\n return" sage: visitor = sms.SageArgSpecVisitor() sage: args = ast.parse(s).body[0].args.args sage: [visitor.visit_arg(n) for n in args] ['a', 'b', 'c', 'd']
- sage.misc.sageinspect.formatannotation(annotation, base_module=None)#
This is taken from Python 3.7’s inspect.py; the only change is to add documentation.
INPUT:
annotation
– annotation for a functionbase_module
(optional, defaultNone
)
This is only relevant with Python 3, so the doctests are marked accordingly.
EXAMPLES:
sage: from sage.misc.sageinspect import formatannotation sage: import inspect sage: def foo(a, *, b:int, **kwargs): ....: pass sage: s = inspect.signature(foo) sage: a = s.parameters['a'].annotation sage: a <class 'inspect._empty'> sage: formatannotation(a) 'inspect._empty' sage: b = s.parameters['b'].annotation sage: b <class 'int'> sage: formatannotation(b) 'int'
- sage.misc.sageinspect.is_function_or_cython_function(obj)#
Check whether something is a function.
This is a variant of
inspect.isfunction()
: We assume that anything which has a genuine__code__
attribute (not using__getattr__
overrides) is a function. This is meant to support Cython functions.Think twice before using this function (or any function from the
inspect
orsage.misc.sageinspect
modules). Most uses ofinspect.isfunction()
in ordinary library code can be replaced bycallable()
.EXAMPLES:
sage: from sage.misc.sageinspect import is_function_or_cython_function sage: def f(): pass sage: is_function_or_cython_function(f) True sage: is_function_or_cython_function(lambda x:x) True sage: from sage.categories.coercion_methods import _mul_parent sage: is_function_or_cython_function(_mul_parent) True sage: is_function_or_cython_function(Integer.digits) # unbound method False sage: is_function_or_cython_function(Integer(1).digits) # bound method False
- sage.misc.sageinspect.isclassinstance(obj)#
Check if argument is instance of non built-in class
INPUT:
obj
– objectEXAMPLES:
sage: from sage.misc.sageinspect import isclassinstance sage: isclassinstance(int) False sage: class myclass: pass sage: isclassinstance(myclass()) True sage: isclassinstance(myclass) False sage: class mymetaclass(type): pass sage: class myclass2(metaclass=mymetaclass): pass 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.
This function is deprecated.
EXAMPLES:
sage: from sage.misc.sageinspect import loadable_module_extension sage: from importlib.machinery import EXTENSION_SUFFIXES sage: loadable_module_extension() in EXTENSION_SUFFIXES doctest:warning... DeprecationWarning: loadable_module_extension is deprecated; use importlib.machinery.EXTENSION_SUFFIXES instead See https://github.com/sagemath/sage/issues/33636 for details. True
- sage.misc.sageinspect.sage_formatargspec(args, varargs=None, varkw=None, defaults=None, kwonlyargs=(), kwonlydefaults=None, annotations={}, formatarg=<class 'str'>, formatvarargs=<function <lambda> at 0x7f487a845fc0>, formatvarkw=<function <lambda> at 0x7f487a846050>, formatvalue=<function <lambda> at 0x7f487a8460e0>, formatreturns=<function <lambda> at 0x7f487a846170>, formatannotation=<function formatannotation at 0x7f487a845f30>)#
Format an argument spec from the values returned by getfullargspec.
The first seven arguments are (args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations). The other five arguments are the corresponding optional formatting functions that are called to turn names and values into strings. The last argument is an optional function to format the sequence of arguments.
This is taken from Python 3.7’s inspect.py, where it is deprecated. The only change, aside from documentation (this paragraph and the next, plus doctests), is to remove the deprecation warning.
Sage uses this function to format arguments, as obtained by
sage_getargspec()
. Sincesage_getargspec()
works for Cython functions while Python’s inspect module does not, it makes sense to keep this function for formatting instances ofinspect.FullArgSpec
.EXAMPLES:
sage: from sage.misc.sageinspect import sage_formatargspec sage: args = ['a', 'b', 'c'] sage: defaults = [3] sage: sage_formatargspec(args, defaults=defaults) '(a, b, c=3)'
- sage.misc.sageinspect.sage_getargspec(obj)#
Return the names and default values of a function’s arguments.
INPUT:
obj
, any callable objectOUTPUT:
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
andkeywords
are the names of the*
and**
arguments orNone
.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 theCachedMethod
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) FullArgSpec(args=['x', 'y', 'z', 't'], varargs='args', varkw='keywords', defaults=(1, 2), kwonlyargs=[], kwonlydefaults=None, annotations={})
We now run sage_getargspec on some functions from the Sage library:
sage: sage_getargspec(identity_matrix) FullArgSpec(args=['ring', 'n', 'sparse'], varargs=None, varkw=None, defaults=(0, False), kwonlyargs=[], kwonlydefaults=None, annotations={}) sage: sage_getargspec(factor) FullArgSpec(args=['n', 'proof', 'int_', 'algorithm', 'verbose'], varargs=None, varkw='kwds', defaults=(None, False, 'pari', 0), kwonlyargs=[], kwonlydefaults=None, annotations={})
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) FullArgSpec(args=['base_ring', 'n', 'names', 'order'], varargs=None, varkw=None, defaults=('degrevlex',), kwonlyargs=[], kwonlydefaults=None, annotations={}) sage: sage_getargspec(P.__class__) FullArgSpec(args=['self', 'x'], varargs='args', varkw='kwds', defaults=(0,), kwonlyargs=[], kwonlydefaults=None, annotations={})
The following tests against various bugs that were fixed in github issue #9976:
sage: from sage.rings.polynomial.real_roots import bernstein_polynomial_factory_ratlist sage: sage_getargspec(bernstein_polynomial_factory_ratlist.coeffs_bitsize) FullArgSpec(args=['self'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={}) sage: from sage.rings.polynomial.pbori.pbori import BooleanMonomialMonoid sage: sage_getargspec(BooleanMonomialMonoid.gen) FullArgSpec(args=['self', 'i'], varargs=None, varkw=None, defaults=(0,), kwonlyargs=[], kwonlydefaults=None, annotations={}) sage: I = P*[x,y] sage: sage_getargspec(I.groebner_basis) FullArgSpec(args=['self', 'algorithm', 'deg_bound', 'mult_bound', 'prot'], varargs='args', varkw='kwds', defaults=('', None, None, False), kwonlyargs=[], kwonlydefaults=None, annotations={}) sage: cython("cpdef int foo(x,y) except -1: return 1") sage: sage_getargspec(foo) FullArgSpec(args=['x', 'y'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})
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) FullArgSpec(args=['a', 'b', 'c', 'd'], varargs=None, varkw=None, defaults=(1,), kwonlyargs=[], kwonlydefaults=None, annotations={})
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
- functionobj_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 github issue #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=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.The optional boolean argument
embedded
controls the string formatting. It is False by default.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 ofobj.__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 :class:`Integer` class represents arbitrary precision integers. It derives from the :class:`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 github issue #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) '...sage/rings/rational.pyx' sage: sage_getfile(Sq) '...sage/algebras/steenrod/steenrod_algebra.py' sage: sage_getfile(x) '...sage/symbolic/expression.pyx'
The following tests against some bugs fixed in github issue #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 github issue #11298:
sage: P.<x,y> = QQ[] sage: sage_getfile(P) '...sage/rings/polynomial/multi_polynomial_libsingular...'
A problem fixed in github issue #16309:
sage: cython( # optional - sage.misc.cython ....: ''' ....: class Bar: pass ....: cdef class Foo: pass ....: ''') sage: sage_getfile(Bar) # optional - sage.misc.cython '...pyx' sage: sage_getfile(Foo) # optional - sage.misc.cython '...pyx'
By github issue #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_getfile_relative(obj)#
Get the file name associated to
obj
as a string.This is the same as
sage_getfile()
, but if the source file is part of thesage.*
namespace, it makes the file name relative so that it starts withsage/
.INPUT:
obj
, a Sage object, module, etc.EXAMPLES:
sage: from sage.misc.sageinspect import sage_getfile_relative sage: sage_getfile_relative(sage.rings.rational) 'sage/rings/rational.pyx' sage: sage_getfile_relative(Sq) 'sage/algebras/steenrod/steenrod_algebra.py' sage: sage_getfile_relative(x) 'sage/symbolic/expression.pyx' sage: sage_getfile_relative(range) ''
- 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, andlineno
is an integer.EXAMPLES:
sage: from sage.misc.sageinspect import sage_getsourcelines sage: sage_getsourcelines(matrix)[1] 21 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 forCachedFunction
:sage: cachedfib = cached_function(fibonacci) sage: sage_getsourcelines(cachedfib)[0][0] 'def fibonacci(n, algorithm="pari") -> Integer:\n' sage: sage_getsourcelines(type(cachedfib))[0][0] 'cdef class CachedFunction():\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, defaultTrue
.
OUTPUT:
If the user has assigned an object
obj
to a variable name, then return that variable name. If several variables point toobj
, return a sorted list of those names. Ifomit_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)) []