### Navigation

- index
- modules |
- next |
- previous |
- Miscellaneous »

# 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:...'

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(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, there is no argspec extractable from builtins:

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

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

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)

    x.__init__(...) initializes x; see help(type(x)) for signature

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: visitor.visit(ast.parse("{'a':('e',2,[None,({False:True},'pi')]), 37.0:'temp'}").body[0].value)
      {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
        [11, 15, 6, 2, 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: [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, 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']]
        [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, 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())]]
        [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, 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"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.``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=['self', 'x'], varargs='args', keywords='kwds', defaults=(0,))
      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,))

  TESTS:

  By trac ticket #9976, rather complicated cases work. In the following example, we dynamically create an extension class that returns some source code, and the example shows that the source code is taken for granted, i.e., the argspec of an instance of that class does not coincide with the argspec of its call method. That behaviour is intended, since a decorated method appears to have the generic signature `*args,**kwds`, but in fact it is only supposed to be called with the arguments requested by the underlying undecorated method. We saw an easy example above, namely `I.groebner_basis`. Here is a more difficult one:

      sage: cython_code = [
      ... 'cdef class MyClass:',
      ... '    def _sage_src_(self):',
      ... '        return "def foo(x, a=\\\')\\\"\\\', b={(2+1):\\\'bar\\\', not 1:3, 3<<4:5}): return\\n"',
      ... '    def __call__(self, m,n): return "something"']
      sage: cython('\n'.join(cython_code))
      sage: O = MyClass()
      sage: print sage.misc.sageinspect.sage_getsource(O)
      def foo(x, a=')"', b={(2+1):'bar', not 1:3, 3<<4:5}): return
      sage: sage.misc.sageinspect.sage_getargspec(O)
      ArgSpec(args=['x', 'a', 'b'], varargs=None, keywords=None, defaults=(')"', {False: 3, 48: 5, 3: 'bar'}))
      sage: sage.misc.sageinspect.sage_getargspec(O.__call__)
      ArgSpec(args=['self', 'm', 'n'], varargs=None, keywords=None, defaults=None)

      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
      <BLANKLINE>
      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:

      sage: sage.misc.sageinspect.sage_getargspec(r.lm)

  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,))

  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.

  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 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_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.pyx'

  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'

  AUTHORS:

  - Nick Alexander
  - Simon King

`sage.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 sage.misc.sageinspect import sage_getsource
      sage: sage_getsource(identity_matrix, True)[19:60]
      'identity_matrix(ring, n=0, sparse=False):'
      sage: sage_getsource(identity_matrix, False)[19:60]
      'identity_matrix(ring, n=0, sparse=False):'

  AUTHORS:

  - William Stein
  - extensions by Nick Alexander

`sage.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 sage.misc.sageinspect import sage_getsourcelines
      sage: sage_getsourcelines(matrix, True)[1]
      732
      sage: sage_getsourcelines(matrix, False)[0][0][6:]
      'MatrixFactory(object):\n'

  TESTS:

      sage: cython('''cpdef test_funct(x,y): return''')
      sage: sage_getsourcelines(test_funct)
      (['cpdef test_funct(x,y): return\n'], 6)

  The following tests that an instance of `functools.partial` is correctly dealt with (see trac ticket #9976):

      sage: obj = sage.combinat.partition_algebra.SetPartitionsAk
      sage: sage_getsourcelines(obj)
      (['def create_set_partition_function(letter, k):\n',
      ...
      '    raise ValueError("k must be an integer or an integer + 1/2")\n'], 34)

  Here are some cases that were covered in :trac`11298`; note that line numbers may easily change, and therefore we do not test them:

      sage: P.<x,y> = QQ[]
      sage: I = P*[x,y]
      sage: sage_getsourcelines(P)
      (['cdef class MPolynomialRing_libsingular(MPolynomialRing_generic):\n',
        '\n',
        '    def __cinit__(self):\n',
      ...)
      sage: sage_getsourcelines(I)
      (['class MPolynomialIdeal( MPolynomialIdeal_singular_repr, \\\n',
      ...)
      sage: x = var('x')
      sage: sage_getsourcelines(x)
      (['cdef class Expression(CommutativeRingElement):\n',
        '    cpdef object pyobject(self):\n',
      ...)
      sage: sage_getsourcelines(x)[0][-1]    # last line
      '        return self / x\n'

  We show some enhancements provided by trac ticket #11768. First, we use a dummy parent class that has defined an element class by a nested class definition:

      sage: from sage.misc.nested_class_test import TestNestedParent
      sage: from sage.misc.sageinspect import sage_getsource
      sage: P = TestNestedParent()
      sage: E = P.element_class
      sage: E.__bases__
      (<class sage.misc.nested_class_test.TestNestedParent.Element at ...>,
       <class 'sage.categories.sets_cat.Sets.element_class'>)
      sage: print sage_getsource(E)
          class Element:
              "This is a dummy element class"
              pass
      sage: print sage_getsource(P)
      class TestNestedParent(UniqueRepresentation, Parent):
          ...
          class Element:
              "This is a dummy element class"
              pass

  Here is another example that relies on a nested class definition in the background:

      sage: C = AdditiveMagmas()
      sage: HC = C.Homsets()
      sage: sage_getsourcelines(HC)
      (['    class Homsets(HomsetsCategory):\n', ...], ...)

  Testing against a bug that has occured during work on #11768:

      sage: P.<x,y> = QQ[]
      sage: I = P*[x,y]
      sage: sage_getsourcelines(I)
      (['class MPolynomialIdeal( MPolynomialIdeal_singular_repr, \\\n',
        '                        MPolynomialIdeal_macaulay2_repr, \\\n',
        '                        MPolynomialIdeal_magma_repr, \\\n',
        '                        Ideal_generic ):\n',
        '    def __init__(self, ring, gens, coerce=True):\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))
      []

### Navigation

- index
- modules |
- next |
- previous |
- Miscellaneous »