Beispiel #1
0
 def f(wrapper):
     update_wrapper(wrapper, wrapped, assigned=assigned, updated=updated)
     wrapper._sage_src_ = lambda: sage_getsource(wrapped)
     wrapper._sage_src_lines_ = lambda: sage_getsourcelines(wrapped)
     #Getting the signature right in documentation by Sphinx (Trac 9976)
     #The attribute _sage_argspec_() is read by Sphinx if present and used
     #as the argspec of the function instead of using reflection.
     wrapper._sage_argspec_ = lambda: sage_getargspec(wrapped)
     return wrapper
Beispiel #2
0
 def f(wrapper):
     update_wrapper(wrapper, wrapped, assigned=assigned, updated=updated)
     wrapper._sage_src_ = lambda: sage_getsource(wrapped)
     wrapper._sage_src_lines_ = lambda: sage_getsourcelines(wrapped)
     #Getting the signature right in documentation by Sphinx (Trac 9976)
     #The attribute _sage_argspec_() is read by Sphinx if present and used
     #as the argspec of the function instead of using reflection.
     wrapper._sage_argspec_ = lambda: sage_getargspec(wrapped)
     return wrapper
Beispiel #3
0
 def f(wrapper, assigned=assigned, updated=updated):
     update_wrapper(wrapper, wrapped, assigned=assigned, updated=updated)
     # For backwards-compatibility with old versions of sage_wraps
     wrapper.f = wrapped
     # For forwards-compatibility with functools.wraps on Python 3
     wrapper.__wrapped__ = wrapped
     wrapper._sage_src_ = lambda: sage_getsource(wrapped)
     wrapper._sage_src_lines_ = lambda: sage_getsourcelines(wrapped)
     #Getting the signature right in documentation by Sphinx (Trac 9976)
     #The attribute _sage_argspec_() is read by Sphinx if present and used
     #as the argspec of the function instead of using reflection.
     wrapper._sage_argspec_ = lambda: sage_getargspec(wrapped)
     return wrapper
Beispiel #4
0
    def _sage_src_(self):
        """
        Returns the source code for the wrapped function.

        EXAMPLES:
            sage: from sage.misc.sageinspect import sage_getsource
            sage: g = CachedFunction(number_of_partitions)
            sage: 'bober' in sage_getsource(g)
            True

        """
        from sage.misc.sageinspect import sage_getsource
        return sage_getsource(self.f)
Beispiel #5
0
    def _sage_src_(self):
        """
        Returns the source code for the wrapped function.

        EXAMPLES:
            sage: from sage.misc.sageinspect import sage_getsource
            sage: g = CachedFunction(number_of_partitions)
            sage: 'bober' in sage_getsource(g)
            True

        """
        from sage.misc.sageinspect import sage_getsource
        return sage_getsource(self.f)
Beispiel #6
0
    def _sage_src_(self):
        """
        Returns the source code for the wrapped function.

        EXAMPLES:

        This class is rather abstract so we showcase its features
        using one of its subclasses::

            sage: P.<x,y,z> = PolynomialRing(ZZ)
            sage: I = ideal( x^2 - 3*y, y^3 - x*y, z^3 - x, x^4 - y*z + 1 )
            sage: "primary" in I.primary_decomposition._sage_src_() # indirect doctest
            True
        """
        from sage.misc.sageinspect import sage_getsource
        return sage_getsource(self.f)
Beispiel #7
0
    def _sage_src_(self):
        """
        Returns the source code for the wrapped function.

        EXAMPLE:

        This class is rather abstract so we showcase its features
        using one of its subclasses::

            sage: P.<x,y,z> = PolynomialRing(ZZ)
            sage: I = ideal( x^2 - 3*y, y^3 - x*y, z^3 - x, x^4 - y*z + 1 )
            sage: "primary" in I.primary_decomposition._sage_src_() # indirect doctest
            True
        """
        from sage.misc.sageinspect import sage_getsource
        return sage_getsource(self.f)
Beispiel #8
0
    def _sage_src_(self):
        r"""
        Returns the source code for the wrapped function.

        TESTS::

            sage: from sage.misc.sageinspect import sage_getsource
            sage: from sage.sets.set_from_iterator import Decorator
            sage: d = Decorator()
            sage: d.f = Rational.is_square
            sage: print sage_getsource(d.f)   # indirect doctest
            def is_square(self):
            ...
                return mpq_sgn(self.value) >= 0 and mpz_perfect_square_p(mpq_numref(self.value)) and mpz_perfect_square_p(mpq_denref(self.value))
        """
        from sage.misc.sageinspect import sage_getsource
        return sage_getsource(self.f)
Beispiel #9
0
    def _sage_src_(self):
        r"""
        Returns the source code for the wrapped function.

        TESTS::

            sage: from sage.misc.sageinspect import sage_getsource
            sage: from sage.sets.set_from_iterator import Decorator
            sage: d = Decorator()
            sage: d.f = Rational.is_square
            sage: print(sage_getsource(d.f))   # indirect doctest
            def is_square(self):
            ...
                return mpq_sgn(self.value) >= 0 and mpz_perfect_square_p(mpq_numref(self.value)) and mpz_perfect_square_p(mpq_denref(self.value))
        """
        from sage.misc.sageinspect import sage_getsource
        return sage_getsource(self.f)
Beispiel #10
0
    def _sage_src_(self):
        """
        Returns the source code for this object, which is just the
        source code for the underlying function.  See
        :module:`sage.misc.sageinspect` for more information on this
        convention.

        EXAMPLES::

            sage: from sage.parallel.decorate import Parallel
            sage: p = Parallel(2)
            sage: def f(x, y):
            ...       return x + y
            sage: from sage.misc.sageinspect import sage_getsource
            sage: 'return x + y' in sage_getsource(p(f))
            True
        """
        from sage.misc.sageinspect import sage_getsource
        return sage_getsource(self.func)
Beispiel #11
0
    def _sage_src_(self):
        """
        Returns the source code for this object, which is just the
        source code for the underlying function.  See
        :module:`sage.misc.sageinspect` for more information on this
        convention.

        EXAMPLES::

            sage: from sage.parallel.decorate import Parallel
            sage: p = Parallel(2)
            sage: def f(x, y):
            ....:     return x + y
            sage: from sage.misc.sageinspect import sage_getsource
            sage: 'return x + y' in sage_getsource(p(f))
            True
        """
        from sage.misc.sageinspect import sage_getsource
        return sage_getsource(self.func)
Beispiel #12
0
    def __call__(self, func):
        """Returns a function which acts as an inline operator."""

        left_meth = self.operators[self.precedence]['left']
        right_meth = self.operators[self.precedence]['right']
        wrapper_name = func.__name__
        wrapper_members = {
            'function': staticmethod(func),
            left_meth: _infix_wrapper._left,
            right_meth: _infix_wrapper._right,
            '_sage_src_': lambda: sage_getsource(func)
        }
        for attr in WRAPPER_ASSIGNMENTS:
            try:
                wrapper_members[attr] = getattr(func, attr)
            except AttributeError:
                pass

        wrapper = type(wrapper_name, (_infix_wrapper, ), wrapper_members)

        wrapper_inst = wrapper()
        wrapper_inst.__dict__.update(getattr(func, '__dict__', {}))
        return wrapper_inst
Beispiel #13
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
Beispiel #14
0
    def __call__(self, func):
        """
        Returns a function which acts as an inline operator.

        EXAMPLES::

            sage: from sage.misc.decorators import infix_operator
            sage: def dot(a,b): return a.dot_product(b)
            sage: dot=infix_operator('multiply')(dot)
            sage: u=vector([1,2,3])
            sage: v=vector([5,4,3])
            sage: u *dot* v
            22

            sage: def eadd(a,b):
            ...     return a.parent([i+j for i,j in zip(a,b)])
            sage: eadd=infix_operator('add')(eadd)
            sage: u=vector([1,2,3])
            sage: v=vector([5,4,3])
            sage: u +eadd+ v
            (6, 6, 6)
            sage: 2*u +eadd+ v
            (7, 8, 9)

            sage: def thendo(a,b): return b(a)
            sage: thendo=infix_operator('or')(thendo)
            sage: x |thendo| cos |thendo| (lambda x: x^2)
            cos(x)^2
        """
        def left_func(self, right):
            """
            The function for the operation on the left (e.g., __add__).

            EXAMPLES::

                sage: def dot(a,b): return a.dot_product(b)
                sage: dot=infix_operator('multiply')(dot)
                sage: u=vector([1,2,3])
                sage: v=vector([5,4,3])
                sage: u *dot* v
                22
            """

            if self.left is None:
                if self.right is None:
                    new = copy(self)
                    new.right = right
                    return new
                else:
                    raise SyntaxError("Infix operator already has its "
                                      "right argument")
            else:
                return self.function(self.left, right)

        def right_func(self, left):
            """
            The function for the operation on the right (e.g., __radd__).

            EXAMPLES::

                sage: def dot(a,b): return a.dot_product(b)
                sage: dot=infix_operator('multiply')(dot)
                sage: u=vector([1,2,3])
                sage: v=vector([5,4,3])
                sage: u *dot* v
                22
            """
            if self.right is None:
                if self.left is None:
                    new = copy(self)
                    new.left = left
                    return new
                else:
                    raise SyntaxError("Infix operator already has its "
                                      "left argument")
            else:
                return self.function(left, self.right)

        @sage_wraps(func)
        class wrapper:
            def __init__(self, left=None, right=None):
                """
                Initialize the actual infix object, with possibly a
                specified left and/or right operand.

                EXAMPLES::

                    sage: def dot(a,b): return a.dot_product(b)
                    sage: dot=infix_operator('multiply')(dot)
                    sage: u=vector([1,2,3])
                    sage: v=vector([5,4,3])
                    sage: u *dot* v
                    22
                """

                self.function = func
                self.left = left
                self.right = right

            def __call__(self, *args, **kwds):
                """
                Call the passed function.

                EXAMPLES::

                    sage: def dot(a,b): return a.dot_product(b)
                    sage: dot=infix_operator('multiply')(dot)
                    sage: u=vector([1,2,3])
                    sage: v=vector([5,4,3])
                    sage: dot(u,v)
                    22
                """
                return self.function(*args, **kwds)

        setattr(wrapper, self.operators[self.precedence]['left'], left_func)
        setattr(wrapper, self.operators[self.precedence]['right'], right_func)

        wrapper._sage_src_ = lambda: sage_getsource(func)

        return wrapper()
Beispiel #15
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)
Beispiel #16
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)
Beispiel #17
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
Beispiel #18
0
    def __call__(self, func):
        """
        Returns a function which acts as an inline operator.

        EXAMPLES::

            sage: from sage.misc.decorators import infix_operator
            sage: def dot(a,b): return a.dot_product(b)
            sage: dot=infix_operator('multiply')(dot)
            sage: u=vector([1,2,3])
            sage: v=vector([5,4,3])
            sage: u *dot* v
            22

            sage: def eadd(a,b):
            ...     return a.parent([i+j for i,j in zip(a,b)])
            sage: eadd=infix_operator('add')(eadd)
            sage: u=vector([1,2,3])
            sage: v=vector([5,4,3])
            sage: u +eadd+ v
            (6, 6, 6)
            sage: 2*u +eadd+ v
            (7, 8, 9)

            sage: def thendo(a,b): return b(a)
            sage: thendo=infix_operator('or')(thendo)
            sage: x |thendo| cos |thendo| (lambda x: x^2)
            cos(x)^2
        """
        def left_func(self, right):
            """
            The function for the operation on the left (e.g., __add__).

            EXAMPLES::

                sage: def dot(a,b): return a.dot_product(b)
                sage: dot=infix_operator('multiply')(dot)
                sage: u=vector([1,2,3])
                sage: v=vector([5,4,3])
                sage: u *dot* v
                22
            """

            if self.left is None:
                if self.right is None:
                    new = copy(self)
                    new.right = right
                    return new
                else:
                    raise SyntaxError("Infix operator already has its "
                                      "right argument")
            else:
                return self.function(self.left, right)

        def right_func(self, left):
            """
            The function for the operation on the right (e.g., __radd__).

            EXAMPLES::

                sage: def dot(a,b): return a.dot_product(b)
                sage: dot=infix_operator('multiply')(dot)
                sage: u=vector([1,2,3])
                sage: v=vector([5,4,3])
                sage: u *dot* v
                22
            """
            if self.right is None:
                if self.left is None:
                    new = copy(self)
                    new.left = left
                    return new
                else:
                    raise SyntaxError("Infix operator already has its "
                                      "left argument")
            else:
                return self.function(left, self.right)

        @sage_wraps(func)
        class wrapper:
            def __init__(self, left=None, right=None):
                """
                Initialize the actual infix object, with possibly a
                specified left and/or right operand.

                EXAMPLES::

                    sage: def dot(a,b): return a.dot_product(b)
                    sage: dot=infix_operator('multiply')(dot)
                    sage: u=vector([1,2,3])
                    sage: v=vector([5,4,3])
                    sage: u *dot* v
                    22
                """

                self.function = func
                self.left = left
                self.right = right

            def __call__(self, *args, **kwds):
                """
                Call the passed function.

                EXAMPLES::

                    sage: def dot(a,b): return a.dot_product(b)
                    sage: dot=infix_operator('multiply')(dot)
                    sage: u=vector([1,2,3])
                    sage: v=vector([5,4,3])
                    sage: dot(u,v)
                    22
                """
                return self.function(*args, **kwds)

        setattr(wrapper, self.operators[self.precedence]['left'], left_func)
        setattr(wrapper, self.operators[self.precedence]['right'], right_func)

        wrapper._sage_src_ = lambda: sage_getsource(func)

        return wrapper()