Esempio n. 1
0
def SagePreparseTransformer(line):
    r"""
    EXAMPLES::

        sage: from sage.repl.interpreter import SagePreparseTransformer
        sage: spt = SagePreparseTransformer()
        sage: spt.push('1+1r+2.3^2.3r')
        "Integer(1)+1+RealNumber('2.3')**2.3"
        sage: preparser(False)
        sage: spt.push('2.3^2')
        '2.3^2'

    TESTS:

    Check that syntax errors in the preparser do not crash IPython,
    see :trac:`14961`. ::

        sage: preparser(True)
        sage: bad_syntax = "R.<t> = QQ{]"
        sage: preparse(bad_syntax)
        Traceback (most recent call last):
        ...
        SyntaxError: Mismatched ']'
        sage: from sage.repl.interpreter import get_test_shell
        sage: shell = get_test_shell()
        sage: shell.run_cell(bad_syntax)
          File "<string>", line unknown
        SyntaxError: Mismatched ']'
        <BLANKLINE>
        sage: shell.quit()
    """
    if _do_preparse and not line.startswith('%'):
        return preparse(line)
    else:
        return line
Esempio n. 2
0
def crun(s, evaluator):
    """
    Profile single statement.

    - ``s`` -- string. Sage code to profile.

    - ``evaluator`` -- callable to evaluate.

    EXAMPLES::

        sage: import sage.misc.gperftools as gperf
        sage: ev = lambda ex:eval(ex, globals(), locals())
        sage: gperf.crun('gperf.run_100ms()', evaluator=ev)   # optional - gperftools
        PROFILE: interrupts/evictions/bytes = ...
        Using local file ...
        Using local file ...
    """
    prof = Profiler()
    from sage.repl.preparse import preparse
    py_s = preparse(s)
    prof.start()
    try:
        evaluator(py_s)
    finally:
        prof.stop()
    prof.top()
Esempio n. 3
0
def crun(s, evaluator):
    """
    Profile single statement.

    - ``s`` -- string. Sage code to profile.

    - ``evaluator`` -- callable to evaluate.

    EXAMPLES::

        sage: import sage.misc.gperftools as gperf
        sage: ev = lambda ex:eval(ex, globals(), locals())
        sage: gperf.crun('gperf.run_100ms()', evaluator=ev)   # optional - gperftools
        PROFILE: interrupts/evictions/bytes = ...
        Using local file ...
        Using local file ...
    """
    prof = Profiler()
    from sage.repl.preparse import preparse
    py_s = preparse(s)
    prof.start()
    try:
        evaluator(py_s)
    finally:
        prof.stop()
    prof.top()
Esempio n. 4
0
def completions(s, globs, format=False, width=90, system="None"):
    """
    Return a list of completions in the given context.

    INPUT:

    - ``globs`` - a string:object dictionary; context in which to
      search for completions, e.g., :func:`globals()`

    - ``format`` - a bool (default: False); whether to tabulate the
      list
    
    - ``width`` - an int; character width of the table
    
    - ``system`` - a string (default: 'None'); system prefix for the
      completions

    OUTPUT:

    - a list of strings, if ``format`` is False, or a string
    """
    if system not in ['sage', 'python']:
        prepend = system + '.'
        s = prepend + s
    else:
        prepend = ''
    n = len(s)
    if n == 0:
        return '(empty string)'
    try:
        if not '.' in s and not '(' in s:
            v = [x for x in globs.keys() if x[:n] == s] + \
                [x for x in __builtins__.keys() if x[:n] == s] 
        else:
            if not ')' in s:
                i = s.rfind('.')
                method = s[i+1:]
                obj = s[:i]
                n = len(method)
            else:
                obj = preparse(s)
                method = ''
            try:
                O = eval(obj, globs)
                D = dir(O)
                try:
                    D += O.trait_names()
                except (AttributeError, TypeError):
                    pass
                if method == '':
                    v = [obj + '.'+x for x in D if x and x[0] != '_']
                else:
                    v = [obj + '.'+x for x in D if x[:n] == method]
            except Exception, msg:
                v = []
        v = list(set(v))   # make unique
        v.sort()
Esempio n. 5
0
    def preparse_imports_from_sage(self, line):
        """
        Finds occurrences of strings such as ``sage(object)`` in
        *line*, converts ``object`` to :attr:`shell.interface`,
        and replaces those strings with their identifier in the new
        system.  This also works with strings such as
        ``maxima(object)`` if :attr:`shell.interface` is
        ``maxima``.

        :param line: the line to transform
        :type line: string

        EXAMPLES::

            sage: from sage.repl.interpreter import interface_shell_embed, InterfaceShellTransformer
            sage: shell = interface_shell_embed(maxima)
            sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, prefilter_manager=shell.prefilter_manager)
            sage: ift.shell.ex('a = 3')
            sage: ift.preparse_imports_from_sage('2 + sage(a)')
            '2 + sage0 '
            sage: maxima.eval('sage0')
            '3'
            sage: ift.preparse_imports_from_sage('2 + maxima(a)') # maxima calls set_seed on startup which is why 'sage0' will becomes 'sage4' and not just 'sage1'
            '2 +  sage4 '
            sage: ift.preparse_imports_from_sage('2 + gap(a)')
            '2 + gap(a)'

        Since :trac:`28439`, this also works with more complicated expressions
        containing nested parentheses::

            sage: shell = interface_shell_embed(gap)
            sage: shell.user_ns = locals()
            sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, prefilter_manager=shell.prefilter_manager)
            sage: line = '2 + sage((1+2)*gap(-(5-3)^2).sage()) - gap(1+(2-1))'
            sage: line = ift.preparse_imports_from_sage(line)
            sage: gap.eval(line)
            '-12'
        """
        new_line = []
        pos = 0
        while True:
            m = self._sage_import_re.search(line, pos)
            if not m:
                new_line.append(line[pos:])
                break
            expr_start, expr_end = containing_block(line,
                                                    m.end() - 1,
                                                    delimiters=['()'])
            expr = preparse(line[expr_start + 1:expr_end - 1])
            result = self.shell.interface(eval(expr, self.shell.user_ns))
            self.temporary_objects.add(result)
            new_line += [line[pos:m.start()], result.name()]
            pos = expr_end
        return ' '.join(new_line)
Esempio n. 6
0
def runsnake(command):
    """
    Graphical profiling with ``runsnake``

    INPUT:

    - ``command`` -- the command to be run as a string.

    EXAMPLES::

        sage: runsnake("list(SymmetricGroup(3))")        # optional - runsnake

    ``command`` is first preparsed (see :func:`preparse`)::

        sage: runsnake('for x in range(1,4): print(x^2)') # optional - runsnake
        1
        4
        9

    :func:`runsnake` requires the program ``runsnake``. Due to non
    trivial dependencies (python-wxgtk, ...), installing it within the
    Sage distribution is unpractical. Hence, we recommend installing
    it with the system wide Python. On Ubuntu 10.10, this can be done
    with::

        > sudo apt-get install python-profiler python-wxgtk2.8 python-setuptools
        > sudo easy_install RunSnakeRun

    See the ``runsnake`` website for instructions for other platforms.

    :func:`runsnake` further assumes that the system wide Python is
    installed in ``/usr/bin/python``.

    .. SEEALSO::

        - `The runsnake website <http://www.vrplumber.com/programming/runsnakerun/>`_
        - ``%prun``
        - :class:`Profiler`

    """
    import cProfile
    import os
    from sage.misc.temporary_file import tmp_filename
    from sage.misc.misc import get_main_globals
    from sage.repl.preparse import preparse
    tmpfile = tmp_filename()
    cProfile.runctx(preparse(command.lstrip().rstrip()),
                    get_main_globals(),
                    locals(),
                    filename=tmpfile)
    os.system("/usr/bin/python -E `which runsnake` %s &" % tmpfile)
Esempio n. 7
0
def SagePreparseTransformer(lines):
    r"""
    EXAMPLES::

        sage: from sage.repl.interpreter import SagePreparseTransformer
        sage: spt = SagePreparseTransformer
        sage: spt(['1+1r+2.3^2.3r\n'])
        ["Integer(1)+1+RealNumber('2.3')**2.3\n"]
        sage: preparser(False)
        sage: spt(['2.3^2\n'])
        ['2.3^2\n']

    TESTS:

    Check that syntax errors in the preparser do not crash IPython,
    see :trac:`14961`. ::

        sage: preparser(True)
        sage: bad_syntax = "R.<t> = QQ{]"
        sage: preparse(bad_syntax)
        Traceback (most recent call last):
        ...
        SyntaxError: Mismatched ']'
        sage: from sage.repl.interpreter import get_test_shell
        sage: shell = get_test_shell()
        sage: shell.run_cell(bad_syntax)
          File "<string>", line unknown
        SyntaxError: Mismatched ']'
        <BLANKLINE>
        sage: shell.quit()

    Make sure the quote state is carried over across subsequent lines in order
    to avoid interfering with multi-line strings, see :trac:`30417`. ::

        sage: SagePreparseTransformer(["'''\n", 'abc-1-2\n', "'''\n"])
        ["'''\n", 'abc-1-2\n', "'''\n"]
        sage: # instead of ["'''\n", 'abc-Integer(1)-Integer(2)\n', "'''\n"]

    .. NOTE::

        IPython may call this function more than once for the same input lines.
        So when debugging the preparser, print outs may be duplicated. If using
        IPython >= 7.17, try:
        ``sage.repl.interpreter.SagePreparseTransformer.has_side_effects = True``

    """
    if _do_preparse:
        # IPython ensures the input lines end with a newline, and it expects
        # the same of the output lines.
        lines = preparse(''.join(lines)).splitlines(keepends=True)
    return lines
Esempio n. 8
0
 def handle(self):
     print(f'Request from {self.client_address}')
     err_lvl = ErrLvl.OKAY
     err_msg = None
     result = None
     # self.request is the TCP socket connected to the client
     conn = DmlSocket(sock=self.request)
     try:
         msg = conn.recvall_str()
     except Exception as e:
         err_lvl = ErrLvl.RECV
         err_msg = str(e)
         err_msg += '\n' + traceback.format_exc()
     if err_lvl == ErrLvl.OKAY:
         try:
             parsed = preparse(msg)
         except Exception as e:
             err_lvl = ErrLvl.PREPARSE
             err_msg = str(e)
             err_msg += '\n' + "*" * 40
             err_msg += '\n*** Received message: ***'
             err_msg += '\n' + "*" * 40
             err_msg += '\n' + msg
             err_msg += '\n' + "*" * 40
             err_msg += '\n\n' + traceback.format_exc()
     if err_lvl == ErrLvl.OKAY:
         # Redirect stdout to my stdout to capture into a string
         sys.stdout = mystdout = StringIO()
         try:
             eval(compile(parsed, '<cmdline>', 'exec'))
             result = mystdout.getvalue().strip(
             )  # Get result from mystdout
         except Exception as e:
             err_lvl = ErrLvl.EXECUTE
             err_msg = str(e)
             err_msg += '\n' + "*" * 40
             err_msg += '\n*** Pre-parsed Sage Code: ***'
             err_msg += '\n' + "*" * 40
             err_msg += '\n' + parsed
             err_msg += '\n' + "*" * 40
             err_msg += '\n\n' + traceback.format_exc()
         # Restore stdout
         sys.stdout = sys.__stdout__
     response = {
         'err_lvl': err_lvl,
         'err_msg': err_msg,
         'result': result,
     }
     resp_j = json.dumps(response)
     conn.sendall_str(resp_j)
Esempio n. 9
0
def SagePreparseTransformer(lines):
    r"""
    EXAMPLES::

        sage: from sage.repl.interpreter import SagePreparseTransformer
        sage: spt = SagePreparseTransformer
        sage: spt(['1+1r+2.3^2.3r'])
        ["Integer(1)+1+RealNumber('2.3')**2.3"]
        sage: preparser(False)
        sage: spt(['2.3^2'])
        ['2.3^2']

    TESTS:

    Check that syntax errors in the preparser do not crash IPython,
    see :trac:`14961`. ::

        sage: preparser(True)
        sage: bad_syntax = "R.<t> = QQ{]"
        sage: preparse(bad_syntax)
        Traceback (most recent call last):
        ...
        SyntaxError: Mismatched ']'
        sage: from sage.repl.interpreter import get_test_shell
        sage: shell = get_test_shell()
        sage: shell.run_cell(bad_syntax)
          File "<string>", line unknown
        SyntaxError: Mismatched ']'
        <BLANKLINE>
        sage: shell.quit()

    Make sure the quote state is carried over across subsequent lines in order
    to avoid interfering with multi-line strings, see :trac:`30417`. ::

        sage: SagePreparseTransformer(["'''", 'abc-1-2', "'''"])
        ["'''", 'abc-1-2', "'''"]
        sage: # instead of ["'''", 'abc-Integer(1)-Integer(2)', "'''"]

    """
    lines_out = []
    reset = True
    for line in lines:
        if _do_preparse and not line.startswith('%'):
            lines_out += [preparse(line, reset=reset)]
            reset = False
        else:
            lines_out += [line]
    return lines_out
Esempio n. 10
0
def runsnake(command):
    """
    Graphical profiling with ``runsnake``

    INPUT:

    - ``command`` -- the command to be run as a string.

    EXAMPLES::

        sage: runsnake("list(SymmetricGroup(3))")        # optional - runsnake

    ``command`` is first preparsed (see :func:`preparse`)::

        sage: runsnake('for x in range(1,4): print(x^2)') # optional - runsnake
        1
        4
        9

    :func:`runsnake` requires the program ``runsnake``. Due to non
    trivial dependencies (python-wxgtk, ...), installing it within the
    Sage distribution is unpractical. Hence, we recommend installing
    it with the system wide Python. On Ubuntu 10.10, this can be done
    with::

        > sudo apt-get install python-profiler python-wxgtk2.8 python-setuptools
        > sudo easy_install RunSnakeRun

    See the ``runsnake`` website for instructions for other platforms.

    :func:`runsnake` further assumes that the system wide Python is
    installed in ``/usr/bin/python``.

    .. seealso::

        - `The runsnake website <http://www.vrplumber.com/programming/runsnakerun/>`_
        - ``%prun``
        - :class:`Profiler`

    """
    import cProfile
    import os
    from sage.misc.temporary_file import tmp_filename
    from sage.misc.misc import get_main_globals
    from sage.repl.preparse import preparse
    tmpfile = tmp_filename()
    cProfile.runctx(preparse(command.lstrip().rstrip()), get_main_globals(), locals(), filename=tmpfile)
    os.system("/usr/bin/python -E `which runsnake` %s &" % tmpfile)
Esempio n. 11
0
    def preparse_imports_from_sage(self, line):
        """
        Finds occurrences of strings such as ``sage(object)`` in
        *line*, converts ``object`` to :attr:`shell.interface`,
        and replaces those strings with their identifier in the new
        system.  This also works with strings such as
        ``maxima(object)`` if :attr:`shell.interface` is
        ``maxima``.

        :param line: the line to transform
        :type line: string

        .. warning::

            This does not parse nested parentheses correctly.  Thus,
            lines like ``sage(a.foo())`` will not work correctly.
            This can't be done in generality with regular expressions.

        EXAMPLES::

            sage: from sage.repl.interpreter import interface_shell_embed, InterfaceShellTransformer
            sage: shell = interface_shell_embed(maxima)
            sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, prefilter_manager=shell.prefilter_manager)
            sage: ift.shell.ex('a = 3')
            sage: ift.preparse_imports_from_sage('2 + sage(a)')
            '2 + sage0 '
            sage: maxima.eval('sage0')
            '3'
            sage: ift.preparse_imports_from_sage('2 + maxima(a)')
            '2 +  sage1 '
            sage: ift.preparse_imports_from_sage('2 + gap(a)')
            '2 + gap(a)'
        """
        for sage_code in self._sage_import_re.findall(line):
            expr = preparse(sage_code)
            result = self.shell.interface(eval(expr, self.shell.user_ns))
            self.temporary_objects.add(result)
            line = self._sage_import_re.sub(' ' + result.name() + ' ', line, 1)
        return line
Esempio n. 12
0
    def parse(self, string, *args):
        r"""
        A Sage specialization of :class:`doctest.DocTestParser`.

        INPUT:

        - ``string`` -- the string to parse.
        - ``name`` -- optional string giving the name identifying string,
          to be used in error messages.

        OUTPUT:

        - A list consisting of strings and :class:`doctest.Example`
          instances.  There will be at least one string between
          successive examples (exactly one unless or long or optional
          tests are removed), and it will begin and end with a string.

        EXAMPLES::

            sage: from sage.doctest.parsing import SageDocTestParser
            sage: DTP = SageDocTestParser(True, ('sage','magma','guava'))
            sage: example = 'Explanatory text::\n\n    sage: E = magma("EllipticCurve([1, 1, 1, -10, -10])") # optional: magma\n\nLater text'
            sage: parsed = DTP.parse(example)
            sage: parsed[0]
            'Explanatory text::\n\n'
            sage: parsed[1].sage_source
            'E = magma("EllipticCurve([1, 1, 1, -10, -10])") # optional: magma\n'
            sage: parsed[2]
            '\nLater text'

        If the doctest parser is not created to accept a given
        optional argument, the corresponding examples will just be
        removed::

            sage: DTP2 = SageDocTestParser(True, ('sage',))
            sage: parsed2 = DTP2.parse(example)
            sage: parsed2
            ['Explanatory text::\n\n', '\nLater text']

        You can mark doctests as having a particular tolerance::

            sage: example2 = 'sage: gamma(1.6) # tol 2.0e-11\n0.893515349287690'
            sage: ex = DTP.parse(example2)[1]
            sage: ex.sage_source
            'gamma(1.6) # tol 2.0e-11\n'
            sage: ex.want
            u'0.893515349287690\n'
            sage: type(ex.want)
            <class 'sage.doctest.parsing.MarkedOutput'>
            sage: ex.want.tol
            2.000000000000000000?e-11

        You can use continuation lines::

            sage: s = "sage: for i in range(4):\n....:     print(i)\n....:\n"
            sage: ex = DTP2.parse(s)[1]
            sage: ex.source
            'for i in range(Integer(4)):\n    print(i)\n'

        Sage currently accepts backslashes as indicating that the end
        of the current line should be joined to the next line.  This
        feature allows for breaking large integers over multiple lines
        but is not standard for Python doctesting.  It's not
        guaranteed to persist, but works in Sage 5.5::

            sage: n = 1234\
            ....:     5678
            sage: print(n)
            12345678
            sage: type(n)
            <type 'sage.rings.integer.Integer'>

        It also works without the line continuation::

            sage: m = 8765\
            4321
            sage: print(m)
            87654321
        """
        # Hack for non-standard backslash line escapes accepted by the current
        # doctest system.
        m = backslash_replacer.search(string)
        while m is not None:
            next_prompt = find_sage_prompt.search(string,m.end())
            g = m.groups()
            if next_prompt:
                future = string[m.end():next_prompt.start()] + '\n' + string[next_prompt.start():]
            else:
                future = string[m.end():]
            string = string[:m.start()] + g[0] + "sage:" + g[1] + future
            m = backslash_replacer.search(string,m.start())

        string = find_sage_prompt.sub(r"\1>>> sage: ", string)
        string = find_sage_continuation.sub(r"\1...", string)
        res = doctest.DocTestParser.parse(self, string, *args)
        filtered = []
        for item in res:
            if isinstance(item, doctest.Example):
                optional_tags = parse_optional_tags(item.source)
                if optional_tags:
                    for tag in optional_tags:
                        self.optionals[tag] += 1
                    if (('not implemented' in optional_tags) or
                            ('not tested' in optional_tags)):
                        continue

                    if 'long time' in optional_tags:
                        if self.long:
                            optional_tags.remove('long time')
                        else:
                            continue

                    if self.optional_tags is not True:
                        extra = optional_tags - self.optional_tags # set difference
                        if extra:
                            if not('external' in self.optional_tags
                                   and available_software.issuperset(extra)):
                                continue
                elif self.optional_only:
                    self.optionals['sage'] += 1
                    continue
                item.want = parse_tolerance(item.source, item.want)
                if item.source.startswith("sage: "):
                    item.sage_source = item.source[6:]
                    if item.sage_source.lstrip().startswith('#'):
                        continue
                    item.source = preparse(item.sage_source)
            filtered.append(item)
        return filtered
Esempio n. 13
0
File: trace.py Progetto: drupel/sage
def trace(code, preparse=True):
    r"""
    Evaluate Sage code using the interactive tracer and return the
    result. The string ``code`` must be a valid expression
    enclosed in quotes (no assignments - the result of the expression
    is returned). In the Sage notebook this just raises a
    NotImplementedException.

    INPUT:


    -  ``code`` - str

    -  ``preparse`` - bool (default: True); if True, run
       expression through the Sage preparser.


    REMARKS: This function is extremely powerful! For example, if you
    want to step through each line of execution of, e.g.,
    ``factor(100)``, type

    ::

        sage: trace("factor(100)")             # not tested

    then at the (Pdb) prompt type ``s`` (or ``step``), then press return
    over and over to step through every line of Python that is called
    in the course of the above computation. Type ``?`` at any time for
    help on how to use the debugger (e.g., ``l`` lists 11 lines around
    the current line; ``bt`` gives a back trace, etc.).

    Setting a break point: If you have some code in a file and would
    like to drop into the debugger at a given point, put the following
    code at that point in the file:

    ``import pdb; pdb.set_trace()``

    For an article on how to use the Python debugger, see
    http://www.onlamp.com/pub/a/python/2005/09/01/debugger.html

    TESTS:

    The only real way to test this is via pexpect spawning a
    sage subprocess that uses IPython.

    ::

        sage: import pexpect
        sage: s = pexpect.spawn('sage')
        sage: _ = s.sendline("trace('print(factor(10))'); print(3+97)")
        sage: _ = s.sendline("s"); _ = s.sendline("c");
        sage: _ = s.expect('100', timeout=90)

    Seeing the ipdb prompt and the 2 \* 5 in the output below is a
    strong indication that the trace command worked correctly.

    ::

        sage: print(s.before[s.before.find('--'):])
        --...
        ipdb> c
        2 * 5

    We test what happens in notebook embedded mode::

        sage: sage.plot.plot.EMBEDDED_MODE = True
        sage: trace('print(factor(10))')
        Traceback (most recent call last):
        ...
        NotImplementedError: the trace command is not implemented in the Sage notebook; you must use the command line.
    """
    from sage.plot.plot import EMBEDDED_MODE
    if EMBEDDED_MODE:
        raise NotImplementedError("the trace command is not implemented in the Sage notebook; you must use the command line.")

    from IPython.core.debugger import Pdb
    pdb = Pdb()

    try:
        ipython = get_ipython()
    except NameError:
        raise NotImplementedError("the trace command can only be run from the Sage command-line")

    from sage.repl.preparse import preparse
    code = preparse(code)
    return pdb.run(code, ipython.user_ns)
Esempio n. 14
0
def parse_p_adic(s):
	s = s.strip().replace(' ','')
	
	#Try to read p-adic number as:
	#<expression of rational number> + O(p^e)
	cQp = re.compile(r'^([\+\-\*/\^\d]*)\+O\((\d+)\^(\-?\d+)\)$')
	matchQp = cQp.match(s)
	if matchQp != None:
		#Given searchterm is a p-adic number:
		a, p, e = matchQp.groups()
		p = ZZ(p)
		e = ZZ(e)
		#print("a,p,e:",a,p,e)
		#print("preparse(a):",preparse(a))
		A = eval(preparse(a))
		#print("A:",A)
		prec = e + min(0,-A.valuation(p))
		Q_p = Qp(p,prec=prec)
		result = Q_p(A).add_bigoh(e)
		return result

	#Try to read p-adic number as:
	#O(p^e)
	cQp = re.compile(r'^O\((\d+)\^(\-?\d+)\)$')
	matchQp = cQp.match(s)
	if matchQp != None:
		#Given searchterm is a p-adic number:
		p, e = matchQp.groups()
		p = ZZ(p)
		e = ZZ(e)
		prec = e
		Q_p = Qp(p,prec=prec)
		result = Q_p(0).add_bigoh(e)
		return result
	
	#Try to read p-adic number as:
	#Qp:digits	
	cQp2 = re.compile(r'^[qQzZ](\d+)[: ](\-?)((?:\d*\.)?)(\d*)$')
	matchQp2 = cQp2.match(s)
	if matchQp2 != None:
		p, sign, digits0, digits1 = matchQp2.groups()
		lenp = ZZ(len(p))
		p = ZZ(p)
		print("p,sign,digits0,digits1:",p,sign,digits0,digits1)
		print("lenp:",lenp)
		lend0 = ZZ(len(digits0))
		lend1 = ZZ(len(digits1))
		if lend0 % lenp == 0 and lend1 % lenp == 0:
			num_digits0 = ZZ(lend0/lenp)
			num_digits1 = ZZ(lend1/lenp)
			prec = num_digits0 + num_digits1
			Q_p = Qp(p, prec = prec)
			result = Q_p(0)
			for i in range(num_digits0):
				print(i,ZZ(digits0[lenp*i:lenp*(i+1)]))
				result += Q_p(ZZ(digits0[lenp*i:lenp*(i+1)]) * p**(i-num_digits0))
			for i in range(num_digits1):
				print(i,ZZ(digits1[lenp*i:lenp*(i+1)]))
				result += Q_p(ZZ(digits1[lenp*i:lenp*(i+1)]) * p**i)
			result = result.add_bigoh(num_digits1)
			if sign == '-':
				result = -result
			print("result:",result)
			return result
		
	return None	
Esempio n. 15
0
    def parse(self, string, *args):
        r"""
        A Sage specialization of :class:`doctest.DocTestParser`.

        INPUT:

        - ``string`` -- the string to parse.
        - ``name`` -- optional string giving the name identifying string,
          to be used in error messages.

        OUTPUT:

        - A list consisting of strings and :class:`doctest.Example`
          instances.  There will be at least one string between
          successive examples (exactly one unless or long or optional
          tests are removed), and it will begin and end with a string.

        EXAMPLES::

            sage: from sage.doctest.parsing import SageDocTestParser
            sage: DTP = SageDocTestParser(('sage','magma','guava'))
            sage: example = 'Explanatory text::\n\n    sage: E = magma("EllipticCurve([1, 1, 1, -10, -10])") # optional: magma\n\nLater text'
            sage: parsed = DTP.parse(example)
            sage: parsed[0]
            'Explanatory text::\n\n'
            sage: parsed[1].sage_source
            'E = magma("EllipticCurve([1, 1, 1, -10, -10])") # optional: magma\n'
            sage: parsed[2]
            '\nLater text'

        If the doctest parser is not created to accept a given
        optional argument, the corresponding examples will just be
        removed::

            sage: DTP2 = SageDocTestParser(('sage',))
            sage: parsed2 = DTP2.parse(example)
            sage: parsed2
            ['Explanatory text::\n\n', '\nLater text']

        You can mark doctests as having a particular tolerance::

            sage: example2 = 'sage: gamma(1.6) # tol 2.0e-11\n0.893515349287690'
            sage: ex = DTP.parse(example2)[1]
            sage: ex.sage_source
            'gamma(1.6) # tol 2.0e-11\n'
            sage: ex.want
            u'0.893515349287690\n'
            sage: type(ex.want)
            <class 'sage.doctest.parsing.MarkedOutput'>
            sage: ex.want.tol
            2.000000000000000000...?e-11

        You can use continuation lines::

            sage: s = "sage: for i in range(4):\n....:     print(i)\n....:\n"
            sage: ex = DTP2.parse(s)[1]
            sage: ex.source
            'for i in range(Integer(4)):\n    print(i)\n'

        Sage currently accepts backslashes as indicating that the end
        of the current line should be joined to the next line.  This
        feature allows for breaking large integers over multiple lines
        but is not standard for Python doctesting.  It's not
        guaranteed to persist, but works in Sage 5.5::

            sage: n = 1234\
            ....:     5678
            sage: print(n)
            12345678
            sage: type(n)
            <type 'sage.rings.integer.Integer'>

        It also works without the line continuation::

            sage: m = 8765\
            4321
            sage: print(m)
            87654321

        Test that :trac:`26575` is resolved::

            sage: example3 = 'sage: Zp(5,4,print_mode="digits")(5)\n...00010'
            sage: parsed3 = DTP.parse(example3)
            sage: dte = parsed3[1]
            sage: dte.sage_source
            'Zp(5,4,print_mode="digits")(5)\n'
            sage: dte.want
            '...00010\n'
        """
        # Hack for non-standard backslash line escapes accepted by the current
        # doctest system.
        m = backslash_replacer.search(string)
        while m is not None:
            next_prompt = find_sage_prompt.search(string, m.end())
            g = m.groups()
            if next_prompt:
                future = string[m.end():next_prompt.start(
                )] + '\n' + string[next_prompt.start():]
            else:
                future = string[m.end():]
            string = string[:m.start()] + g[0] + "sage:" + g[1] + future
            m = backslash_replacer.search(string, m.start())

        replace_ellipsis = not python_prompt.search(string)
        if replace_ellipsis:
            # There are no >>> prompts, so we can allow ... to begin the output
            # We do so by replacing ellipses with a special tag, then putting them back after parsing
            string = find_python_continuation.sub(r"\1" + ellipsis_tag + r"\2",
                                                  string)
        string = find_sage_prompt.sub(r"\1>>> sage: ", string)
        string = find_sage_continuation.sub(r"\1...", string)
        res = doctest.DocTestParser.parse(self, string, *args)
        filtered = []
        for item in res:
            if isinstance(item, doctest.Example):
                optional_tags = parse_optional_tags(item.source)
                if optional_tags:
                    for tag in optional_tags:
                        self.optionals[tag] += 1
                    if (('not implemented' in optional_tags)
                            or ('not tested' in optional_tags)):
                        continue

                    if 'long time' in optional_tags:
                        if self.long:
                            optional_tags.remove('long time')
                        else:
                            continue

                    if self.optional_tags is not True:
                        extra = optional_tags - self.optional_tags  # set difference
                        if extra:
                            if not ('external' in self.optional_tags
                                    and available_software.issuperset(extra)):
                                continue
                elif self.optional_only:
                    self.optionals['sage'] += 1
                    continue
                if replace_ellipsis:
                    item.want = item.want.replace(ellipsis_tag, "...")
                    if item.exc_msg is not None:
                        item.exc_msg = item.exc_msg.replace(
                            ellipsis_tag, "...")
                item.want = parse_tolerance(item.source, item.want)
                if item.source.startswith("sage: "):
                    item.sage_source = item.source[6:]
                    if item.sage_source.lstrip().startswith('#'):
                        continue
                    item.source = preparse(item.sage_source)
            filtered.append(item)
        return filtered
Esempio n. 16
0
def trace(code, preparse=True):
    r"""
    Evaluate Sage code using the interactive tracer and return the
    result. The string ``code`` must be a valid expression
    enclosed in quotes (no assignments - the result of the expression
    is returned). In the Sage notebook this just raises a
    NotImplementedException.

    INPUT:


    -  ``code`` - str

    -  ``preparse`` - bool (default: True); if True, run
       expression through the Sage preparser.


    REMARKS: This function is extremely powerful! For example, if you
    want to step through each line of execution of, e.g.,
    ``factor(100)``, type

    ::

        sage: trace("factor(100)")             # not tested

    then at the (Pdb) prompt type ``s`` (or ``step``), then press return
    over and over to step through every line of Python that is called
    in the course of the above computation. Type ``?`` at any time for
    help on how to use the debugger (e.g., ``l`` lists 11 lines around
    the current line; ``bt`` gives a back trace, etc.).

    Setting a break point: If you have some code in a file and would
    like to drop into the debugger at a given point, put the following
    code at that point in the file:

    ``import pdb; pdb.set_trace()``

    For an article on how to use the Python debugger, see
    http://www.onlamp.com/pub/a/python/2005/09/01/debugger.html

    TESTS:

    For tests we disable garbage collection, see :trac:`21258` ::

        sage: import gc
        sage: gc.disable()

    The only real way to test this is via pexpect spawning a
    sage subprocess that uses IPython::

        sage: import pexpect
        sage: s = pexpect.spawn('sage')
        sage: _ = s.sendline("trace('print(factor(10))'); print(3+97)")
        sage: _ = s.expect('ipdb>', timeout=90)
        sage: _ = s.sendline("s"); _ = s.sendline("c")
        sage: _ = s.expect('100', timeout=90)

    Seeing the ipdb prompt and the 2 \* 5 in the output below is a
    strong indication that the trace command worked correctly::

        sage: print(s.before[s.before.find(b'--'):].decode())
        --...
        ipdb> c
        2 * 5

    We test what happens in notebook embedded mode::

        sage: sage.plot.plot.EMBEDDED_MODE = True
        sage: trace('print(factor(10))')
        Traceback (most recent call last):
        ...
        NotImplementedError: the trace command is not implemented in the Sage notebook; you must use the command line.

    Re-enable garbage collection::

        sage: gc.enable()
    """
    from sage.plot.plot import EMBEDDED_MODE
    if EMBEDDED_MODE:
        raise NotImplementedError(
            "the trace command is not implemented in the Sage notebook; you must use the command line."
        )

    from IPython.core.debugger import Pdb
    pdb = Pdb()

    try:
        ipython = get_ipython()
    except NameError:
        raise NotImplementedError(
            "the trace command can only be run from the Sage command-line")

    from sage.repl.preparse import preparse
    code = preparse(code)
    return pdb.run(code, ipython.user_ns)
Esempio n. 17
0
def sage_eval(source, locals=None, cmds='', preparse=True):
    r"""
    Obtain a Sage object from the input string by evaluating it using
    Sage. This means calling eval after preparsing and with globals
    equal to everything included in the scope of ``from sage.all
    import *``.).

    INPUT:


    -  ``source`` - a string or object with a _sage_
       method

    -  ``locals`` - evaluate in namespace of sage.all plus
       the locals dictionary

    -  ``cmds`` - string; sequence of commands to be run
       before source is evaluated.

    -  ``preparse`` - (default: True) if True, preparse the
       string expression.


    EXAMPLES: This example illustrates that preparsing is applied.

    ::

        sage: eval('2^3')
        1
        sage: sage_eval('2^3')
        8

    However, preparsing can be turned off.

    ::

        sage: sage_eval('2^3', preparse=False)
        1

    Note that you can explicitly define variables and pass them as the
    second option::

        sage: x = PolynomialRing(RationalField(),"x").gen()
        sage: sage_eval('x^2+1', locals={'x':x})
        x^2 + 1

    This example illustrates that evaluation occurs in the context of
    ``from sage.all import *``. Even though bernoulli has
    been redefined in the local scope, when calling
    ``sage_eval`` the default value meaning of bernoulli
    is used. Likewise for QQ below.

    ::

        sage: bernoulli = lambda x : x^2
        sage: bernoulli(6)
        36
        sage: eval('bernoulli(6)')
        36
        sage: sage_eval('bernoulli(6)')
        1/42

    ::

        sage: QQ = lambda x : x^2
        sage: QQ(2)
        4
        sage: sage_eval('QQ(2)')
        2
        sage: parent(sage_eval('QQ(2)'))
        Rational Field

    This example illustrates setting a variable for use in evaluation.

    ::

        sage: x = 5
        sage: eval('4/3 + x', {'x': 25})  # py2
        26
        sage: eval('4//3 + x', {'x': 25})  # py3
        26
        sage: sage_eval('4/3 + x',  locals={'x': 25})
        79/3

    You can also specify a sequence of commands to be run before the
    expression is evaluated::

        sage: sage_eval('p', cmds='K.<x> = QQ[]\np = x^2 + 1')
        x^2 + 1

    If you give commands to execute and a dictionary of variables, then
    the dictionary will be modified by assignments in the commands::

        sage: vars = {}
        sage: sage_eval('None', cmds='y = 3', locals=vars)
        sage: vars['y'], parent(vars['y'])
        (3, Integer Ring)

    You can also specify the object to evaluate as a tuple. A 2-tuple
    is assumed to be a pair of a command sequence and an expression; a
    3-tuple is assumed to be a triple of a command sequence, an
    expression, and a dictionary holding local variables. (In this
    case, the given dictionary will not be modified by assignments in
    the commands.)

    ::

        sage: sage_eval(('f(x) = x^2', 'f(3)'))
        9
        sage: vars = {'rt2': sqrt(2.0)}
        sage: sage_eval(('rt2 += 1', 'rt2', vars))
        2.41421356237309
        sage: vars['rt2']
        1.41421356237310

    This example illustrates how ``sage_eval`` can be
    useful when evaluating the output of other computer algebra
    systems.

    ::

        sage: R.<x> = PolynomialRing(RationalField())
        sage: gap.eval('R:=PolynomialRing(Rationals,["x"]);')
        'Rationals[x]'
        sage: ff = gap.eval('x:=IndeterminatesOfPolynomialRing(R);; f:=x^2+1;'); ff
        'x^2+1'
        sage: sage_eval(ff, locals={'x':x})
        x^2 + 1
        sage: eval(ff)
        Traceback (most recent call last):
        ...
        RuntimeError: Use ** for exponentiation, not '^', which means xor
        in Python, and has the wrong precedence.

    Here you can see eval simply will not work but
    ``sage_eval`` will.

    TESTS:

    We get a nice minimal error message for syntax errors, that still
    points to the location of the error (in the input string)::

        sage: sage_eval('RR(22/7]')
        Traceback (most recent call last):
        ...
         File "<string>", line 1
            RR(Integer(22)/Integer(7)]
                                     ^
        SyntaxError: unexpected EOF while parsing

    ::

        sage: sage_eval('None', cmds='$x = $y[3] # Does Perl syntax work?')
        Traceback (most recent call last):
        ...
         File "<string>", line 1
            $x = $y[Integer(3)] # Does Perl syntax work?
            ^
        SyntaxError: invalid syntax
    """
    if isinstance(source, (list, tuple)):
        cmds = source[0]
        if len(source) > 2:
            locals = copy(source[2])
        source = source[1]

    if not isinstance(source, six.string_types):
        raise TypeError("source must be a string.")

    if locals is None:
        locals = {}

    import sage.all
    if len(cmds):
        cmd_seq = cmds + '\n_sage_eval_returnval_ = ' + source
        if preparse:
            cmd_seq = preparser.preparse_file(cmd_seq)
    else:
        if preparse:
            source = preparser.preparse(source)

    if len(cmds):
        exec(cmd_seq, sage.all.__dict__, locals)
        return locals['_sage_eval_returnval_']
    else:
        return eval(source, sage.all.__dict__, locals)
Esempio n. 18
0
def sage_timeit(stmt, globals_dict=None, preparse=None, number=0, repeat=3, precision=3, seconds=False):
    """nodetex
    Accurately measure the wall time required to execute ``stmt``.

    INPUT:

    - ``stmt`` -- a text string.

    - ``globals_dict`` -- a dictionary or ``None`` (default). Evaluate
      ``stmt`` in the context of the globals dictionary. If not set,
      the current ``globals()`` dictionary is used.

    - ``preparse`` -- (default: use globals preparser default) if
      ``True`` preparse ``stmt`` using the Sage preparser.

    - ``number`` -- integer, (optional, default: 0), number of loops.

    - ``repeat`` -- integer, (optional, default: 3), number of
      repetition.

    - ``precision`` -- integer, (optional, default: 3), precision of
      output time.

    - ``seconds`` -- boolean (default: ``False``). Whether to just
      return time in seconds.

    OUTPUT:

    An instance of ``SageTimeitResult`` unless the optional parameter
    ``seconds=True`` is passed. In that case, the elapsed time in
    seconds is returned as a floating-point number.

    EXAMPLES::

        sage: from sage.misc.sage_timeit import sage_timeit
        sage: sage_timeit('3^100000', globals(), preparse=True, number=50)      # random output
        '50 loops, best of 3: 1.97 ms per loop'
        sage: sage_timeit('3^100000', globals(), preparse=False, number=50)     # random output
        '50 loops, best of 3: 67.1 ns per loop'
        sage: a = 10
        sage: sage_timeit('a^2', globals(), number=50)                            # random output
        '50 loops, best of 3: 4.26 us per loop'

    If you only want to see the timing and not have access to additional
    information, just use the ``timeit`` object::

        sage: timeit('10^2', number=50)
        50 loops, best of 3: ... per loop

    Using sage_timeit gives you more information though::

        sage: s = sage_timeit('10^2', globals(), repeat=1000)
        sage: len(s.series)
        1000
        sage: mean(s.series)   # random output
        3.1298141479492283e-07
        sage: min(s.series)    # random output
        2.9258728027343752e-07
        sage: t = stats.TimeSeries(s.series)
        sage: t.scale(10^6).plot_histogram(bins=20,figsize=[12,6], ymax=2)
        Graphics object consisting of 20 graphics primitives


    The input expression can contain newlines (but doctests cannot, so
    we use ``os.linesep`` here)::

        sage: from sage.misc.sage_timeit import sage_timeit
        sage: from os import linesep as CR
        sage: # sage_timeit(r'a = 2\\nb=131\\nfactor(a^b-1)')
        sage: sage_timeit('a = 2' + CR + 'b=131' + CR + 'factor(a^b-1)',
        ....:             globals(), number=10)
        10 loops, best of 3: ... per loop

    Test to make sure that ``timeit`` behaves well with output::

        sage: timeit("print 'Hi'", number=50)
        50 loops, best of 3: ... per loop

    If you want a machine-readable output, use the ``seconds=True`` option::

        sage: timeit("print 'Hi'", seconds=True)   # random output
        1.42555236816e-06
        sage: t = timeit("print 'Hi'", seconds=True)
        sage: t     #r random output
        3.6010742187499999e-07

    TESTS:

    Make sure that garbage collection is re-enabled after an exception
    occurs in timeit::

        sage: def f(): raise ValueError
        sage: import gc
        sage: gc.isenabled()
        True
        sage: timeit("f()")
        Traceback (most recent call last):
        ...
        ValueError
        sage: gc.isenabled()
        True
    """
    import time, math
    import timeit as timeit_

    import sage.repl.interpreter as interpreter
    import sage.repl.preparse as preparser

    number=int(number)
    repeat=int(repeat)
    precision=int(precision)
    if preparse is None:
        preparse = interpreter._do_preparse
    if preparse:
        stmt = preparser.preparse(stmt)
    if stmt == "":
        return ''

    units = ["s", "ms", "\xc2\xb5s", "ns"]
    scaling = [1, 1e3, 1e6, 1e9]

    timer = timeit_.Timer()

    # this code has tight coupling to the inner workings of timeit.Timer,
    # but is there a better way to achieve that the code stmt has access
    # to the shell namespace?

    src = timeit_.template % {'stmt': timeit_.reindent(stmt, 8),
                             'setup': "pass", 'init' : ''}
    code = compile(src, "<magic-timeit>", "exec")
    ns = {}
    if not globals_dict:
        globals_dict = globals()
    exec(code, globals_dict, ns)
    timer.inner = ns["inner"]


    try:
        import sys
        f = sys.stdout
        sys.stdout = open('/dev/null', 'w')

        if number == 0:
            # determine number so that 0.2 <= total time < 2.0
            number = 1
            for i in range(1, 5):
                number *= 5
                if timer.timeit(number) >= 0.2:
                    break

        series = [s/number for s in timer.repeat(repeat, number)]
        best = min(series)

    finally:
        sys.stdout.close()
        sys.stdout = f
        import gc
        gc.enable()

    if seconds:
        return best

    if best > 0.0:
        order = min(-int(math.floor(math.log10(best)) // 3), 3)
    else:
        order = 3
    stats = (number, repeat, precision, best * scaling[order], units[order])
    return SageTimeitResult(stats,series=series)
Esempio n. 19
0
def sage_timeit(stmt, globals_dict=None, preparse=None, number=0, repeat=3, precision=3, seconds=False):
    """nodetex
    Accurately measure the wall time required to execute ``stmt``.

    INPUT:

    - ``stmt`` -- a text string.

    - ``globals_dict`` -- a dictionary or ``None`` (default). Evaluate
      ``stmt`` in the context of the globals dictionary. If not set,
      the current ``globals()`` dictionary is used.

    - ``preparse`` -- (default: use globals preparser default) if
      ``True`` preparse ``stmt`` using the Sage preparser.

    - ``number`` -- integer, (optional, default: 0), number of loops.

    - ``repeat`` -- integer, (optional, default: 3), number of
      repetition.

    - ``precision`` -- integer, (optional, default: 3), precision of
      output time.

    - ``seconds`` -- boolean (default: ``False``). Whether to just
      return time in seconds.

    OUTPUT:

    An instance of ``SageTimeitResult`` unless the optional parameter
    ``seconds=True`` is passed. In that case, the elapsed time in
    seconds is returned as a floating-point number.

    EXAMPLES::

        sage: from sage.misc.sage_timeit import sage_timeit
        sage: sage_timeit('3^100000', globals(), preparse=True, number=50)      # random output
        '50 loops, best of 3: 1.97 ms per loop'
        sage: sage_timeit('3^100000', globals(), preparse=False, number=50)     # random output
        '50 loops, best of 3: 67.1 ns per loop'
        sage: a = 10
        sage: sage_timeit('a^2', globals(), number=50)                            # random output
        '50 loops, best of 3: 4.26 us per loop'

    If you only want to see the timing and not have access to additional
    information, just use the ``timeit`` object::

        sage: timeit('10^2', number=50)
        50 loops, best of 3: ... per loop

    Using sage_timeit gives you more information though::

        sage: s = sage_timeit('10^2', globals(), repeat=1000)
        sage: len(s.series)
        1000
        sage: mean(s.series)   # random output
        3.1298141479492283e-07
        sage: min(s.series)    # random output
        2.9258728027343752e-07
        sage: t = stats.TimeSeries(s.series)
        sage: t.scale(10^6).plot_histogram(bins=20,figsize=[12,6], ymax=2)
        Graphics object consisting of 20 graphics primitives


    The input expression can contain newlines (but doctests cannot, so
    we use ``os.linesep`` here)::

        sage: from sage.misc.sage_timeit import sage_timeit
        sage: from os import linesep as CR
        sage: # sage_timeit(r'a = 2\\nb=131\\nfactor(a^b-1)')
        sage: sage_timeit('a = 2' + CR + 'b=131' + CR + 'factor(a^b-1)',
        ....:             globals(), number=10)
        10 loops, best of 3: ... per loop

    Test to make sure that ``timeit`` behaves well with output::

        sage: timeit("print('Hi')", number=50)
        50 loops, best of 3: ... per loop

    If you want a machine-readable output, use the ``seconds=True`` option::

        sage: timeit("print('Hi')", seconds=True)   # random output
        1.42555236816e-06
        sage: t = timeit("print('Hi')", seconds=True)
        sage: t     #r random output
        3.6010742187499999e-07

    TESTS:

    Make sure that garbage collection is re-enabled after an exception
    occurs in timeit::

        sage: def f(): raise ValueError
        sage: import gc
        sage: gc.isenabled()
        True
        sage: timeit("f()")
        Traceback (most recent call last):
        ...
        ValueError
        sage: gc.isenabled()
        True
    """
    import time, math
    import timeit as timeit_

    import sage.repl.interpreter as interpreter
    import sage.repl.preparse as preparser

    number = int(number)
    repeat = int(repeat)
    precision = int(precision)
    if preparse is None:
        preparse = interpreter._do_preparse
    if preparse:
        stmt = preparser.preparse(stmt)
    if stmt == "":
        return ''

    units = ["s", "ms", "\xc2\xb5s", "ns"]
    scaling = [1, 1e3, 1e6, 1e9]

    timer = timeit_.Timer()

    # this code has tight coupling to the inner workings of timeit.Timer,
    # but is there a better way to achieve that the code stmt has access
    # to the shell namespace?

    if six.PY2:
        src = timeit_.template % {'stmt': timeit_.reindent(stmt, 8),
                                 'setup': "pass", 'init': ''}
    else:
        src = timeit_.template.format(stmt=timeit_.reindent(stmt, 8),
                                      setup="pass", init='')
    code = compile(src, "<magic-timeit>", "exec")
    ns = {}
    if not globals_dict:
        globals_dict = globals()
    exec(code, globals_dict, ns)
    timer.inner = ns["inner"]


    try:
        import sys
        f = sys.stdout
        sys.stdout = open('/dev/null', 'w')

        if number == 0:
            # determine number so that 0.2 <= total time < 2.0
            number = 1
            for i in range(1, 5):
                number *= 5
                if timer.timeit(number) >= 0.2:
                    break

        series = [s/number for s in timer.repeat(repeat, number)]
        best = min(series)

    finally:
        sys.stdout.close()
        sys.stdout = f
        import gc
        gc.enable()

    if seconds:
        return best

    if best > 0.0:
        order = min(-int(math.floor(math.log10(best)) // 3), 3)
    else:
        order = 3
    stats = (number, repeat, precision, best * scaling[order], units[order])
    return SageTimeitResult(stats,series=series)