more putter
This commit is contained in:
parent
3e6c24cc0c
commit
d2f87363ef
|
@ -0,0 +1,222 @@
|
|||
|
||||
|
||||
#include "py4yap.h"
|
||||
#include <VFS.h>
|
||||
|
||||
atom_t ATOM_true, ATOM_false, ATOM_colon, ATOM_dot, ATOM_none, ATOM_t,
|
||||
ATOM_comma, ATOM_builtin, ATOM_A, ATOM_V, ATOM_self, ATOM_nil, ATOM_brackets, ATOM_curly_brackets;
|
||||
|
||||
functor_t FUNCTOR_dollar1, FUNCTOR_abs1, FUNCTOR_all1, FUNCTOR_any1,
|
||||
FUNCTOR_bin1, FUNCTOR_brackets1, FUNCTOR_comma2, FUNCTOR_dir1,
|
||||
FUNCTOR_float1, FUNCTOR_int1, FUNCTOR_iter1, FUNCTOR_iter2, FUNCTOR_long1,
|
||||
FUNCTOR_len1, FUNCTOR_curly1, FUNCTOR_ord1, FUNCTOR_range1, FUNCTOR_range2,
|
||||
FUNCTOR_range3, FUNCTOR_sum1, FUNCTOR_pointer1, FUNCTOR_complex2,
|
||||
FUNCTOR_plus2, FUNCTOR_sub2, FUNCTOR_mul2, FUNCTOR_div2, FUNCTOR_hat2,
|
||||
FUNCTOR_colon2, FUNCTOR_comma2, FUNCTOR_equal2, FUNCTOR_sqbrackets2,
|
||||
FUNCTOR_dot2, FUNCTOR_brackets1;
|
||||
|
||||
X_API PyObject *py_Builtin;
|
||||
X_API PyObject *py_Yapex;
|
||||
X_API PyObject *py_Sys;
|
||||
PyObject *py_Context;
|
||||
PyObject *py_ModDict;
|
||||
|
||||
VFS_t pystream;
|
||||
|
||||
static void *
|
||||
py_open( const char *name, const char *io_mode) {
|
||||
#if HAVE_STRCASESTR
|
||||
if (strcasestr(name,"//python/")== name)
|
||||
name += strlen("//python/");
|
||||
#else
|
||||
if (strstr(name,"//python/")== name)
|
||||
name += strlen("//python/");
|
||||
#endif
|
||||
// we assume object is already open, so there is no need to open it.
|
||||
PyObject *stream = string_to_python( name, true, NULL);
|
||||
if (stream == Py_None)
|
||||
return NULL;
|
||||
return stream;
|
||||
}
|
||||
|
||||
static bool
|
||||
py_close(int sno) {
|
||||
PyObject *s = YAP_foreign_stream(sno);
|
||||
PyObject* fclose = PyObject_GetAttrString(s, "close");
|
||||
PyObject* rc= PyObject_CallObject(fclose, NULL);
|
||||
bool v = (rc == Py_True);
|
||||
return v;
|
||||
}
|
||||
|
||||
static PyObject * pyw; // buffer
|
||||
static int pyw_kind;
|
||||
PyObject * pyw_data;
|
||||
|
||||
static int
|
||||
py_put(int sno, int ch) {
|
||||
PyObject *s = YAP_foreign_stream(sno);
|
||||
PyUnicode_WRITE( pyw_kind, pyw_data, 0, ch );
|
||||
PyObject* fput = PyObject_GetAttrString(s, "write");
|
||||
PyObject_CallFunctionObjArgs(fput, pyw, NULL);
|
||||
return ch;
|
||||
}
|
||||
|
||||
static int
|
||||
py_get(int sno) {
|
||||
PyObject *s = YAP_foreign_stream(sno);
|
||||
PyObject* fget = PyObject_GetAttrString(s, "read");
|
||||
PyObject *pyr = PyObject_CallFunctionObjArgs(fget, PyLong_FromLong(1), NULL);
|
||||
return PyUnicode_READ_CHAR( pyr, 0) ;
|
||||
}
|
||||
|
||||
static int64_t py_seek(int sno, int64_t where, int how) {
|
||||
PyObject *s = YAP_foreign_stream(sno);
|
||||
PyObject* fseek = PyObject_GetAttrString(s, "seek");
|
||||
PyObject *pyr = PyObject_CallFunctionObjArgs(fseek, PyLong_FromLong(where), PyLong_FromLong(how), NULL);
|
||||
return PyLong_AsLong(pyr);
|
||||
}
|
||||
|
||||
static void
|
||||
py_flush(int sno) {
|
||||
PyObject *s = YAP_foreign_stream(sno);
|
||||
PyObject* flush = PyObject_GetAttrString(s, "flush");
|
||||
PyObject_CallFunction( flush, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool
|
||||
init_python_stream(void)
|
||||
{
|
||||
pyw = PyUnicode_FromString("x");
|
||||
pyw_kind = PyUnicode_KIND(pyw);
|
||||
pyw_data = PyUnicode_DATA(pyw);
|
||||
|
||||
pystream.name = "python stream";
|
||||
pystream.vflags = VFS_CAN_WRITE|VFS_CAN_EXEC| VFS_CAN_SEEK|VFS_HAS_PREFIX;
|
||||
pystream.prefix = "//python/";
|
||||
pystream.suffix = NULL;
|
||||
pystream.open = py_open;
|
||||
pystream.close = py_close;
|
||||
pystream.get_char = py_get;
|
||||
pystream.put_char = py_put;
|
||||
pystream.flush = py_flush;
|
||||
pystream.seek = py_seek;
|
||||
pystream.next = GLOBAL_VFS;
|
||||
GLOBAL_VFS = &pystream;
|
||||
// NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
X_API PyObject *py_F2P;
|
||||
|
||||
extern X_API bool python_in_python;
|
||||
|
||||
static void add_modules(void) {
|
||||
py_Main = PyImport_AddModule("__main__");
|
||||
Py_INCREF(py_Main);
|
||||
py_Sys = PyImport_AddModule("sys");
|
||||
Py_INCREF(py_Sys);
|
||||
py_Builtin = PyImport_AddModule("__builtin__");
|
||||
Py_INCREF(py_Builtin);
|
||||
py_ModDict = PyObject_GetAttrString(py_Sys, "modules");
|
||||
// py_Yapex = PyImport_ImportModule("yap4py.yapi");
|
||||
// PyObject *py_Yap =
|
||||
py_Yapex = PyImport_AddModule("yap4py.yapi");
|
||||
if (py_Yapex)
|
||||
Py_INCREF(py_Yapex);
|
||||
//py_F2P = PyObject_GetAttrString(py_Yap, "globals");
|
||||
py_F2P = NULL;
|
||||
init_python_stream();
|
||||
}
|
||||
|
||||
|
||||
static void install_py_constants(void) {
|
||||
FUNCTOR_dot2 = PL_new_functor(PL_new_atom("."), 2);
|
||||
// FUNCTOR_equal2 = PL_new_functor(PL_new_atom("="), 2);
|
||||
// FUNCTOR_boolop1 = PL_new_functor(PL_new_atom("@"), 1);
|
||||
ATOM_A = PL_new_atom("A");
|
||||
ATOM_V = PL_new_atom("V");
|
||||
ATOM_builtin = PL_new_atom("__builtin__");
|
||||
ATOM_comma = PL_new_atom(",");
|
||||
ATOM_colon = PL_new_atom(":");
|
||||
ATOM_true = PL_new_atom("true");
|
||||
ATOM_false = PL_new_atom("false");
|
||||
ATOM_dot = PL_new_atom(".");
|
||||
ATOM_self = PL_new_atom("self");
|
||||
ATOM_nil = PL_new_atom("[]");
|
||||
ATOM_brackets = PL_new_atom("()");
|
||||
ATOM_curly_brackets = PL_new_atom("{}");
|
||||
FUNCTOR_abs1 = PL_new_functor(PL_new_atom("abs"), 1);
|
||||
FUNCTOR_all1 = PL_new_functor(PL_new_atom("all"), 1);
|
||||
FUNCTOR_any1 = PL_new_functor(PL_new_atom("any"), 1);
|
||||
FUNCTOR_bin1 = PL_new_functor(PL_new_atom("bin"), 1);
|
||||
FUNCTOR_ord1 = PL_new_functor(PL_new_atom("ord"), 1);
|
||||
FUNCTOR_int1 = PL_new_functor(PL_new_atom("int"), 1);
|
||||
FUNCTOR_long1 = PL_new_functor(PL_new_atom("long"), 1);
|
||||
FUNCTOR_float1 = PL_new_functor(PL_new_atom("float"), 1);
|
||||
FUNCTOR_curly1 = PL_new_functor(PL_new_atom("{}"), 1);
|
||||
FUNCTOR_brackets1 = PL_new_functor(PL_new_atom("()"), 1);
|
||||
FUNCTOR_dollar1 = PL_new_functor(PL_new_atom("$"), 1);
|
||||
FUNCTOR_pointer1 = PL_new_functor(PL_new_atom("__obj__"), 1);
|
||||
FUNCTOR_dir1 = PL_new_functor(PL_new_atom("dir"), 1);
|
||||
FUNCTOR_iter1 = PL_new_functor(PL_new_atom("iter"), 1);
|
||||
FUNCTOR_iter2 = PL_new_functor(PL_new_atom("iter"), 2);
|
||||
FUNCTOR_len1 = PL_new_functor(PL_new_atom("len"), 1);
|
||||
FUNCTOR_range1 = PL_new_functor(PL_new_atom("range"), 1);
|
||||
FUNCTOR_range2 = PL_new_functor(PL_new_atom("range"), 2);
|
||||
FUNCTOR_range3 = PL_new_functor(PL_new_atom("range"), 3);
|
||||
FUNCTOR_sum1 = PL_new_functor(PL_new_atom("sum"), 1);
|
||||
FUNCTOR_complex2 = PL_new_functor(PL_new_atom("i"), 2);
|
||||
FUNCTOR_plus2 = PL_new_functor(PL_new_atom("+"), 2);
|
||||
FUNCTOR_sub2 = PL_new_functor(PL_new_atom("-"), 2);
|
||||
FUNCTOR_mul2 = PL_new_functor(PL_new_atom("*"), 2);
|
||||
FUNCTOR_div2 = PL_new_functor(PL_new_atom("/"), 2);
|
||||
FUNCTOR_hat2 = PL_new_functor(PL_new_atom("^"), 2);
|
||||
FUNCTOR_colon2 = PL_new_functor(PL_new_atom(":"), 2);
|
||||
FUNCTOR_comma2 = PL_new_functor(PL_new_atom(","), 2);
|
||||
FUNCTOR_equal2 = PL_new_functor(PL_new_atom("="), 2);
|
||||
FUNCTOR_sqbrackets2 = PL_new_functor(PL_new_atom("[]"), 2);
|
||||
}
|
||||
|
||||
foreign_t end_python(void) {
|
||||
if (!python_in_python)
|
||||
Py_Finalize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool libpython_initialized = 0;
|
||||
|
||||
X_API bool do_init_python(void) {
|
||||
// char **argv;
|
||||
if (libpython_initialized)
|
||||
return true;
|
||||
libpython_initialized = true;
|
||||
|
||||
// PyGILState_STATE gstate = PyGILState_Ensure();
|
||||
term_t t = PL_new_term_ref();
|
||||
if (!python_in_python)
|
||||
Py_Initialize();
|
||||
install_py_constants();
|
||||
PL_reset_term_refs(t);
|
||||
install_pl2pl();
|
||||
// PyGILState_Release(gstate);
|
||||
add_modules();
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
|
||||
O_API bool init_python_dll(void);
|
||||
|
||||
|
||||
O_API bool init_python_dll(void) {
|
||||
do_init_python();
|
||||
install_pypreds();
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
include(FindPythonModule)
|
||||
|
||||
set (PROLOG_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/yapi.yap ${CMAKE_CURRENT_SOURCE_DIR}/jupyter.yap)
|
||||
set (PROLOG_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/yapi.yap)
|
||||
set (PYTHON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/yapi.py ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py ${CMAKE_CURRENT_SOURCE_DIR}/__main__.py)
|
||||
|
||||
file(RELATIVE_PATH RELATIVE_SOURCE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR})
|
||||
|
@ -76,17 +76,15 @@ add_custom_target( YAP4PY_SETUP_DIRS
|
|||
)
|
||||
|
||||
add_custom_target( YAP4PY ALL
|
||||
COMMAND ${PYTHON_EXECUTABLE} -m pip uninstall -y YAP4PY
|
||||
COMMAND ${SWIG_EXECUTABLE} -python -modern -c++ -py3 -DX_API -I${CMAKE_SOURCE_DIR}/CXX -I${CMAKE_SOURCE_DIR}/include -I${CMAKE_SOURCE_DIR}/H -I${CMAKE_SOURCE_DIR}/H/generated -I${CMAKE_SOURCE_DIR}/OPTYap -I../../.. -o yap_wrap.cpp yap.i
|
||||
COMMAND ${PYTHON_EXECUTABLE} setup.py sdist bdist_wheel
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS YAP4PY_SETUP)
|
||||
|
||||
|
||||
|
||||
install(CODE "execute_process(
|
||||
COMMAND ${PYTHON_EXECUTABLE} -m pip install --force --no-index -f packages/python/swig/dist YAP4PY
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})"
|
||||
COMMAND ${PYTHON_EXECUTABLE} -m pip install --ignore-installed ${CMAKE_CURRENT_BINARY_DIR}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})"
|
||||
DEPENDS Py4YAP ${CMAKE_BINARY_DIR}/${YAP_STARTUP} ${dlls} )
|
||||
|
||||
install(FILES ${PROLOG_SOURCES} DESTINATION ${libpl})
|
||||
|
|
|
@ -4,11 +4,7 @@ import sys
|
|||
import yapi
|
||||
|
||||
|
||||
def main(args=None):
|
||||
"""The main routine."""
|
||||
if args is None:
|
||||
"""The main routine."""
|
||||
if args is None:
|
||||
args = sys.argv[1:]
|
||||
yap.yapi.live(args)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
yap4pi.yapi.live(args)
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
from IPython.core.oinspect import *
|
||||
|
||||
|
||||
from pygments import highlight
|
||||
from pygments.lexers import PrologLexer
|
||||
from pygments.formatters import HtmlFormatter
|
||||
|
||||
|
||||
def yaplight(code):
|
||||
return highlight(code, PythonLexer(), HtmlFormatter(noclasses=True))
|
||||
|
||||
def _get_info(self, obj, oname='', formatter=None, info=None, detail_level=0):
|
||||
"""Retrieve an info dict and format it.
|
||||
|
||||
Parameters
|
||||
==========
|
||||
|
||||
obj: any
|
||||
Object to inspect and return info from
|
||||
oname: str (default: ''):
|
||||
Name of the variable pointing to `obj`.
|
||||
formatter: callable
|
||||
info:
|
||||
already computed informations
|
||||
detail_level: integer
|
||||
Granularity of detail level, if set to 1, give more informations.
|
||||
"""
|
||||
|
||||
info = self._info(obj, oname=oname, info=info, detail_level=detail_level)
|
||||
|
||||
_mime = {
|
||||
'text/plain': [],
|
||||
'text/html': '',
|
||||
}
|
||||
|
||||
def append_field(bundle, title, key, formatter=None):
|
||||
field = info[key]
|
||||
if field is not None:
|
||||
formatted_field = self._mime_format(field, formatter)
|
||||
bundle['text/plain'].append((title, formatted_field['text/plain']))
|
||||
bundle['text/html'] += '<h1>' + title + '</h1>\n' + formatted_field['text/html'] + '\n'
|
||||
|
||||
def code_formatter(text):
|
||||
return {
|
||||
'text/plain': self.format(text),
|
||||
'text/html': yaplight(text)
|
||||
}
|
||||
|
||||
if info['isalias']:
|
||||
append_field(_mime, 'Repr', 'string_form')
|
||||
|
||||
elif info['ismagic']:
|
||||
if detail_level > 0:
|
||||
append_field(_mime, 'Source', 'source', code_formatter)
|
||||
else:
|
||||
append_field(_mime, 'Docstring', 'docstring', formatter)
|
||||
append_field(_mime, 'File', 'file')
|
||||
|
||||
# elif info['isclass'] or is_simple_callable(obj):
|
||||
# # Functions, methods, classes
|
||||
# append_field(_mime, 'Signature', 'definition', code_formatter)
|
||||
# append_field(_mime, 'Init signature', 'init_definition', code_formatter)
|
||||
# if detail_level > 0 and info['source']:
|
||||
# append_field(_mime, 'Source', 'source', code_formatter)
|
||||
# else:
|
||||
# append_field(_mime, 'Docstring', 'docstring', formatter)
|
||||
# append_field(_mime, 'Init docstring', 'init_docstring', formatter)
|
||||
#
|
||||
# append_field(_mime, 'File', 'file')
|
||||
# append_field(_mime, 'Type', 'type_name')
|
||||
|
||||
else:
|
||||
# General Python objects
|
||||
append_field(_mime, 'Signature', 'definition', code_formatter)
|
||||
append_field(_mime, 'Call signature', 'call_def', code_formatter)
|
||||
append_field(_mime, 'Type', 'type_name')
|
||||
append_field(_mime, 'String form', 'string_form')
|
||||
|
||||
# Namespace
|
||||
if info['namespace'] != 'Interactive':
|
||||
append_field(_mime, 'Namespace', 'namespace')
|
||||
|
||||
append_field(_mime, 'Length', 'length')
|
||||
append_field(_mime, 'File', 'file')
|
||||
|
||||
# Source or docstring, depending on detail level and whether
|
||||
# source found.
|
||||
# if detail_level > 0 and info['source']:
|
||||
append_field(_mime, 'Source', 'source', code_formatter)
|
||||
# else:
|
||||
# append_field(_mime, 'Docstring', 'docstring', formatter)
|
||||
|
||||
append_field(_mime, 'Class docstring', 'class_docstring', formatter)
|
||||
append_field(_mime, 'Init docstring', 'init_docstring', formatter)
|
||||
append_field(_mime, 'Call docstring', 'call_docstring', formatter)
|
||||
|
||||
|
||||
return self.format_mime(_mime)
|
||||
|
||||
Inspector._get_info = _get_info
|
|
@ -0,0 +1,16 @@
|
|||
"""Public API for display tools in IPython.
|
||||
"""
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (C) 2012 The IPython Development Team
|
||||
#
|
||||
# Distributed under the terms of the BSD License. The full license is in
|
||||
# the file COPYING, distributed as part of this software.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
from IPython.core.display import *
|
||||
from IPython.lib.display import *
|
|
@ -0,0 +1,408 @@
|
|||
# encoding: utf-8
|
||||
"""
|
||||
A mixin for :class:`~IPython.core.application.Application` classes that
|
||||
launch InteractiveShell instances, load extensions, etc.
|
||||
"""
|
||||
|
||||
# Copyright (c) IPython Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
|
||||
import glob
|
||||
from itertools import chain
|
||||
import os
|
||||
import sys
|
||||
|
||||
from traitlets.config.application import boolean_flag
|
||||
from traitlets.config.configurable import Configurable
|
||||
from traitlets.config.loader import Config
|
||||
from IPython.core.application import SYSTEM_CONFIG_DIRS, ENV_CONFIG_DIRS
|
||||
from IPython.core import pylabtools
|
||||
from IPython.utils.contexts import preserve_keys
|
||||
from IPython.utils.path import filefind
|
||||
from traitlets import (
|
||||
Unicode, Instance, List, Bool, CaselessStrEnum, observe,
|
||||
)
|
||||
from IPython.terminal import pt_inputhooks
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Aliases and Flags
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
gui_keys = tuple(sorted(pt_inputhooks.backends) + sorted(pt_inputhooks.aliases))
|
||||
|
||||
backend_keys = sorted(pylabtools.backends.keys())
|
||||
backend_keys.insert(0, 'auto')
|
||||
|
||||
shell_flags = {}
|
||||
|
||||
addflag = lambda *args: shell_flags.update(boolean_flag(*args))
|
||||
addflag('autoindent', 'YAPInteractive.autoindent',
|
||||
'Turn on autoindenting.', 'Turn off autoindenting.'
|
||||
)
|
||||
addflag('automagic', 'YAPInteractive.automagic',
|
||||
"""Turn on the auto calling of magic commands. Type %%magic at the
|
||||
IPython prompt for more information.""",
|
||||
'Turn off the auto calling of magic commands.'
|
||||
)
|
||||
addflag('pdb', 'YAPInteractive.pdb',
|
||||
"Enable auto calling the pdb debugger after every exception.",
|
||||
"Disable auto calling the pdb debugger after every exception."
|
||||
)
|
||||
addflag('pprint', 'PlainTextFormatter.pprint',
|
||||
"Enable auto pretty printing of results.",
|
||||
"Disable auto pretty printing of results."
|
||||
)
|
||||
addflag('color-info', 'YAPInteractive.color_info',
|
||||
"""IPython can display information about objects via a set of functions,
|
||||
and optionally can use colors for this, syntax highlighting
|
||||
source code and various other elements. This is on by default, but can cause
|
||||
problems with some pagers. If you see such problems, you can disable the
|
||||
colours.""",
|
||||
"Disable using colors for info related things."
|
||||
)
|
||||
nosep_config = Config()
|
||||
nosep_config.YAPInteractive.separate_in = ''
|
||||
nosep_config.YAPInteractive.separate_out = ''
|
||||
nosep_config.YAPInteractive.separate_out2 = ''
|
||||
|
||||
shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
|
||||
shell_flags['pylab'] = (
|
||||
{'YAPInteractiveApp' : {'pylab' : 'auto'}},
|
||||
"""Pre-load matplotlib and numpy for interactive use with
|
||||
the default matplotlib backend."""
|
||||
)
|
||||
shell_flags['matplotlib'] = (
|
||||
{'YAPInteractiveApp' : {'matplotlib' : 'auto'}},
|
||||
"""Configure matplotlib for interactive use with
|
||||
the default matplotlib backend."""
|
||||
)
|
||||
|
||||
# it's possible we don't want short aliases for *all* of these:
|
||||
shell_aliases = dict(
|
||||
autocall='YAPInteractive.autocall',
|
||||
colors='YAPInteractive.colors',
|
||||
logfile='YAPInteractive.logfile',
|
||||
logappend='YAPInteractive.logappend',
|
||||
c='YAPInteractiveApp.code_to_run',
|
||||
m='YAPInteractiveApp.module_to_run',
|
||||
ext='YAPInteractiveApp.extra_extension',
|
||||
gui='YAPInteractiveApp.gui',
|
||||
pylab='YAPInteractiveApp.pylab',
|
||||
matplotlib='YAPInteractiveApp.matplotlib',
|
||||
)
|
||||
shell_aliases['cache-size'] = 'YAPInteractive.cache_size'
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Main classes and functions
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
class YAPInteractiveApp(Configurable):
|
||||
"""A Mixin for applications that start YAPInteractive instances.
|
||||
|
||||
Provides configurables for loading extensions and executing files
|
||||
as part of configuring a Shell environment.
|
||||
|
||||
The following methods should be called by the :meth:`initialize` method
|
||||
of the subclass:
|
||||
|
||||
- :meth:`init_path`
|
||||
- :meth:`init_shell` (to be implemented by the subclass)
|
||||
- :meth:`init_gui_pylab`
|
||||
- :meth:`init_extensions`
|
||||
- :meth:`init_code`
|
||||
"""
|
||||
extensions = List(Unicode(),
|
||||
help="A list of dotted module names of IPython extensions to load."
|
||||
).tag(config=True)
|
||||
extra_extension = Unicode('',
|
||||
help="dotted module name of an IPython extension to load."
|
||||
).tag(config=True)
|
||||
|
||||
reraise_ipython_extension_failures = Bool(False,
|
||||
help="Reraise exceptions encountered loading IPython extensions?",
|
||||
).tag(config=True)
|
||||
|
||||
# Extensions that are always loaded (not configurable)
|
||||
default_extensions = List(Unicode(), [u'storemagic']).tag(config=False)
|
||||
|
||||
hide_initial_ns = Bool(True,
|
||||
help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
|
||||
be hidden from tools like %who?"""
|
||||
).tag(config=True)
|
||||
|
||||
exec_files = List(Unicode(),
|
||||
help="""List of files to run at IPython startup."""
|
||||
).tag(config=True)
|
||||
exec_PYTHONSTARTUP = Bool(True,
|
||||
help="""Run the file referenced by the PYTHONSTARTUP environment
|
||||
variable at IPython startup."""
|
||||
).tag(config=True)
|
||||
file_to_run = Unicode('',
|
||||
help="""A file to be run""").tag(config=True)
|
||||
|
||||
exec_lines = List(Unicode(),
|
||||
help="""lines of code to run at IPython startup."""
|
||||
).tag(config=True)
|
||||
code_to_run = Unicode('',
|
||||
help="Execute the given command string."
|
||||
).tag(config=True)
|
||||
module_to_run = Unicode('',
|
||||
help="Run the module as a script."
|
||||
).tag(config=True)
|
||||
gui = CaselessStrEnum(gui_keys, allow_none=True,
|
||||
help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
|
||||
).tag(config=True)
|
||||
matplotlib = CaselessStrEnum(backend_keys, allow_none=True,
|
||||
help="""Configure matplotlib for interactive use with
|
||||
the default matplotlib backend."""
|
||||
).tag(config=True)
|
||||
pylab = CaselessStrEnum(backend_keys, allow_none=True,
|
||||
help="""Pre-load matplotlib and numpy for interactive use,
|
||||
selecting a particular matplotlib backend and loop integration.
|
||||
"""
|
||||
).tag(config=True)
|
||||
pylab_import_all = Bool(True,
|
||||
help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
|
||||
and an ``import *`` is done from numpy and pylab, when using pylab mode.
|
||||
|
||||
When False, pylab mode should not import any names into the user namespace.
|
||||
"""
|
||||
).tag(config=True)
|
||||
shell = Instance('yap_ipython.core.interactiveshell.YAPInteractiveABC',
|
||||
allow_none=True)
|
||||
# whether interact-loop should start
|
||||
interact = Bool(True)
|
||||
|
||||
user_ns = Instance(dict, args=None, allow_none=True)
|
||||
@observe('user_ns')
|
||||
def _user_ns_changed(self, change):
|
||||
if self.shell is not None:
|
||||
self.shell.user_ns = change['new']
|
||||
self.shell.init_user_ns()
|
||||
|
||||
def init_path(self):
|
||||
"""Add current working directory, '', to sys.path"""
|
||||
if sys.path[0] != '':
|
||||
sys.path.insert(0, '')
|
||||
|
||||
def init_shell(self):
|
||||
raise NotImplementedError("Override in subclasses")
|
||||
|
||||
def init_gui_pylab(self):
|
||||
"""Enable GUI event loop integration, taking pylab into account."""
|
||||
enable = False
|
||||
shell = self.shell
|
||||
if self.pylab:
|
||||
enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
|
||||
key = self.pylab
|
||||
elif self.matplotlib:
|
||||
enable = shell.enable_matplotlib
|
||||
key = self.matplotlib
|
||||
elif self.gui:
|
||||
enable = shell.enable_gui
|
||||
key = self.gui
|
||||
|
||||
if not enable:
|
||||
return
|
||||
|
||||
try:
|
||||
r = enable(key)
|
||||
except ImportError:
|
||||
self.log.warning("Eventloop or matplotlib integration failed. Is matplotlib installed?")
|
||||
self.shell.showtraceback()
|
||||
return
|
||||
except Exception:
|
||||
self.log.warning("GUI event loop or pylab initialization failed")
|
||||
self.shell.showtraceback()
|
||||
return
|
||||
|
||||
if isinstance(r, tuple):
|
||||
gui, backend = r[:2]
|
||||
self.log.info("Enabling GUI event loop integration, "
|
||||
"eventloop=%s, matplotlib=%s", gui, backend)
|
||||
if key == "auto":
|
||||
print("Using matplotlib backend: %s" % backend)
|
||||
else:
|
||||
gui = r
|
||||
self.log.info("Enabling GUI event loop integration, "
|
||||
"eventloop=%s", gui)
|
||||
|
||||
def init_extensions(self):
|
||||
"""Load all IPython extensions in IPythonApp.extensions.
|
||||
|
||||
This uses the :meth:`ExtensionManager.load_extensions` to load all
|
||||
the extensions listed in ``self.extensions``.
|
||||
"""
|
||||
try:
|
||||
self.log.debug("Loading IPython extensions...")
|
||||
extensions = self.default_extensions + self.extensions
|
||||
if self.extra_extension:
|
||||
extensions.append(self.extra_extension)
|
||||
for ext in extensions:
|
||||
try:
|
||||
self.log.info("Loading IPython extension: %s" % ext)
|
||||
self.shell.extension_manager.load_extension(ext)
|
||||
except:
|
||||
if self.reraise_ipython_extension_failures:
|
||||
raise
|
||||
msg = ("Error in loading extension: {ext}\n"
|
||||
"Check your config files in {location}".format(
|
||||
ext=ext,
|
||||
location=self.profile_dir.location
|
||||
))
|
||||
self.log.warning(msg, exc_info=True)
|
||||
except:
|
||||
if self.reraise_ipython_extension_failures:
|
||||
raise
|
||||
self.log.warning("Unknown error in loading extensions:", exc_info=True)
|
||||
|
||||
def init_code(self):
|
||||
"""run the pre-flight code, specified via exec_lines"""
|
||||
self._run_startup_files()
|
||||
self._run_exec_lines()
|
||||
self._run_exec_files()
|
||||
|
||||
# Hide variables defined here from %who etc.
|
||||
if self.hide_initial_ns:
|
||||
self.shell.user_ns_hidden.update(self.shell.user_ns)
|
||||
|
||||
# command-line execution (ipython -i script.py, ipython -m module)
|
||||
# should *not* be excluded from %whos
|
||||
self._run_cmd_line_code()
|
||||
self._run_module()
|
||||
|
||||
# flush output, so itwon't be attached to the first cell
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
|
||||
def _run_exec_lines(self):
|
||||
"""Run lines of code in IPythonApp.exec_lines in the user's namespace."""
|
||||
if not self.exec_lines:
|
||||
return
|
||||
try:
|
||||
self.log.debug("Running code from IPythonApp.exec_lines...")
|
||||
for line in self.exec_lines:
|
||||
try:
|
||||
self.log.info("Running code in user namespace: %s" %
|
||||
line)
|
||||
self.shell.run_cell(line, store_history=False)
|
||||
except:
|
||||
self.log.warning("Error in executing line in user "
|
||||
"namespace: %s" % line)
|
||||
self.shell.showtraceback()
|
||||
except:
|
||||
self.log.warning("Unknown error in handling IPythonApp.exec_lines:")
|
||||
self.shell.showtraceback()
|
||||
|
||||
def _exec_file(self, fname, shell_futures=False):
|
||||
try:
|
||||
full_filename = filefind(fname, [u'.', self.ipython_dir])
|
||||
except IOError:
|
||||
self.log.warning("File not found: %r"%fname)
|
||||
return
|
||||
# Make sure that the running script gets a proper sys.argv as if it
|
||||
# were run from a system shell.
|
||||
save_argv = sys.argv
|
||||
sys.argv = [full_filename] + self.extra_args[1:]
|
||||
try:
|
||||
if os.path.isfile(full_filename):
|
||||
self.log.info("Running file in user namespace: %s" %
|
||||
full_filename)
|
||||
# Ensure that __file__ is always defined to match Python
|
||||
# behavior.
|
||||
with preserve_keys(self.shell.user_ns, '__file__'):
|
||||
self.shell.user_ns['__file__'] = fname
|
||||
if full_filename.endswith('.ipy'):
|
||||
self.shell.safe_execfile_ipy(full_filename,
|
||||
shell_futures=shell_futures)
|
||||
else:
|
||||
# default to python, even without extension
|
||||
self.shell.safe_execfile(full_filename,
|
||||
self.shell.user_ns,
|
||||
shell_futures=shell_futures,
|
||||
raise_exceptions=True)
|
||||
finally:
|
||||
sys.argv = save_argv
|
||||
|
||||
def _run_startup_files(self):
|
||||
"""Run files from profile startup directory"""
|
||||
startup_dirs = [self.profile_dir.startup_dir] + [
|
||||
os.path.join(p, 'startup') for p in chain(ENV_CONFIG_DIRS, SYSTEM_CONFIG_DIRS)
|
||||
]
|
||||
startup_files = []
|
||||
|
||||
if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
|
||||
not (self.file_to_run or self.code_to_run or self.module_to_run):
|
||||
python_startup = os.environ['PYTHONSTARTUP']
|
||||
self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
|
||||
try:
|
||||
self._exec_file(python_startup)
|
||||
except:
|
||||
self.log.warning("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
|
||||
self.shell.showtraceback()
|
||||
for startup_dir in startup_dirs[::-1]:
|
||||
startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
|
||||
startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
|
||||
if not startup_files:
|
||||
return
|
||||
|
||||
self.log.debug("Running startup files from %s...", startup_dir)
|
||||
try:
|
||||
for fname in sorted(startup_files):
|
||||
self._exec_file(fname)
|
||||
except:
|
||||
self.log.warning("Unknown error in handling startup files:")
|
||||
self.shell.showtraceback()
|
||||
|
||||
def _run_exec_files(self):
|
||||
"""Run files from IPythonApp.exec_files"""
|
||||
if not self.exec_files:
|
||||
return
|
||||
|
||||
self.log.debug("Running files in IPythonApp.exec_files...")
|
||||
try:
|
||||
for fname in self.exec_files:
|
||||
self._exec_file(fname)
|
||||
except:
|
||||
self.log.warning("Unknown error in handling IPythonApp.exec_files:")
|
||||
self.shell.showtraceback()
|
||||
|
||||
def _run_cmd_line_code(self):
|
||||
"""Run code or file specified at the command-line"""
|
||||
if self.code_to_run:
|
||||
line = self.code_to_run
|
||||
try:
|
||||
self.log.info("Running code given at command line (c=): %s" %
|
||||
line)
|
||||
self.shell.run_cell(line, store_history=False)
|
||||
except:
|
||||
self.log.warning("Error in executing line in user namespace: %s" %
|
||||
line)
|
||||
self.shell.showtraceback()
|
||||
if not self.interact:
|
||||
self.exit(1)
|
||||
|
||||
# Like Python itself, ignore the second if the first of these is present
|
||||
elif self.file_to_run:
|
||||
fname = self.file_to_run
|
||||
if os.path.isdir(fname):
|
||||
fname = os.path.join(fname, "__main__.py")
|
||||
try:
|
||||
self._exec_file(fname, shell_futures=True)
|
||||
except:
|
||||
self.shell.showtraceback(tb_offset=4)
|
||||
if not self.interact:
|
||||
self.exit(1)
|
||||
|
||||
def _run_module(self):
|
||||
"""Run module specified at the command-line."""
|
||||
if self.module_to_run:
|
||||
# Make sure that the module gets a proper sys.argv as if it were
|
||||
# run using `python -m`.
|
||||
save_argv = sys.argv
|
||||
sys.argv = [sys.executable] + self.extra_args
|
||||
try:
|
||||
self.shell.safe_run_module(self.module_to_run,
|
||||
self.shell.user_ns)
|
||||
finally:
|
||||
sys.argv = save_argv
|
Reference in New Issue