Пример #1
0
def preparse_worksheet_cell(s, globals):
    """
    Preparse the contents of a worksheet cell in the notebook,
    respecting the user using ``preparser(False)`` to turn off the
    preparser.  This function calls
    :func:`~sage.repl.preparse.preparse_file` which also reloads
    attached files.  It also does displayhook formatting by calling
    the :func:`~sagenb.notebook.interfaces.format.displayhook_hack`
    function.

    INPUT:

    - ``s`` - a string containing code

    - ``globals`` - a string:object dictionary; passed directly to
      :func:`~sage.repl.preparse.preparse_file`

    OUTPUT:

        - a string
    """
    if do_preparse():
        s = preparse_file(s, globals=globals)
    s = displayhook_hack(s)
    if _automatic_names:
        s = automatic_name_filter(s)
    return s
Пример #2
0
    def get_data(self, filename):
        """exec_module is already defined for us, we just have to provide a way
        of getting the source code of the module"""
        filename = os.path.abspath(filename)
        with open(filename) as f:
            contents = f.read()

        from sage.repl.preparse import handle_encoding_declaration, preparse_file
        #contents = handle_encoding_declaration(contents, out)
        parsed = preparse_file(contents)
        print(f'🐰 Importing {filename} via Sage preparser')
        header = '''from sage.all import *
'''
        return header + parsed
Пример #3
0
def load(filename, globals, attach=False):
    r"""
    Execute a file in the scope given by ``globals``. If the name starts with
    ``http://`` or ``https://``, it is treated as a URL and downloaded.

    .. NOTE::

        For Cython files, the situation is more complicated --
        the module is first compiled to a temporary module ``t`` and
        executed via::

            from t import *

    INPUT:

    - ``filename`` -- a string denoting a filename or URL.

    - ``globals`` -- a string:object dictionary; the context in which
      to execute the file contents.

    - ``attach`` -- a boolean (default: False); whether to add the
      file to the list of attached files.

    Loading an executable Sage script from the command prompt will run whatever
    code is inside an

        if __name__ == "__main__":

    section, as the condition on ``__name__`` will hold true (code run from the
    command prompt is considered to be running in the ``__main__`` module.)

    EXAMPLES:

    Note that ``.py`` files are *not* preparsed::

        sage: t = tmp_filename(ext='.py')
        sage: with open(t, 'w') as f:
        ....:     _ = f.write("print(('hi', 2^3)); z = -2^7")
        sage: z = 1
        sage: sage.repl.load.load(t, globals())
        ('hi', 1)
        sage: z
        -7

    A ``.sage`` file *is* preparsed::

        sage: t = tmp_filename(ext='.sage')
        sage: with open(t, 'w') as f:
        ....:     _ = f.write("print(('hi', 2^3)); z = -2^7")
        sage: z = 1
        sage: sage.repl.load.load(t, globals())
        ('hi', 8)
        sage: z
        -128

    Cython files are *not* preparsed::

        sage: t = tmp_filename(ext='.pyx')
        sage: with open(t, 'w') as f:
        ....:     _ = f.write("print(('hi', 2^3)); z = -2^7")
        sage: z = 1
        sage: sage.repl.load.load(t, globals())
        Compiling ...
        ('hi', 1)
        sage: z
        -7

    If the file is not a Cython, Python, or Sage file, a ``ValueError``
    is raised::

        sage: sage.repl.load.load(tmp_filename(ext=".foo"), globals())
        Traceback (most recent call last):
        ...
        ValueError: unknown file extension '.foo' for load or attach (supported extensions: .py, .pyx, .sage, .spyx, .f, .f90, .m)

    We load a file given at a remote URL (not tested for security reasons)::

        sage: sage.repl.load.load('https://www.sagemath.org/files/loadtest.py', globals())  # not tested
        hi from the net
        5

    We can load files using secure http (https)::

        sage: sage.repl.load.load('https://raw.githubusercontent.com/sagemath/sage-patchbot/3.0.0/sage_patchbot/util.py', globals())  # optional - internet

    We attach a file::

        sage: t = tmp_filename(ext='.py')
        sage: with open(t, 'w') as f:
        ....:     _ = f.write("print('hello world')")
        sage: sage.repl.load.load(t, globals(), attach=True)
        hello world
        sage: t in attached_files()
        True

    You cannot attach remote URLs (yet)::

        sage: sage.repl.load.load('https://www.sagemath.org/files/loadtest.py', globals(), attach=True)  # optional - internet
        Traceback (most recent call last):
        ...
        NotImplementedError: you cannot attach a URL

    The default search path for loading and attaching files is the
    current working directory, i.e., ``'.'``.  But you can modify the
    path with :func:`load_attach_path`::

        sage: sage.repl.attach.reset(); reset_load_attach_path()
        sage: load_attach_path()
        ['.']
        sage: t_dir = tmp_dir()
        sage: fname = 'test.py'
        sage: fullpath = os.path.join(t_dir, fname)
        sage: with open(fullpath, 'w') as f:
        ....:     _ = f.write("print(37 * 3)")
        sage: load_attach_path(t_dir, replace=True)
        sage: attach(fname)
        111
        sage: sage.repl.attach.reset(); reset_load_attach_path() # clean up

    or by setting the environment variable ``SAGE_LOAD_ATTACH_PATH``
    to a colon-separated list before starting Sage::

        $ export SAGE_LOAD_ATTACH_PATH="/path/to/my/library:/path/to/utils"
        $ sage
        sage: load_attach_path()          # not tested
        ['.', '/path/to/my/library', '/path/to/utils']

    TESTS:

    Make sure that load handles filenames with spaces in the name or path::

        sage: t = tmp_filename(ext=' b.sage')
        sage: with open(t, 'w') as f:
        ....:     _ = f.write("print(2)")
        sage: sage.repl.load.load(t, globals())
        2

    Non-existing files with spaces give correct messages::

        sage: sage.repl.load.load("this file should not exist", globals())
        Traceback (most recent call last):
        ...
        OSError: did not find file 'this file should not exist' to load or attach
    """
    if attach:
        from sage.repl.attach import add_attached_file

    if isinstance(filename, bytes):
        # For Python 3 in particular, convert bytes filenames to str since the
        # rest of this functions operate on filename as a str
        filename = bytes_to_str(filename, FS_ENCODING, 'surrogateescape')

    filename = os.path.expanduser(filename)

    if filename.lower().startswith(('http://', 'https://')):
        if attach:
            # But see https://en.wikipedia.org/wiki/HTTP_ETag for how
            # we will do this.
            # http://www.diveintopython.net/http_web_services/etags.html
            raise NotImplementedError("you cannot attach a URL")
        from sage.misc.remote_file import get_remote_file
        filename = get_remote_file(filename, verbose=False)

    from sage.repl.attach import load_attach_path
    for path in load_attach_path():
        fpath = os.path.join(path, filename)
        fpath = os.path.expanduser(fpath)
        if os.path.isfile(fpath):
            break
    else:
        raise IOError('did not find file %r to load or attach' % filename)

    ext = os.path.splitext(fpath)[1].lower()
    if ext == '.py':
        if attach:
            add_attached_file(fpath)
        with open(fpath) as f:
            code = compile(f.read(), fpath, 'exec')
            exec(code, globals)
    elif ext == '.sage':
        from sage.repl.attach import load_attach_mode
        from sage.repl.preparse import preparse_file_named, preparse_file
        load_debug_mode, attach_debug_mode = load_attach_mode()
        if (attach and attach_debug_mode) or ((not attach) and load_debug_mode):
            # Preparse to a file to enable tracebacks with
            # code snippets. Use preparse_file_named to make
            # the file name appear in the traceback as well.
            # See Trac 11812.
            if attach:
                add_attached_file(fpath)
            with open(preparse_file_named(fpath)) as f:
                code = compile(f.read(), preparse_file_named(fpath), 'exec')
                exec(code, globals)
        else:
            # Preparse in memory only for speed.
            if attach:
                add_attached_file(fpath)
            with open(fpath) as f:
                exec(preparse_file(f.read()) + "\n", globals)
    elif ext == '.spyx' or ext == '.pyx':
        if attach:
            add_attached_file(fpath)
        exec(load_cython(fpath), globals)
    elif ext == '.f' or ext == '.f90':
        from sage.misc.inline_fortran import fortran
        with open(fpath) as f:
            fortran(f.read(), globals)
    elif ext == '.m':
        # Assume magma for now, though maybe .m is used by maple and
        # mathematica too, and we should really analyze the file
        # further.
        s = globals['magma'].load(fpath)
        i = s.find('\n')
        print(s[i + 1:])
    else:
        raise ValueError('unknown file extension %r for load or attach (supported extensions: .py, .pyx, .sage, .spyx, .f, .f90, .m)' % ext)
Пример #4
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)
Пример #5
0
def load(filename, globals, attach=False):
    r"""
    Executes a file in the scope given by ``globals``.  If the name
    starts with ``http://``, it is treated as a URL and downloaded.

    .. NOTE::

        For Cython files, the situation is more complicated --
        the module is first compiled to a temporary module ``t`` and
        executed via::

            from t import *

    INPUT:

    - ``filename`` -- a string denoting a filename or URL.

    - ``globals`` -- a string:object dictionary; the context in which
      to execute the file contents.

    - ``attach`` -- a boolean (default: False); whether to add the
      file to the list of attached files.

    EXAMPLES:

    Note that ``.py`` files are *not* preparsed::

        sage: t = tmp_filename(ext='.py')
        sage: with open(t, 'w') as f:
        ....:     _ = f.write("print(('hi', 2^3)); z = -2^7")
        sage: z = 1
        sage: sage.repl.load.load(t, globals())
        ('hi', 1)
        sage: z
        -7

    A ``.sage`` file *is* preparsed::

        sage: t = tmp_filename(ext='.sage')
        sage: with open(t, 'w') as f:
        ....:     _ = f.write("print(('hi', 2^3)); z = -2^7")
        sage: z = 1
        sage: sage.repl.load.load(t, globals())
        ('hi', 8)
        sage: z
        -128

    Cython files are *not* preparsed::

        sage: t = tmp_filename(ext='.pyx')
        sage: with open(t, 'w') as f:
        ....:     _ = f.write("print(('hi', 2^3)); z = -2^7")
        sage: z = 1
        sage: sage.repl.load.load(t, globals())
        Compiling ...
        ('hi', 1)
        sage: z
        -7

    If the file isn't a Cython, Python, or a Sage file, a ValueError
    is raised::

        sage: sage.repl.load.load(tmp_filename(ext=".foo"), globals())
        Traceback (most recent call last):
        ...
        ValueError: unknown file extension '.foo' for load or attach (supported extensions: .py, .pyx, .sage, .spyx, .f, .f90, .m)

    We load a file given at a remote URL::

        sage: sage.repl.load.load('http://wstein.org/loadtest.py', globals())  # optional - internet
        hi from the net
        5

    We can load files using secure http (https)::

        sage: sage.repl.load.load('https://github.com/jasongrout/minimum_rank/raw/minimum_rank_1_0_0/minrank.py', globals())  # optional - internet

    We attach a file::

        sage: t = tmp_filename(ext='.py')
        sage: with open(t, 'w') as f:
        ....:     _ = f.write("print('hello world')")
        sage: sage.repl.load.load(t, globals(), attach=True)
        hello world
        sage: t in attached_files()
        True

    You can't attach remote URLs (yet)::

        sage: sage.repl.load.load('http://wstein.org/loadtest.py', globals(), attach=True)  # optional - internet
        Traceback (most recent call last):
        ...
        NotImplementedError: you can't attach a URL

    The default search path for loading and attaching files is the
    current working directory, i.e., ``'.'``.  But you can modify the
    path with :func:`load_attach_path`::

        sage: sage.repl.attach.reset(); reset_load_attach_path()
        sage: load_attach_path()
        ['.']
        sage: t_dir = tmp_dir()
        sage: fname = 'test.py'
        sage: fullpath = os.path.join(t_dir, fname)
        sage: with open(fullpath, 'w') as f:
        ....:     _ = f.write("print(37 * 3)")
        sage: load_attach_path(t_dir)
        sage: attach(fname)
        111
        sage: sage.repl.attach.reset(); reset_load_attach_path() # clean up

    or by setting the environment variable ``SAGE_LOAD_ATTACH_PATH``
    to a colon-separated list before starting Sage::

        $ export SAGE_LOAD_ATTACH_PATH="/path/to/my/library:/path/to/utils"
        $ sage
        sage: load_attach_path()          # not tested
        ['.', '/path/to/my/library', '/path/to/utils']

    TESTS:

    Make sure that load handles filenames with spaces in the name or path::

        sage: t = tmp_filename(ext=' b.sage')
        sage: with open(t, 'w') as f:
        ....:     _ = f.write("print(2)")
        sage: sage.repl.load.load(t, globals())
        2

    Non-existing files with spaces give correct messages::

        sage: sage.repl.load.load("this file should not exist", globals())
        Traceback (most recent call last):
        ...
        IOError: did not find file 'this file should not exist' to load or attach
    """
    if attach:
        from sage.repl.attach import add_attached_file

    if isinstance(filename, bytes):
        # For Python 3 in particular, convert bytes filenames to str since the
        # rest of this functions operate on filename as a str
        filename = bytes_to_str(filename, FS_ENCODING, 'surrogateescape')

    filename = os.path.expanduser(filename)

    if filename.lower().startswith(('http://', 'https://')):
        if attach:
            # But see https://en.wikipedia.org/wiki/HTTP_ETag for how
            # we will do this.
            # http://www.diveintopython.net/http_web_services/etags.html
            raise NotImplementedError("you can't attach a URL")
        from sage.misc.remote_file import get_remote_file
        filename = get_remote_file(filename, verbose=False)

    from sage.repl.attach import load_attach_path
    for path in load_attach_path():
        fpath = os.path.join(path, filename)
        fpath = os.path.expanduser(fpath)
        if os.path.isfile(fpath):
            break
    else:
        raise IOError('did not find file %r to load or attach' % filename)

    ext = os.path.splitext(fpath)[1].lower()
    if ext == '.py':
        if attach:
            add_attached_file(fpath)
        with open(fpath) as f:
            code = compile(f.read(), fpath, 'exec')
            exec(code, globals)
    elif ext == '.sage':
        from sage.repl.attach import load_attach_mode
        from sage.repl.preparse import preparse_file_named, preparse_file
        load_debug_mode, attach_debug_mode = load_attach_mode()
        if (attach and attach_debug_mode) or ((not attach) and load_debug_mode):
            # Preparse to a file to enable tracebacks with
            # code snippets. Use preparse_file_named to make
            # the file name appear in the traceback as well.
            # See Trac 11812.
            if attach:
                add_attached_file(fpath)
            with open(preparse_file_named(fpath)) as f:
                code = compile(f.read(), preparse_file_named(fpath), 'exec')
                exec(code, globals)
        else:
            # Preparse in memory only for speed.
            if attach:
                add_attached_file(fpath)
            with open(fpath) as f:
                exec(preparse_file(f.read()) + "\n", globals)
    elif ext == '.spyx' or ext == '.pyx':
        if attach:
            add_attached_file(fpath)
        exec(load_cython(fpath), globals)
    elif ext == '.f' or ext == '.f90':
        from sage.misc.inline_fortran import fortran
        with open(fpath) as f:
            fortran(f.read(), globals)
    elif ext == '.m':
        # Assume magma for now, though maybe .m is used by maple and
        # mathematica too, and we should really analyze the file
        # further.
        s = globals['magma'].load(fpath)
        i = s.find('\n'); s = s[i+1:]
        print(s)
    else:
        raise ValueError('unknown file extension %r for load or attach (supported extensions: .py, .pyx, .sage, .spyx, .f, .f90, .m)' % ext)
Пример #6
0
def load(filename, globals, attach=False):
    r"""
    Executes a file in the scope given by ``globals``.  If the name
    starts with ``http://``, it is treated as a URL and downloaded.

    .. NOTE::

        For Cython files, the situation is more complicated --
        the module is first compiled to a temporary module ``t`` and
        executed via::

            from t import *

    INPUT:

    - ``filename`` -- a string denoting a filename or URL.

    - ``globals`` -- a string:object dictionary; the context in which
      to execute the file contents.

    - ``attach`` -- a boolean (default: False); whether to add the
      file to the list of attached files.

    EXAMPLES:

    Note that ``.py`` files are *not* preparsed::

        sage: t = tmp_filename(ext='.py')
        sage: open(t,'w').write("print 'hi', 2/3; z = -2/7")
        sage: z = 1
        sage: sage.repl.load.load(t, globals())  # optional - python2
        hi 0
        sage: z  # optional - python2
        -1

    A ``.sage`` file *is* preparsed::

        sage: t = tmp_filename(ext='.sage')
        sage: open(t,'w').write("print 'hi', 2/3; z = -2/7")
        sage: z = 1
        sage: sage.repl.load.load(t, globals())
        hi 2/3
        sage: z
        -2/7

    Cython files are *not* preparsed::

        sage: t = tmp_filename(ext='.pyx')
        sage: open(t,'w').write("print 'hi', 2/3; z = -2/7")
        sage: z = 1
        sage: sage.repl.load.load(t, globals())
        Compiling ...
        hi 0
        sage: z
        -1

    If the file isn't a Cython, Python, or a Sage file, a ValueError
    is raised::

        sage: sage.repl.load.load(tmp_filename(ext=".foo"), globals())
        Traceback (most recent call last):
        ...
        ValueError: unknown file extension '.foo' for load or attach (supported extensions: .py, .pyx, .sage, .spyx, .f, .f90, .m)

    We load a file given at a remote URL::

        sage: sage.repl.load.load('http://wstein.org/loadtest.py', globals())  # optional - internet
        hi from the net
        5

    We can load files using secure http (https)::

        sage: sage.repl.load.load('https://github.com/jasongrout/minimum_rank/raw/minimum_rank_1_0_0/minrank.py', globals())  # optional - internet

    We attach a file::

        sage: t = tmp_filename(ext='.py')
        sage: open(t,'w').write("print 'hello world'")
        sage: sage.repl.load.load(t, globals(), attach=True)
        hello world
        sage: t in attached_files()
        True

    You can't attach remote URLs (yet)::

        sage: sage.repl.load.load('http://wstein.org/loadtest.py', globals(), attach=True)  # optional - internet
        Traceback (most recent call last):
        ...
        NotImplementedError: you can't attach a URL

    The default search path for loading and attaching files is the
    current working directory, i.e., ``'.'``.  But you can modify the
    path with :func:`load_attach_path`::

        sage: sage.repl.attach.reset(); reset_load_attach_path()
        sage: load_attach_path()
        ['.']
        sage: t_dir = tmp_dir()
        sage: fullpath = os.path.join(t_dir, 'test.py')
        sage: open(fullpath, 'w').write("print 37 * 3")
        sage: load_attach_path(t_dir)
        sage: attach('test.py')
        111
        sage: sage.repl.attach.reset(); reset_load_attach_path() # clean up

    or by setting the environment variable ``SAGE_LOAD_ATTACH_PATH``
    to a colon-separated list before starting Sage::

        $ export SAGE_LOAD_ATTACH_PATH="/path/to/my/library:/path/to/utils"
        $ sage
        sage: load_attach_path()          # not tested
        ['.', '/path/to/my/library', '/path/to/utils']

    TESTS:

    Make sure that load handles filenames with spaces in the name or path::

        sage: t = tmp_filename(ext=' b.sage'); open(t,'w').write("print 2")
        sage: sage.repl.load.load(t, globals())
        2

    Non-existing files with spaces give correct messages::

        sage: sage.repl.load.load("this file should not exist", globals())
        Traceback (most recent call last):
        ...
        IOError: did not find file 'this file should not exist' to load or attach
    """
    if attach:
        from sage.repl.attach import add_attached_file

    filename = os.path.expanduser(filename)

    if filename.lower().startswith(('http://', 'https://')):
        if attach:
            # But see http://en.wikipedia.org/wiki/HTTP_ETag for how
            # we will do this.
            # http://www.diveintopython.net/http_web_services/etags.html
            raise NotImplementedError("you can't attach a URL")
        from sage.misc.remote_file import get_remote_file
        filename = get_remote_file(filename, verbose=False)

    from sage.repl.attach import load_attach_path
    for path in load_attach_path():
        fpath = os.path.join(path, filename)
        fpath = os.path.expanduser(fpath)
        if os.path.isfile(fpath):
            break
    else:
        raise IOError('did not find file %r to load or attach' % filename)

    ext = os.path.splitext(fpath)[1].lower()
    if ext == '.py':
        if attach:
            add_attached_file(fpath)
        with open(fpath) as f:
            code = compile(f.read(), fpath, 'exec')
            exec(code, globals)
    elif ext == '.sage':
        from sage.repl.attach import load_attach_mode
        from sage.repl.preparse import preparse_file_named, preparse_file
        load_debug_mode, attach_debug_mode = load_attach_mode()
        if (attach and attach_debug_mode) or ((not attach)
                                              and load_debug_mode):
            # Preparse to a file to enable tracebacks with
            # code snippets. Use preparse_file_named to make
            # the file name appear in the traceback as well.
            # See Trac 11812.
            if attach:
                add_attached_file(fpath)
            with open(preparse_file_named(fpath)) as f:
                code = compile(f.read(), preparse_file_named(fpath), 'exec')
                exec(code, globals)
        else:
            # Preparse in memory only for speed.
            if attach:
                add_attached_file(fpath)
            exec(preparse_file(open(fpath).read()) + "\n", globals)
    elif ext == '.spyx' or ext == '.pyx':
        if attach:
            add_attached_file(fpath)
        exec(load_cython(fpath), globals)
    elif ext == '.f' or ext == '.f90':
        from sage.misc.inline_fortran import fortran
        with open(fpath) as f:
            fortran(f.read(), globals)
    elif ext == '.m':
        # Assume magma for now, though maybe .m is used by maple and
        # mathematica too, and we should really analyze the file
        # further.
        s = globals['magma'].load(fpath)
        i = s.find('\n')
        s = s[i + 1:]
        print(s)
    else:
        raise ValueError(
            'unknown file extension %r for load or attach (supported extensions: .py, .pyx, .sage, .spyx, .f, .f90, .m)'
            % ext)
Пример #7
0
def load(filename, globals, attach=False):
    """
    Executes a file in the scope given by ``globals``.  The
    ``filename`` itself is also evaluated in the scope.  If the name
    starts with ``http://``, it is treated as a URL and downloaded.

    .. NOTE::

        For Cython files, the situation is more complicated --
        the module is first compiled to a temporary module ``t`` and
        executed via::

            from t import *

    INPUT:

    - ``filename`` -- a string; a .py, .sage, .pyx, etc., filename,
      URL, or expression that evaluates to one

    - ``globals`` -- a string:object dictionary; the context in which
      to evaluate the ``filename`` and exec its contents

    - ``attach`` -- a boolean (default: False); whether to add the
      file to the list of attached files

    EXAMPLES:

    Note that ``.py`` files are *not* preparsed::

        sage: t = tmp_filename(ext='.py')
        sage: open(t,'w').write("print 'hi', 2/3; z = -2/7")
        sage: z = 1
        sage: sage.repl.load.load(t, globals())
        hi 0
        sage: z
        -1

    A ``.sage`` file *is* preparsed::

        sage: t = tmp_filename(ext='.sage')
        sage: open(t,'w').write("print 'hi', 2/3; z = -2/7")
        sage: z = 1
        sage: sage.repl.load.load(t, globals())
        hi 2/3
        sage: z
        -2/7

    Cython files are *not* preparsed::

        sage: t = tmp_filename(ext='.pyx')
        sage: open(t,'w').write("print 'hi', 2/3; z = -2/7")
        sage: z = 1
        sage: sage.repl.load.load(t, globals())
        Compiling ...
        hi 0
        sage: z
        -1

    If the file isn't a Cython, Python, or a Sage file, a ValueError
    is raised::

        sage: sage.repl.load.load('a.foo',globals())
        Traceback (most recent call last):
        ...
        ValueError: argument (='a.foo') to load or attach must have extension py, pyx, sage, spyx, or m

    A filename given as an expression get evaluated.  This ensures
    that ``load DATA+'foo.sage'`` works in the Notebook, say::

        sage: t=tmp_filename(ext='.py'); open(t,'w').write("print 'hello world'")
        sage: sage.repl.load.load(t, globals())
        hello world

    We load a file given at a remote URL::

        sage: sage.repl.load.load('http://wstein.org/loadtest.py', globals())  # optional - internet
        hi from the net
        5

    We can load files using secure http (https)::

        sage: sage.repl.load.load('https://github.com/jasongrout/minimum_rank/raw/minimum_rank_1_0_0/minrank.py', globals())  # optional - internet

    We attach a file::

        sage: t = tmp_filename(ext='.py')
        sage: open(t,'w').write("print 'hello world'")
        sage: sage.repl.load.load(t, globals(), attach=True)
        hello world
        sage: t in attached_files()
        True

    You can't attach remote URLs (yet)::

        sage: sage.repl.load.load('http://wstein.org/loadtest.py', globals(), attach=True)  # optional - internet
        Traceback (most recent call last):
        ...
        NotImplementedError: you can't attach a URL

    The default search path for loading and attaching files is the
    current working directory, i.e., ``'.'``.  But you can modify the
    path with :func:`load_attach_path`::

        sage: sage.repl.attach.reset(); reset_load_attach_path()
        sage: load_attach_path()
        ['.']
        sage: t_dir = tmp_dir()
        sage: fullpath = os.path.join(t_dir, 'test.py')
        sage: open(fullpath, 'w').write("print 37 * 3")
        sage: load_attach_path(t_dir)
        sage: attach('test.py')
        111
        sage: sage.repl.attach.reset(); reset_load_attach_path() # clean up

    or by setting the environment variable ``SAGE_LOAD_ATTACH_PATH``
    to a colon-separated list before starting Sage::

        $ export SAGE_LOAD_ATTACH_PATH="/path/to/my/library:/path/to/utils"
        $ sage
        sage: load_attach_path()          # not tested
        ['.', '/path/to/my/library', '/path/to/utils']

    Make sure that load handles filenames with spaces in the name or path::

        sage: t = tmp_filename(ext=' b.sage'); open(t,'w').write("print 2")
        sage: sage.repl.load.load(t, globals())
        2
    """
    if attach:
        from sage.repl.attach import add_attached_file

    try:
        filename = eval(filename, globals)
    except Exception:
        # First check if the file exists. The filename may have spaces in
        # its name, but more importantly modified_attached_files calls load
        # with the absolute file path and that may contain spaces in the path
        # As a side effect, this also allows file names with spaces in
        # them, but currently I don't see a way to disallow this case.
        if not os.path.exists(filename) and not os.path.isabs(filename):
            # handle multiple input files separated by spaces, which was
            # maybe a bad idea, but which we have to handle for backwards
            # compatibility.
            v = filename.split()
            if len(v) > 1:
                for file in v:
                    load(file, globals, attach=attach)
                return

    filename = filename.strip()

    if filename.lower().startswith(('http://', 'https://')):
        if attach:
            # But see http://en.wikipedia.org/wiki/HTTP_ETag for how
            # we will do this.
            # http://www.diveintopython.net/http_web_services/etags.html
            raise NotImplementedError("you can't attach a URL")
        from remote_file import get_remote_file
        filename = get_remote_file(filename, verbose=False)

    if not is_loadable_filename(filename):
        raise ValueError('argument (=%r) to load or attach must have extension py, pyx, sage, spyx, or m' % filename)

    fpath = os.path.expanduser(filename)
    if os.path.isabs(fpath):
        if not os.path.exists(fpath):
            raise IOError('did not find file %r to load or attach' % filename)
    else:
        from sage.repl.attach import load_attach_path
        for path in load_attach_path():
            fpath = os.path.join(path, filename)
            fpath = os.path.expanduser(fpath)
            if os.path.exists(fpath):
                break
        else:
            raise IOError('did not find file %r in load / attach search path' \
                % filename)

    if fpath.endswith('.py'):
        if attach:
            add_attached_file(fpath)
        with open(fpath) as f:
            code = compile(f.read(), fpath, 'exec')
            exec(code, globals)
    elif fpath.endswith('.sage'):
        from sage.repl.attach import load_attach_mode
        from sage.repl.preparse import preparse_file_named, preparse_file
        load_debug_mode, attach_debug_mode = load_attach_mode()
        if (attach and attach_debug_mode) or ((not attach) and load_debug_mode):
            # Preparse to a file to enable tracebacks with
            # code snippets. Use preparse_file_named to make
            # the file name appear in the traceback as well.
            # See Trac 11812.
            if attach:
                add_attached_file(fpath)
            with open(preparse_file_named(fpath)) as f:
                code = compile(f.read(), preparse_file_named(fpath), 'exec')
                exec(code, globals)
        else:
            # Preparse in memory only for speed.
            if attach:
                add_attached_file(fpath)
            exec(preparse_file(open(fpath).read()) + "\n", globals)
    elif fpath.endswith('.spyx') or fpath.endswith('.pyx'):
        if attach:
            add_attached_file(fpath)
        exec(load_cython(fpath), globals)
    elif fpath.endswith('.m'):
        # Assume magma for now, though maybe .m is used by maple and
        # mathematica too, and we should really analyze the file
        # further.
        s = globals['magma'].load(fpath)
        i = s.find('\n'); s = s[i+1:]
        print(s)
Пример #8
0
    def execute(self):
        if self.calculation_time is not None:
            if self.is_uptodate():
                return

        from tempfile import mkdtemp
        from shutil import rmtree
        oldwkdir = os.getcwd()
        old_stdout = sys.stdout

        if (test_ipython()):
            out = dualStdout(old_stdout=old_stdout)
        else:
            out = StringIO()

        wkdir = mkdtemp(suffix='pe')
        os.chdir(wkdir)
        codedir = os.path.join(wkdir, '.code')
        os.mkdir(codedir)
        code_filename = os.path.join(codedir, '_code.py')
        with open(code_filename, 'w') as f:
            f.write(
                '# -*- coding: utf-8 -*-\nfrom sage.all import *\nfrom pemongo import *\n'
                + preparse_file(self.code))
        self.file_set = {}
        sys.stdout = out

        # import the code and collect results, finally cleanup
        try:
            mod = None
            # import the code module into mod and maybe collect exception
            try:
                mod = import_(code_filename)
            except Exception as e:
                from traceback import format_exc
                print('Exception:{}\r\n'.format(e))
                print(format_exc() + '\r\n')

            # collect result, if applicable
            try:
                self.result = dict(mod.result)
            except AttributeError:
                self.result = {}

            # collect files
            onlyfiles = [
                f for f in os.listdir(wkdir)
                if os.path.isfile(os.path.join(wkdir, f))
            ]
            for i, filename in enumerate(onlyfiles):
                if os.path.getsize(os.path.join(
                        wkdir, filename)) > self.MAX_FILESIZE_BYTES:
                    raise RuntimeException('Too big file ' + filename)
                else:
                    # the following is bad for large files. We however set a limit.
                    with open(os.path.join(wkdir, filename), 'rb') as f:
                        self.file_set[filename] = f.read()
        # cleanup
        finally:
            os.chdir(oldwkdir)
            sys.stdout = old_stdout
            rmtree(wkdir)
        # collect stdout
        self.output = out.getvalue()  #.decode('utf-8')
        self.calculation_time = time.time()
Пример #9
0
def load(filename, globals, attach=False):
    r"""
    Executes a file in the scope given by ``globals``.  If the name
    starts with ``http://``, it is treated as a URL and downloaded.

    .. NOTE::

        For Cython files, the situation is more complicated --
        the module is first compiled to a temporary module ``t`` and
        executed via::

            from t import *

    INPUT:

    - ``filename`` -- a string denoting a filename or URL.

    - ``globals`` -- a string:object dictionary; the context in which
      to execute the file contents.

    - ``attach`` -- a boolean (default: False); whether to add the
      file to the list of attached files.

    EXAMPLES:

    Note that ``.py`` files are *not* preparsed::

        sage: t = tmp_filename(ext='.py')
        sage: open(t,'w').write("print 'hi', 2/3; z = -2/7")
        sage: z = 1
        sage: sage.repl.load.load(t, globals())
        hi 0
        sage: z
        -1

    A ``.sage`` file *is* preparsed::

        sage: t = tmp_filename(ext='.sage')
        sage: open(t,'w').write("print 'hi', 2/3; z = -2/7")
        sage: z = 1
        sage: sage.repl.load.load(t, globals())
        hi 2/3
        sage: z
        -2/7

    Cython files are *not* preparsed::

        sage: t = tmp_filename(ext='.pyx')
        sage: open(t,'w').write("print 'hi', 2/3; z = -2/7")
        sage: z = 1
        sage: sage.repl.load.load(t, globals())
        Compiling ...
        hi 0
        sage: z
        -1

    If the file isn't a Cython, Python, or a Sage file, a ValueError
    is raised::

        sage: sage.repl.load.load(tmp_filename(ext=".foo"), globals())
        Traceback (most recent call last):
        ...
        ValueError: unknown file extension '.foo' for load or attach (supported extensions: .py, .pyx, .sage, .spyx, .f, .f90, .m)

    We load a file given at a remote URL::

        sage: sage.repl.load.load('http://wstein.org/loadtest.py', globals())  # optional - internet
        hi from the net
        5

    We can load files using secure http (https)::

        sage: sage.repl.load.load('https://github.com/jasongrout/minimum_rank/raw/minimum_rank_1_0_0/minrank.py', globals())  # optional - internet

    We attach a file::

        sage: t = tmp_filename(ext='.py')
        sage: open(t,'w').write("print 'hello world'")
        sage: sage.repl.load.load(t, globals(), attach=True)
        hello world
        sage: t in attached_files()
        True

    You can't attach remote URLs (yet)::

        sage: sage.repl.load.load('http://wstein.org/loadtest.py', globals(), attach=True)  # optional - internet
        Traceback (most recent call last):
        ...
        NotImplementedError: you can't attach a URL

    The default search path for loading and attaching files is the
    current working directory, i.e., ``'.'``.  But you can modify the
    path with :func:`load_attach_path`::

        sage: sage.repl.attach.reset(); reset_load_attach_path()
        sage: load_attach_path()
        ['.']
        sage: t_dir = tmp_dir()
        sage: fullpath = os.path.join(t_dir, 'test.py')
        sage: open(fullpath, 'w').write("print 37 * 3")
        sage: load_attach_path(t_dir)
        sage: attach('test.py')
        111
        sage: sage.repl.attach.reset(); reset_load_attach_path() # clean up

    or by setting the environment variable ``SAGE_LOAD_ATTACH_PATH``
    to a colon-separated list before starting Sage::

        $ export SAGE_LOAD_ATTACH_PATH="/path/to/my/library:/path/to/utils"
        $ sage
        sage: load_attach_path()          # not tested
        ['.', '/path/to/my/library', '/path/to/utils']

    TESTS:

    Make sure that load handles filenames with spaces in the name or path::

        sage: t = tmp_filename(ext=' b.sage'); open(t,'w').write("print 2")
        sage: sage.repl.load.load(t, globals())
        2

    Non-existing files with spaces give correct messages::

        sage: sage.repl.load.load("this file should not exist", globals())
        Traceback (most recent call last):
        ...
        IOError: did not find file 'this file should not exist' to load or attach

    Evaluating a filename is deprecated::

        sage: sage.repl.load.load("tmp_filename(ext='.py')", globals())
        doctest:...: DeprecationWarning: using unevaluated expressions as argument to load() is dangerous and deprecated
        See http://trac.sagemath.org/17654 for details.

    Test filenames separated by spaces (deprecated)::

        sage: t = tmp_filename(ext='.py')
        sage: with open(t, 'w') as f:
        ....:     f.write("print 'hello'\n")
        sage: sage.repl.load.load(t + " " + t, globals())
        hello
        hello
        doctest:...: DeprecationWarning: using multiple filenames separated by spaces as load() argument is dangerous and deprecated
        See http://trac.sagemath.org/17654 for details.
    """
    if attach:
        from sage.repl.attach import add_attached_file

    filename = os.path.expanduser(filename)
    if not os.path.exists(filename):
        try:
            # Try *evaluating* the filename
            filename = eval(filename, globals).strip()
        except Exception:
            # Handle multiple input files separated by spaces, which was
            # maybe a bad idea, but which we have to handle for backwards
            # compatibility.
            v = filename.split()
            if len(v) > 1:
                try:
                    for f in v:
                        load(f, globals, attach=attach)
                except IOError:
                    # Splitting the filename didn't work, pretend it
                    # didn't happen :-)
                    pass
                else:
                    # Only show deprecation message if the filename
                    # splitting worked.
                    from sage.misc.superseded import deprecation
                    deprecation(17654, 'using multiple filenames separated by spaces as load() argument is dangerous and deprecated')
                    return
        else:
            from sage.misc.superseded import deprecation
            deprecation(17654, 'using unevaluated expressions as argument to load() is dangerous and deprecated')

    if filename.lower().startswith(('http://', 'https://')):
        if attach:
            # But see http://en.wikipedia.org/wiki/HTTP_ETag for how
            # we will do this.
            # http://www.diveintopython.net/http_web_services/etags.html
            raise NotImplementedError("you can't attach a URL")
        from sage.misc.remote_file import get_remote_file
        filename = get_remote_file(filename, verbose=False)

    from sage.repl.attach import load_attach_path
    for path in load_attach_path():
        fpath = os.path.join(path, filename)
        fpath = os.path.expanduser(fpath)
        if os.path.isfile(fpath):
            break
    else:
        raise IOError('did not find file %r to load or attach' % filename)

    ext = os.path.splitext(fpath)[1].lower()
    if ext == '.py':
        if attach:
            add_attached_file(fpath)
        with open(fpath) as f:
            code = compile(f.read(), fpath, 'exec')
            exec(code, globals)
    elif ext == '.sage':
        from sage.repl.attach import load_attach_mode
        from sage.repl.preparse import preparse_file_named, preparse_file
        load_debug_mode, attach_debug_mode = load_attach_mode()
        if (attach and attach_debug_mode) or ((not attach) and load_debug_mode):
            # Preparse to a file to enable tracebacks with
            # code snippets. Use preparse_file_named to make
            # the file name appear in the traceback as well.
            # See Trac 11812.
            if attach:
                add_attached_file(fpath)
            with open(preparse_file_named(fpath)) as f:
                code = compile(f.read(), preparse_file_named(fpath), 'exec')
                exec(code, globals)
        else:
            # Preparse in memory only for speed.
            if attach:
                add_attached_file(fpath)
            exec(preparse_file(open(fpath).read()) + "\n", globals)
    elif ext == '.spyx' or ext == '.pyx':
        if attach:
            add_attached_file(fpath)
        exec(load_cython(fpath), globals)
    elif ext == '.f' or ext == '.f90':
        from sage.misc.inline_fortran import fortran
        with open(fpath) as f:
            fortran(f.read(), globals)
    elif ext == '.m':
        # Assume magma for now, though maybe .m is used by maple and
        # mathematica too, and we should really analyze the file
        # further.
        s = globals['magma'].load(fpath)
        i = s.find('\n'); s = s[i+1:]
        print(s)
    else:
        raise ValueError('unknown file extension %r for load or attach (supported extensions: .py, .pyx, .sage, .spyx, .f, .f90, .m)' % ext)