示例#1
0
 def can_document_member(cls, member, membername, isattr, parent):
     # It can be documented if it is a genuine function.
     # Often, a class instance has the same documentation as its class,
     # and then we typically want to document the class and not the instance.
     # However, there is an exception: CachedFunction(f) returns a class instance,
     # whose doc string coincides with that of f and is thus different from
     # that of the class CachedFunction. In that situation, we want that f is documented.
     # This is part of SAGE TRAC 9976
     return isinstance(member, (FunctionType, BuiltinFunctionType)) or (isclassinstance(member) and _sage_getdoc_unformatted(member)!=_sage_getdoc_unformatted(member.__class__))
示例#2
0
 def can_document_member(cls, member, membername, isattr, parent):
     # It can be documented if it is a genuine function.
     # Often, a class instance has the same documentation as its class,
     # and then we typically want to document the class and not the instance.
     # However, there is an exception: CachedFunction(f) returns a class instance,
     # whose doc string coincides with that of f and is thus different from
     # that of the class CachedFunction. In that situation, we want that f is documented.
     # This is part of SAGE TRAC 9976
     return isinstance(member, (FunctionType, BuiltinFunctionType)) or (isclassinstance(member) and _sage_getdoc_unformatted(member)!=_sage_getdoc_unformatted(member.__class__))
示例#3
0
 def args_on_obj(obj):
     if hasattr(obj, "_sage_argspec_"):
         return obj._sage_argspec_()
     if inspect.isbuiltin(obj) or \
            inspect.ismethoddescriptor(obj):
         # can never get arguments of a C function or method unless
         # a function to do so is supplied
         if self.env.config.autodoc_builtin_argspec:
             argspec = self.env.config.autodoc_builtin_argspec(obj)
             return argspec
         else:
             return None
     argspec = sage_getargspec(obj)  #inspect.getargspec(obj)
     if isclassinstance(obj) or inspect.isclass(obj):
         # if a class should be documented as function, we try
         # to use the constructor signature as function
         # signature without the first argument.
         if argspec is not None and argspec[0]:
             del argspec[0][0]
     return argspec
示例#4
0
 def args_on_obj(obj):
     if hasattr(obj, "_sage_argspec_"):
         return obj._sage_argspec_()
     if inspect.isbuiltin(obj) or \
            inspect.ismethoddescriptor(obj):
         # can never get arguments of a C function or method unless
         # a function to do so is supplied
         if self.env.config.autodoc_builtin_argspec:
             argspec = self.env.config.autodoc_builtin_argspec(obj)
             return argspec
         else:
             return None
     argspec = sage_getargspec(obj) #inspect.getargspec(obj)
     if isclassinstance(obj) or inspect.isclass(obj):
         # if a class should be documented as function, we try
         # to use the constructor signature as function
         # signature without the first argument.
         if argspec is not None and argspec[0]:
             del argspec[0][0]
     return argspec
示例#5
0
def find_object_modules(obj):
    r"""
    Return a dictionary whose keys are the names of the modules where ``obj``
    appear and the value at a given module name is the list of names that
    ``obj`` have in that module.

    It is very unlikely that the output dictionary has several keys except when
    ``obj`` is an instance of a class.

    EXAMPLES::

        sage: from sage.misc.dev_tools import find_object_modules
        sage: find_object_modules(RR)
        {'sage.rings.real_mpfr': ['RR']}
        sage: find_object_modules(ZZ)
        {'sage.rings.integer_ring': ['Z', 'ZZ']}

    .. NOTE::

        It might be a good idea to move this function in
        :mod:`sage.misc.sageinspect`.
    """
    from sage.misc import sageinspect

    # see if the object is defined in its own module
    # might be wrong for class instances as the instanciation might appear
    # outside of the module !!
    module_name = None
    if sageinspect.isclassinstance(obj):
        module_name = obj.__class__.__module__
    elif hasattr(obj, '__module__') and obj.__module__:
        module_name = obj.__module__

    if module_name:
        if module_name not in sys.modules:
            raise ValueError("This should not happen!")
        d = sys.modules[module_name].__dict__
        matching = sorted(key for key in d if d[key] is obj)
        if matching:
            return {module_name: matching}

    # otherwise, we parse all (already loaded) modules and hope to find
    # something
    module_to_obj = {}
    for module_name, module in sys.modules.items():
        if module_name != '__main__' and hasattr(module, '__dict__'):
            d = module.__dict__
            names = [key for key in d if d[key] is obj]
            if names:
                module_to_obj[module_name] = names

    # if the object is an instance, we try to guess where it is defined
    if sageinspect.isclassinstance(obj):
        dec_pattern = re.compile(r"^(\w[\w0-9\_]*)\s*=", re.MULTILINE)
        module_to_obj2 = {}
        for module_name, obj_names in module_to_obj.items():
            module_to_obj2[module_name] = []
            try:
                src = sageinspect.sage_getsource(sys.modules[module_name])
            except TypeError:
                pass
            else:
                m = dec_pattern.search(src)
                while m:
                    if m.group(1) in obj_names:
                        module_to_obj2[module_name].append(m.group(1))
                    m = dec_pattern.search(src, m.end())
            if not module_to_obj2[module_name]:
                del module_to_obj2[module_name]

        if module_to_obj2:
            return module_to_obj2

    return module_to_obj
示例#6
0
文件: dev_tools.py 项目: chos9/sage
def import_statements(*objects, **options):
    """
    Print import statements for the given objects.

    INPUT:

    - ``*objects`` -- a sequence of objects.

    - ``lazy`` -- a boolean (default: ``False``)
      Whether to print a lazy import statement.

    - ``verbose`` -- a boolean (default: ``True``)
      Whether to print information in case of ambiguity.

    EXAMPLES::

        sage: import_statements(WeylGroup, lazy_attribute)
        from sage.combinat.root_system.weyl_group import WeylGroup
        from sage.misc.lazy_attribute import lazy_attribute

        sage: import_statements(IntegerRing)
        from sage.rings.integer_ring import IntegerRing

    If ``lazy`` is True, then :func:`lazy_import` statements are
    displayed instead::

        sage: import_statements(WeylGroup, lazy_attribute, lazy=True)
        from sage.misc.lazy_import import lazy_import
        lazy_import('sage.combinat.root_system.weyl_group', 'WeylGroup')
        lazy_import('sage.misc.lazy_attribute', 'lazy_attribute')

    In principle, the function should also work on object which are instances.
    In case of ambiguity, one or two warning lines are printed::

        sage: import_statements(NN)
        from sage.rings.semirings.non_negative_integer_semiring import NN

        sage: import_statements(ZZ)
          ** Warning **: several names for that object: Z, ZZ
        from sage.rings.integer_ring import Z

        sage: import_statements(euler_phi)
        from sage.rings.arith import euler_phi

        sage: import_statements(x)
          ** Warning **: several modules for that object: sage.all_cmdline, sage.calculus.predefined, sage.interacts.library
        from sage.calculus.predefined import x

    If you don't like the warning you can disable them with the option ``verbose``::

        sage: import_statements(ZZ, verbose=False)
        from sage.rings.integer_ring import Z

        sage: import_statements(x, verbose=False)
        from sage.calculus.predefined import x

    If the object has several names, an other way to get the import
    statement you expect is to use a string instead of the object::

        sage: import_statements(cached_function)
          ** Warning **: several names for that object: CachedFunction, cached_function
        from sage.misc.cachefunc import CachedFunction

        sage: import_statements('cached_function')
        from sage.misc.cachefunc import cached_function
        sage: import_statements('Z')
        from sage.rings.integer_ring import Z


    Specifying a string is also useful for objects that are not
    imported in the Sage interpreter namespace by default. In this
    case, an object with that name is looked up in all the modules
    that have been imported in this session::

        sage: print_import_statement
        Traceback (most recent call last):
        ...
        NameError: name 'print_import_statement' is not defined

        sage: import_statements("print_import_statement")
        from sage.misc.dev_tools import print_import_statement

    We test different object which have no appropriate answer::

        sage: import_statements('my_tailor_is_rich')
        Traceback (most recent call last):
        ...
        ValueError: no import statement for my_tailor_is_rich
        sage: import_statements(5)
        Traceback (most recent call last):
        ...
        ValueError: no import statement for 5
    """
    import inspect, sys, re
    import sage.all
    from sage.misc import sageinspect
    from sage.misc.flatten import flatten

    lazy = options.get("lazy", False)
    verbose = options.get("verbose", True)
    if lazy:
        print "from sage.misc.lazy_import import lazy_import"

    for obj in objects:
        # if obj is a string use it has a name and look for an object
        if isinstance(obj, str):
            name = obj
            if name in sage.all.__dict__:
                obj = sage.all.__dict__[name]
            else:
                # Look for the first module which contains that name.
                # TODO: improve this heuristic.
                for module in sys.modules.values():
                    if hasattr(module, '__dict__') and name in module.__dict__:
                        obj = module.__dict__[name]
                        break
        else:
            name = None

        # Case 1: the object is a module
        if inspect.ismodule(obj):
            if lazy:
                print "lazy_import('%s')"%obj.__name__
            else:
                print "import %s"%obj.__name__
            continue

        # Case 2: the object is defined in its module
        module = None
        if sageinspect.isclassinstance(obj):
            module = obj.__class__.__module__
        elif hasattr(obj, '__module__') and obj.__module__:
            module = obj.__module__

        if module:
            d = sys.modules[module].__dict__
            if name is None:
                names = sorted(key for key in d if d[key] is obj)
            else:
                names = [name]
            if names:
                if verbose and len(names) > 1:
                    print "  ** Warning **: several names for that object: %s"%', '.join(names)
                print_import_statement(module, names[0], lazy)
                continue


        # Case 3: search for this object in all modules
        names = {} # dictionnary: module -> names of the object in that module
        for module in sys.modules:
            if module != '__main__' and hasattr(sys.modules[module],'__dict__'):
                d = sys.modules[module].__dict__

                if name is not None:
                    if name in d and d[name] is obj:
                        names[module] = name
                else:
                    n = [key for key in d if d[key] is obj]
                    if n:
                        names[module] = n

        all_names = sorted(set(flatten(names.values())))
        if len(all_names) == 0:
            raise ValueError("no import statement for %s"%obj)
        elif verbose and len(all_names) > 1:
            print "  ** Warning **: several names for that object:",
            print ", ".join(sorted(all_names))

        modules = sorted(flatten(names),cmp=module_names_cmp)
        if verbose and len(modules) > 1:
            print "  ** Warning **: several modules for that object:",
            print ", ".join(modules[:4]),
            if len(modules) > 4:
                print "..."
            else:
                print

        # Case 4: if the object is a class instance, we look for a
        # module where it is instanciated
        if sageinspect.isclassinstance(obj):
            names_pattern = dict((name,re.compile("^%s\ *="%name, re.MULTILINE)) for name in all_names)

            for module in modules:
                sources = sageinspect.sage_getsource(sys.modules[module])
                for name in names[module]:
                    if names_pattern[name].search(sources):
                        break
                else:
                    continue
                break
        else:
            module = modules[0]
            name = names[module][0]

        if name is not None:
            print_import_statement(module, name, lazy)
        else:
            raise ValueError("no import statement for %s"%obj)
示例#7
0
def find_object_modules(obj):
    r"""
    Return a dictionnary whose keys are the names of the modules where ``obj``
    appear and the value at a given module name is the list of names that
    ``obj`` have in that module.

    It is very unlikely that the output dictionnary has several keys except when
    ``obj`` is an instance of a class.

    EXAMPLES::

        sage: from sage.misc.dev_tools import find_object_modules
        sage: find_object_modules(RR)
        {'sage.rings.real_mpfr': ['RR']}
        sage: find_object_modules(ZZ)
        {'sage.rings.integer_ring': ['Z', 'ZZ']}

    .. NOTE::

        It might be a good idea to move this function in
        :mod:`sage.misc.sageinspect`.
    """
    from sage.misc import sageinspect

    # see if the object is defined in its own module
    # might be wrong for class instances as the instanciation might appear
    # outside of the module !!
    module_name = None
    if sageinspect.isclassinstance(obj):
        module_name = obj.__class__.__module__
    elif hasattr(obj, '__module__') and obj.__module__:
        module_name = obj.__module__

    if module_name:
        import sys
        if module_name not in sys.modules:
            raise ValueError("This should not happen!")
        d = sys.modules[module_name].__dict__
        matching = sorted(key for key in d if d[key] is obj)
        if matching:
            return {module_name: matching}

    # otherwise, we parse all (already loaded) modules and hope to find
    # something
    import sys
    module_to_obj = {}
    for module_name, module in sys.modules.iteritems():
        if module_name != '__main__' and hasattr(module, '__dict__'):
            d = module.__dict__
            names = [key for key in d if d[key] is obj]
            if names:
                module_to_obj[module_name] = names

    # if the object is an instance, we try to guess where it is defined
    if sageinspect.isclassinstance(obj):
        import re
        dec_pattern = re.compile("^(\w[\w0-9\_]*)\s*=", re.MULTILINE)
        module_to_obj2 = {}
        for module_name, obj_names in module_to_obj.iteritems():
            module_to_obj2[module_name] = []
            src = sageinspect.sage_getsource(sys.modules[module_name])
            m = dec_pattern.search(src)
            while m:
                if m.group(1) in obj_names:
                    module_to_obj2[module_name].append(m.group(1))
                m = dec_pattern.search(src, m.end())

            if not module_to_obj2[module_name]:
                del module_to_obj2[module_name]

        if module_to_obj2:
            return module_to_obj2

    return module_to_obj
示例#8
0
def import_statements(*objects, **options):
    """
    Print import statements for the given objects.

    INPUT:

    - ``*objects`` -- a sequence of objects.

    - ``lazy`` -- a boolean (default: ``False``)
      Whether to print a lazy import statement.

    - ``verbose`` -- a boolean (default: ``True``)
      Whether to print information in case of ambiguity.

    EXAMPLES::

        sage: import_statements(WeylGroup, lazy_attribute)
        from sage.combinat.root_system.weyl_group import WeylGroup
        from sage.misc.lazy_attribute import lazy_attribute

        sage: import_statements(IntegerRing)
        from sage.rings.integer_ring import IntegerRing

    If ``lazy`` is True, then :func:`lazy_import` statements are
    displayed instead::

        sage: import_statements(WeylGroup, lazy_attribute, lazy=True)
        from sage.misc.lazy_import import lazy_import
        lazy_import('sage.combinat.root_system.weyl_group', 'WeylGroup')
        lazy_import('sage.misc.lazy_attribute', 'lazy_attribute')

    In principle, the function should also work on object which are instances.
    In case of ambiguity, one or two warning lines are printed::

        sage: import_statements(NN)
        from sage.rings.semirings.non_negative_integer_semiring import NN

        sage: import_statements(ZZ)
          ** Warning **: several names for that object: Z, ZZ
        from sage.rings.integer_ring import Z

        sage: import_statements(euler_phi)
        from sage.rings.arith import euler_phi

        sage: import_statements(x)
          ** Warning **: several modules for that object: sage.all_cmdline, sage.calculus.predefined, sage.interacts.library
        from sage.calculus.predefined import x

    If you don't like the warning you can disable them with the option ``verbose``::

        sage: import_statements(ZZ, verbose=False)
        from sage.rings.integer_ring import Z

        sage: import_statements(x, verbose=False)
        from sage.calculus.predefined import x

    If the object has several names, an other way to get the import
    statement you expect is to use a string instead of the object::

        sage: import_statements(cached_function)
          ** Warning **: several names for that object: CachedFunction, cached_function
        from sage.misc.cachefunc import CachedFunction

        sage: import_statements('cached_function')
        from sage.misc.cachefunc import cached_function
        sage: import_statements('Z')
        from sage.rings.integer_ring import Z

    Specifying a string is also useful for objects that are not
    imported in the Sage interpreter namespace by default. In this
    case, an object with that name is looked up in all the modules
    that have been imported in this session::

        sage: print_import_statement
        Traceback (most recent call last):
        ...
        NameError: name 'print_import_statement' is not defined

        sage: import_statements("print_import_statement")
        from sage.misc.dev_tools import print_import_statement

    We test different object which have no appropriate answer::

        sage: import_statements('my_tailor_is_rich')
        Traceback (most recent call last):
        ...
        ValueError: no import statement for my_tailor_is_rich
        sage: import_statements(5)
        Traceback (most recent call last):
        ...
        ValueError: no import statement for 5
    """
    import inspect, sys, re
    import sage.all
    from sage.misc import sageinspect
    from sage.misc.flatten import flatten

    lazy = options.get("lazy", False)
    verbose = options.get("verbose", True)
    if lazy:
        print "from sage.misc.lazy_import import lazy_import"

    for obj in objects:
        # if obj is a string use it has a name and look for an object
        if isinstance(obj, str):
            name = obj
            if name in sage.all.__dict__:
                obj = sage.all.__dict__[name]
            else:
                # Look for the first module which contains that name.
                # TODO: improve this heuristic.
                for module in sys.modules.values():
                    if hasattr(module, '__dict__') and name in module.__dict__:
                        obj = module.__dict__[name]
                        break
        else:
            name = None

        # Case 1: the object is a module
        if inspect.ismodule(obj):
            if lazy:
                print "lazy_import('%s')" % obj.__name__
            else:
                print "import %s" % obj.__name__
            continue

        # Case 2: the object is defined in its module
        module = None
        if sageinspect.isclassinstance(obj):
            module = obj.__class__.__module__
        elif hasattr(obj, '__module__') and obj.__module__:
            module = obj.__module__

        if module:
            d = sys.modules[module].__dict__
            if name is None:
                names = sorted(key for key in d if d[key] is obj)
            else:
                names = [name]
            if names:
                if verbose and len(names) > 1:
                    print "  ** Warning **: several names for that object: %s" % ', '.join(
                        names)
                print_import_statement(module, names[0], lazy)
                continue

        # Case 3: search for this object in all modules
        names = {}  # dictionnary: module -> names of the object in that module
        for module in sys.modules:
            if module != '__main__' and hasattr(sys.modules[module],
                                                '__dict__'):
                d = sys.modules[module].__dict__

                if name is not None:
                    if name in d and d[name] is obj:
                        names[module] = name
                else:
                    n = [key for key in d if d[key] is obj]
                    if n:
                        names[module] = n

        all_names = sorted(set(flatten(names.values())))
        if len(all_names) == 0:
            raise ValueError("no import statement for %s" % obj)
        elif verbose and len(all_names) > 1:
            print "  ** Warning **: several names for that object:",
            print ", ".join(sorted(all_names))

        modules = sorted(flatten(names), cmp=module_names_cmp)
        if verbose and len(modules) > 1:
            print "  ** Warning **: several modules for that object:",
            print ", ".join(modules[:4]),
            if len(modules) > 4:
                print "..."
            else:
                print

        # Case 4: if the object is a class instance, we look for a
        # module where it is instanciated
        if sageinspect.isclassinstance(obj):
            names_pattern = dict(
                (name, re.compile("^%s\ *=" % name, re.MULTILINE))
                for name in all_names)

            for module in modules:
                sources = sageinspect.sage_getsource(sys.modules[module])
                for name in names[module]:
                    if names_pattern[name].search(sources):
                        break
                else:
                    continue
                break
        else:
            module = modules[0]
            name = names[module][0]

        if name is not None:
            print_import_statement(module, name, lazy)
        else:
            raise ValueError("no import statement for %s" % obj)