This commit is contained in:
Vitor Santos Costa
2018-01-18 14:47:27 +00:00
parent 791484c132
commit 4c25aa21c5
83 changed files with 4764 additions and 2063 deletions

View File

@@ -1,17 +1,9 @@
set (EXTRAS
MANIFEST.in
YAP_KERNEL.md
)
set (PL_SOURCES
yap_ipython/prolog/jupyter.yap
)
set (PYTHON_SOURCES
yap_ipython/core/getipython.py
yap_ipython/core/__init__.py
yap_ipython/core/interactiveshell.py
yap_ipython/core/modulefind.py
# yap_ipython/core/modulefind.py
yap_ipython/core/oinspect.py
yap_ipython/core/release.py
yap_ipython/core/shellapp.py
@@ -59,19 +51,62 @@
yap_kernel/pylab/config.py
)
configure_file(setup.py.in ${CMAKE_CURRENT_BINARY_DIR}/setup.py)
configure_file(${CMAKE_SOURCE_DIR}/misc/editors/prolog.js.in ${CMAKE_CURRENT_BINARY_DIR}/prolog.js )
set (EXTRAS
MANIFEST.in
YAP_KERNEL.md
setup.py
setup.cfg
README.md
)
set (RESOURCES
resources/custom.js
resources/prolog.js
#resources/logo-32x32.png
#resources/logo-64x64.png
)
set (RENAMED_RESOURCES
resources/logo-32x32.png
resources/logo-64x64.png
# resources/codemirror/mode/prolog/prolog.js
)
set (PL_SOURCES
yap_ipython/prolog/jupyter.yap
)
set(FILES ${PYTHON_SOURCES} ${PL_SOURCES} ${EXTRAS} ${RESOURCES})
set(SETUP_PY ${CMAKE_CURRENT_BINARY_DIR}/setup.py)
add_custom_target( YAPKernel ALL
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${i}
COMMAND ${CMAKE_COMMAND} -E tar cvf ${CMAKE_CURRENT_BINARY_DIR}/yap.tgz ${FILESi}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/resources/logo-32x32.png
COMMAND ${CMAKE_COMMAND} -E tar xvf yap.tgz
COMMAND ${CMAKE_COMMAND} -E copy_if_changed ${CMAKE_SOURCE_DIR}/docs/icons/yap_32z32x32.png ${CMAKE_CURRENT_BINARY_DIR}/resources/logo-32x32.png
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/docs/icons/yap_32x32x32.png
)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/resources/logo-64x64.png
COMMAND ${CMAKE_COMMAND} -E copy_if_changed ${CMAKE_SOURCE_DIR}/docs/icons/yap_64x64x32.png ${CMAKE_CURRENT_BINARY_DIR}/resources/logo-64x64.png
)
add_custom_target(YAP_KERNEL
COMMAND ${CMAKE_COMMAND} -E tar xvf yap.tgz
COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY} build sdist bdist
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS YAP4PY
)
)
install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m pip install --ignore-installed --no-deps .
COMMAND ${PYTHON_EXECUTABLE} -m yap_kernel.kernelspec
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
install(FILES ${PL_SOURCES} DESTINATION ${libpl} )

View File

@@ -1,9 +1,42 @@
/*define(['./prolog.js'], function(){
var onload = function(){
console.log("I am being loaded");
;(function(window_CodeMirror){
"use strict";
};
return {onload:onload}
});*/
// the `require` namespace for codemirror
CM_PATH = "components/codemirror/";
define(
[
"underscore",
"jquery",
CM_PATH + "lib/codemirror",
"base/js/namespace",
// silent upgrades
"./jshint.js",
CM_PATH + "addon/lint/javascript-lint",
CM_PATH + "addon/hint/javascript-hint",
CM_PATH + "addon/lint/lint",
CM_PATH + "addon/hint/show-hint",
"./prolog.js"
],
function(_, $, CodeMirror, Jupyter){
// the main function
cm_tweak_js = function(cell){
var editor = cell.code_mirror,
opts = {},
meta = ensure_ns(cell),
keys = editor.getOption("extraKeys") || {},
mode = editor.getMode();
// only update editors we care about, reset ones we might have messed
if(!editor){
return;
} else {
editor.setOption("mode", "x-text/prolog");
}
}
}
} // the `define` callback
); // the `define`
).call(this, window.CodeMirror);

View File

@@ -39,20 +39,19 @@ pjoin = os.path.join
here = os.path.abspath(os.path.dirname(__file__))
# pkg_root = pjoin(here, name)
packages = setuptools.find_packages('${CMAKE_CURRENT_SOURCE_DIR}')
packages = setuptools.find_packages(here)
# for d, _, _ in os.walk(pjoin(here, name)):
# if os.path.exists(pjoin(d, '__init__.py')):
# packages.append(d[len(here)+1:].replace(os.path.sep, '.'))
sys.path.insert(0, "${CMAKE_CURRENT_SOURCE_DIR}")
sys.path.insert(0, here)
package_data = {
'yap_ipython': ['prolog/*.*'],
'yap_kernel': ['resources/*.*']
}
version_ns = {}
with open(pjoin('${CMAKE_CURRENT_SOURCE_DIR}', name, '_version.py')) as f:
version_ns = {here, name, '_version.py')) as f:
exec(f.read(), {}, version_ns)
@@ -65,7 +64,7 @@ setup_args = dict(
packages = packages,
py_modules = ['yap_kernel_launcher'],
package_data = package_data,
package_dir = {'':"${CMAKE_CURRENT_SOURCE_DIR}"},
package_dir = {'':here},
description = "YAP Kernel for Jupyter",
author = 'YAP Development Team',
author_email = 'YAP-dev@scipy.org',
@@ -95,29 +94,24 @@ if any(a.startswith(('bdist', 'build', 'install')) for a in sys.argv):
from yap_kernel.kernelspec import write_kernel_spec, make_yap_kernel_cmd, KERNEL_NAME
argv = make_yap_kernel_cmd(executable='python')
argv = make_yap_kernel_cmd(executable=sys.executable)
dest = os.path.join(here, 'resources')
try:
shutil.rmtree(dest)
os.makedirs( dest )
shutil.copy2('${CMAKE_SOURCE_DIR}/docs/icons/yap_32x32x32.png',pjoin(dest,"logo_32x32.png"))
shutil.copy2('${CMAKE_SOURCE_DIR}/docs/icons/yap_64x64x32.png',pjoin(dest,"logo_64x64.png"))
write_kernel_spec(dest, overrides={'argv': argv})
except:
pass
# shutil.copy('${CMAKE_CURRENT_SOURCE_DIR}/kernel.js',dest)
# shutil.copy('${CMAKE_SOURCE_DIR}/misc/editors/prolog.js',dest)
setup_args['data_files'] = [(pjoin('share', 'jupyter', 'kernels', KERNEL_NAME), glob(pjoin(dest, '*')))]
#setup_args['data_files'] = [(pjoin('share', 'jupyter', 'kernels', KERNEL_NAME), glob(pjoin(dest, '*')))]
mode_loc = pjoin( sysconfig.get_path('platlib'), 'notebook', 'static', 'components', 'codemirror', 'mode', 'prolog')
custom_loc = pjoin( sysconfig.get_path('platlib'), 'notebook', 'static', 'custom')
# try:
# shutil.copy( pjoin( custom_loc, "custom.js") , pjoin( custom_loc, "custom.js.orig"))
# shutil.copy( "${CMAKE_CURRENT_SOURCE_DIR}/custom.js" , pjoin( custom_loc, "custom.js"))
# if not os.path.exists(mode_loc):
# os.makedirs(mode_loc)
# shutil.copy( "${CMAKE_SOURCE_DIR}/misc/editors/prolog.js" , mode_loc)
# except:
# pass
try:
shutil.copy( pjoin( custom_loc, "custom.js") , pjoin( custom_loc, "custom.js.orig"))
shutil.copy( pjoin( "resources", "custom.js") , pjoin( custom_loc, "custom.js"))
if not os.path.exists(mode_loc):
os.makedirs(mode_loc)
shutil.copy( pjoin( "resources","prolog.js") , mode_loc)
except:
pass
extras_require = setuptools_args['extras_require'] = {
'test:python_version=="2.7"': ['mock'],

View File

@@ -74,7 +74,7 @@ manager.
You will find that the following are experimental:
- :any:`provisionalcompleter`
- :any:`IPCompleter.completions`
- :any:PyCompleter.completions`
- :any:`Completion`
- :any:`rectify_completions`
@@ -154,7 +154,7 @@ except ImportError:
#-----------------------------------------------------------------------------
# Public API
__all__ = ['Completer','IPCompleter']
__all__ = ['Completer','YAPCompleter']
if sys.platform == 'win32':
PROTECTABLES = ' '
@@ -349,7 +349,7 @@ class Completion:
Completion object used and return by yap_ipython completers.
.. warning:: Unstable
This function is unstable, API may change without warning.
It will also raise unless use in proper context manager.
@@ -590,7 +590,7 @@ class Completer(Configurable):
'information for experimental jedi integration.')\
.tag(config=True)
backslash_combining_completions = Bool(True,
backslash_combining_completions = Bool(True,
help="Enable unicode completions, e.g. \\alpha<tab> . "
"Includes completion of latex commands, unicode names, and expanding "
"unicode characters back to latex commands.").tag(config=True)
@@ -692,7 +692,7 @@ class Completer(Configurable):
# Another option, seems to work great. Catches things like ''.<tab>
m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
if m:
expr, attr = m.group(1, 3)
elif self.greedy:
@@ -702,7 +702,7 @@ class Completer(Configurable):
expr, attr = m2.group(1,2)
else:
return []
try:
obj = eval(expr, self.namespace)
except:
@@ -737,7 +737,7 @@ def get__all__entries(obj):
words = getattr(obj, '__all__')
except:
return []
return [w for w in words if isinstance(w, str)]
@@ -886,14 +886,14 @@ def _safe_isinstance(obj, module, class_name):
def back_unicode_name_matches(text):
u"""Match unicode characters back to unicode name
This does ``☃`` -> ``\\snowman``
Note that snowman is not a valid python3 combining character but will be expanded.
Though it will not recombine back to the snowman character by the completion machinery.
This will not either back-complete standard sequences like \\n, \\b ...
Used on Python 3 only.
"""
if len(text)<2:
@@ -916,7 +916,7 @@ def back_unicode_name_matches(text):
def back_latex_name_matches(text:str):
"""Match latex characters back to unicode name
This does ``\\ℵ`` -> ``\\aleph``
Used on Python 3 only.
@@ -990,7 +990,7 @@ def _make_signature(completion)-> str:
class IPCompleter(Completer):
"""Extension of the completer class with yap_ipython-specific features"""
@observe('greedy')
def _greedy_changed(self, change):
"""update the splitter and readline delims when greedy is changed"""
@@ -998,36 +998,36 @@ class IPCompleter(Completer):
self.splitter.delims = GREEDY_DELIMS
else:
self.splitter.delims = DELIMS
merge_completions = Bool(True,
help="""Whether to merge completion results into a single list
If False, only the completion results from the first non-empty
completer will be returned.
"""
).tag(config=True)
omit__names = Enum((0,1,2), default_value=2,
help="""Instruct the completer to omit private method names
Specifically, when completing on ``object.<tab>``.
When 2 [default]: all names that start with '_' will be excluded.
When 1: all 'magic' names (``__foo__``) will be excluded.
When 0: nothing will be excluded.
"""
).tag(config=True)
limit_to__all__ = Bool(False,
help="""
DEPRECATED as of version 5.0.
Instruct the completer to use __all__ for the completion
Specifically, when completing on ``object.<tab>``.
When True: only those names in obj.__all__ will be included.
When False [default]: the __all__ attribute is ignored
""",
).tag(config=True)
@@ -1060,7 +1060,7 @@ class IPCompleter(Completer):
secondary optional dict for completions, to
handle cases (such as yap_ipython embedded inside functions) where
both Python scopes are visible.
use_readline : bool, optional
DEPRECATED, ignored since yap_ipython 6.0, will have no effects
"""
@@ -1611,7 +1611,7 @@ class IPCompleter(Completer):
closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
if not matches:
return matches
# get the cursor position of
# - the text being completed
# - the start of the key text
@@ -1622,13 +1622,13 @@ class IPCompleter(Completer):
completion_start = key_start + token_offset
else:
key_start = completion_start = match.end()
# grab the leading prefix, to make sure all completions start with `text`
if text_start > key_start:
leading = ''
else:
leading = text[text_start:completion_start]
# the index of the `[` character
bracket_idx = match.end(1)
@@ -1647,18 +1647,18 @@ class IPCompleter(Completer):
# brackets were opened inside text, maybe close them
if not continuation.startswith(']'):
suf += ']'
return [leading + k + suf for k in matches]
def unicode_name_matches(self, text):
u"""Match Latex-like syntax for unicode characters base
on the name of the character.
This does ``\\GREEK SMALL LETTER ETA`` -> ``η``
Works only on valid python 3 identifier, or on combining characters that
will combine to form a valid identifier.
Used on Python 3 only.
"""
slashpos = text.rfind('\\')
@@ -1676,7 +1676,7 @@ class IPCompleter(Completer):
def latex_matches(self, text):
u"""Match Latex syntax for unicode characters.
This does both ``\\alp`` -> ``\\alpha`` and ``\\alpha`` -> ``α``
Used on Python 3 only.
@@ -1748,13 +1748,13 @@ class IPCompleter(Completer):
Returns an iterator over the possible completions
.. warning:: Unstable
This function is unstable, API may change without warning.
It will also raise unless use in proper context manager.
Parameters
----------
text:str
Full text of the current input, multi line string.
offset:int
@@ -1783,7 +1783,7 @@ class IPCompleter(Completer):
and usual yap_ipython completion.
.. note::
Completions are not completely deduplicated yet. If identical
completions are coming from different sources this function does not
ensure that each completion object will only be present once.
@@ -1973,7 +1973,7 @@ class IPCompleter(Completer):
if name_text:
return name_text, name_matches[:MATCHES_LIMIT], \
[meth.__qualname__]*min(len(name_matches), MATCHES_LIMIT), ()
# If no line buffer is given, assume the input text is all there was
if line_buffer is None:

View File

@@ -292,7 +292,7 @@ class InputSplitter(object):
"""
# A cache for storing the current indentation
# The first value stores the most recently processed source input
# The second value is the number of spaces for the current indentation
# The second value is the number of spaces for the current indentation
# If self.source matches the first value, the second value is a valid
# current indentation. Otherwise, the cache is invalid and the indentation
# must be recalculated.
@@ -345,14 +345,14 @@ class InputSplitter(object):
def check_complete(self, source):
"""Return whether a block of code is ready to execute, or should be continued
This is a non-stateful API, and will reset the state of this InputSplitter.
Parameters
----------
source : string
Python input code, which can be multiline.
Returns
-------
status : str
@@ -441,7 +441,7 @@ class InputSplitter(object):
guess whether a block is complete or not based solely on prior and
current input lines. The InputSplitter considers it has a complete
interactive block and will not accept more input when either:
* A SyntaxError is raised
* The code is complete and consists of a single line or a single
@@ -461,20 +461,20 @@ class InputSplitter(object):
if not self._is_complete:
#print("Not complete") # debug
return True
# The user can make any (complete) input execute by leaving a blank line
last_line = self.source.splitlines()[-1]
if (not last_line) or last_line.isspace():
#print("Blank line") # debug
return False
# If there's just a single line or AST node, and we're flush left, as is
# the case after a simple statement such as 'a=1', we want to execute it
# straight away.
if self.get_indent_spaces() == 0:
if len(self.source.splitlines()) <= 1:
return False
try:
code_ast = ast.parse(u''.join(self._buffer))
except Exception:
@@ -528,11 +528,11 @@ class IPythonInputSplitter(InputSplitter):
# String with raw, untransformed input.
source_raw = ''
# Flag to track when a transformer has stored input that it hasn't given
# back yet.
transformer_accumulating = False
# Flag to track when assemble_python_lines has stored input that it hasn't
# given back yet.
within_python_line = False
@@ -547,7 +547,7 @@ class IPythonInputSplitter(InputSplitter):
super(IPythonInputSplitter, self).__init__()
self._buffer_raw = []
self._validate = True
if physical_line_transforms is not None:
self.physical_line_transforms = physical_line_transforms
else:
@@ -557,7 +557,7 @@ class IPythonInputSplitter(InputSplitter):
ipy_prompt(),
cellmagic(end_on_blank_line=line_input_checker),
]
self.assemble_logical_lines = assemble_logical_lines()
if logical_line_transforms is not None:
self.logical_line_transforms = logical_line_transforms
@@ -568,21 +568,21 @@ class IPythonInputSplitter(InputSplitter):
assign_from_magic(),
assign_from_system(),
]
self.assemble_python_lines = assemble_python_lines()
if python_line_transforms is not None:
self.python_line_transforms = python_line_transforms
else:
# We don't use any of these at present
self.python_line_transforms = []
@property
def transforms(self):
"Quick access to all transformers."
return self.physical_line_transforms + \
[self.assemble_logical_lines] + self.logical_line_transforms + \
[self.assemble_python_lines] + self.python_line_transforms
@property
def transforms_in_use(self):
"""Transformers, excluding logical line transformers if we're in a
@@ -607,13 +607,13 @@ class IPythonInputSplitter(InputSplitter):
# Nothing that calls reset() expects to handle transformer
# errors
pass
def flush_transformers(self):
def _flush(transform, outs):
"""yield transformed lines
always strings, never None
transform: the current transform
outs: an iterable of previously transformed inputs.
Each may be multiline, which will be passed
@@ -625,16 +625,16 @@ class IPythonInputSplitter(InputSplitter):
tmp = transform.push(line)
if tmp is not None:
yield tmp
# reset the transform
tmp = transform.reset()
if tmp is not None:
yield tmp
out = []
for t in self.transforms_in_use:
out = _flush(t, out)
out = list(out)
if out:
self._store('\n'.join(out))
@@ -645,7 +645,7 @@ class IPythonInputSplitter(InputSplitter):
out = self.source_raw
self.reset()
return out
def source_reset(self):
try:
self.flush_transformers()
@@ -714,18 +714,14 @@ class IPythonInputSplitter(InputSplitter):
if transformed_lines_list:
transformed_lines = '\n'.join(transformed_lines_list)
return super(IPythonInputSplitter, self).push(transformed_lines)
else:
# Got nothing back from transformers - they must be waiting for
# more input.
return False
return hasSyntaxError(self, lines)
def _transform_line(self, line):
"""Push a line of input code through the various transformers.
Returns any output from the transformers, or None if a transformer
is accumulating lines.
Sets self.transformer_accumulating as a side effect.
"""
def _accumulating(dbg):
@@ -738,24 +734,8 @@ class IPythonInputSplitter(InputSplitter):
if line is None:
return _accumulating(transformer)
if not self.within_python_line:
line = self.assemble_logical_lines.push(line)
if line is None:
return _accumulating('acc logical line')
for transformer in self.logical_line_transforms:
line = transformer.push(line)
if line is None:
return _accumulating(transformer)
line = self.assemble_python_lines.push(line)
if line is None:
self.within_python_line = True
return _accumulating('acc python line')
else:
self.within_python_line = False
for transformer in self.python_line_transforms:
for transformer in self.logical_line_transforms:
line = transformer.push(line)
if line is None:
return _accumulating(transformer)
@@ -763,4 +743,3 @@ class IPythonInputSplitter(InputSplitter):
#print("transformers clear") #debug
self.transformer_accumulating = False
return line

View File

@@ -29,6 +29,7 @@ from io import open as io_open
from pickleshare import PickleShareDB
import yap_ipython.yapi
from traitlets.config.configurable import SingletonConfigurable
from yap_ipython.core import oinspect
from yap_ipython.core import magic
@@ -78,7 +79,7 @@ from traitlets import (
from warnings import warn
from logging import error
import yap_ipython.core.hooks
from yap_ipython.yapi import YAPRun, YAPCompleter
from yap_ipython.yapi import YAPRun, YAPCompleter, YAPInputSplitter
from typing import List as ListType
from ast import AST
@@ -337,15 +338,17 @@ class InteractiveShell(SingletonConfigurable):
# Input splitter, to transform input line by line and detect when a block
# is ready to be executed.
input_splitter = Instance('yap_ipython.core.inputsplitter.IPythonInputSplitter',
(), {'line_input_checker': True})
#input_splitter = Instance('yap_ipython.core.inputsplitter.IPythonInputSplitter',
# (), {'line_input_checker': True})
input_splitter = Instance('yap_ipython.yapi.YAPInputSplitter',
(), {'line_input_checker': False})
# This InputSplitter instance is used to transform completed cells before
# running them. It allows cell magics to contain blank lines.
# input_transformer_manager = Instance('yap_ipython.core.inputsplitter.IPythonInputSplitter',
# (), {'line_input_checker': False})
input_transformer_manager = Instance('yap_ipython.yapi.YAPLineProcessor',
(), {'line_input_checker': False})
input_transformer_manager = Instance('yap_ipython.yapi.YAPInputSplitter',
(), {'line_input_checker': True})
logstart = Bool(False, help=
"""
@@ -476,8 +479,8 @@ class InteractiveShell(SingletonConfigurable):
warn('As of yap_ipython 5.0 `PromptManager` config will have no effect'
' and has been replaced by TerminalInteractiveShell.prompts_class')
self.configurables = [self]
self._yrun_cell = YAPRun._yrun_cell
YAPRun.init(self)
yrun = YAPRun( self)
self._yrun_cell = yrun._yrun_cell
# These are relatively independent and stateless
self.init_ipython_dir(ipython_dir)
@@ -519,6 +522,8 @@ class InteractiveShell(SingletonConfigurable):
# The following was in post_config_initialization
self.init_inspector()
self.raw_input_original = input
self.input_splitter.engine(self.yapeng)
self.input_transformer_manager.engine(self.yapeng)
self.init_completer()
# TODO: init_io() needs to happen before init_traceback handlers
# because the traceback handlers hardcode the stdout/stderr streams.
@@ -541,6 +546,8 @@ class InteractiveShell(SingletonConfigurable):
self.events.trigger('shell_initialized', self)
atexit.register(self.atexit_operations)
def get_ipython(self):
"""Return the currently running yap_ipython instance."""
return self
@@ -1966,23 +1973,20 @@ class InteractiveShell(SingletonConfigurable):
magic_run_completer, cd_completer, reset_completer)
self.Completer = YAPCompleter(shell=self,
namespace=self.user_ns,
global_namespace=self.user_global_ns,
parent=self
)
self.configurables.append(self.Completer)
# Add custom completers to the basic ones built into IPCompleter
sdisp = self.strdispatchers.get('complete_command', StrDispatch())
self.strdispatchers['complete_command'] = sdisp
self.Completer.custom_completers = sdisp
self.set_hook('complete_command', module_completer, str_key = 'import')
self.set_hook('complete_command', module_completer, str_key = 'from')
self.set_hook('complete_command', module_completer, str_key = '%aimport')
self.set_hook('complete_command', magic_run_completer, str_key = '%run')
self.set_hook('complete_command', cd_completer, str_key = '%cd')
self.set_hook('complete_command', reset_completer, str_key = '%reset')
# sdisp = self.strdispatchers.get('complete_command', StrDispatch())
# self.strdispatchers['complete_command'] = sdisp
# self.Completer.custom_completers = sdisp
#
# #self.set_hook('complete_command', module_completer, str_key = 'import')
# #self.set_hook('complete_command', module_completer, str_key = 'from')
# self.set_hook('complete_command', module_completer, str_key = '%aimport')
# self.set_hook('complete_command', magic_run_completer, str_key = '%run')
# self.set_hook('complete_command', cd_completer, str_key = '%cd')
# self.set_hook('complete_command', reset_completer, str_key = '%reset')
def complete(self, text, line=None, cursor_pos=None):
@@ -2376,6 +2380,7 @@ class InteractiveShell(SingletonConfigurable):
# code out there that may rely on this).
self.prefilter = self.prefilter_manager.prefilter_lines
def auto_rewrite_input(self, cmd):
"""Print to the screen the rewritten form of the user's command.
@@ -2658,7 +2663,7 @@ class InteractiveShell(SingletonConfigurable):
"""
try:
result = self._yrun_cell(
self, raw_cell, store_history, silent, shell_futures)
raw_cell, store_history, silent, shell_futures)
finally:
self.events.trigger('post_execute')
if not silent:

View File

@@ -10,214 +10,37 @@
* -
*/
:- module(jupyter, [jupyter_query/3,
ready/3,
valid/3,
errors/2]).
:- module( jupyter,
[jupyter_query/3,
errors/2,
ready/2,
completion/2
]
).
:- use_module(library(yapi)).
:- use_module(library(lists)).
:- use_module(library(maplist)).
:- use_module(library(python)).
:- python_import(sys).
:- use_module(library(yapi)).
:- use_module(library(lists)).
:- use_module(library(maplist)).
:- use_module(library(python)).
:- dynamic user:portray_message/2.
:- multifile user:portray_message/2.
:- python_import(sys).
jupyter_query(Self, Cell, Line ) :-
setup_call_cleanup(
user:jupyter_query(Self, Cell, Line ) :-
setup_call_cleanup(
enter_cell(Self),
jupyter_cell(Self, Cell, Line),
exit_cell(Self)
).
ready(_Self, Line ) :-
blank( Line ),
!.
ready(Self, Line ) :-
errors( Self, Line ),
\+ syntax_error(_,_).
errors( Self, Text ) :-
setup_call_cleanup(
open_events( Self, Text, Stream),
clauses(Self, Stream),
close_events( Self )
).
clauses(Self, Stream) :-
repeat,
read_clause(Stream, Cl, [term_position(_Pos), syntax_errors(fail)] ),
command( Self, Cl ),
Cl == end_of_file,
!.
command( _Self, ( :- op(Prio,Assoc,Name) ) ) :-
addop(Prio,Assoc,Name).
command( _Self, ( :- module(Name, Exports) )) :-
retract( active_module( M0 ) ),
atom_concat( '__m0_', Name, M ),
assert( active_module(M) ),
assert( undo( active_module(M0) ) ),
maplist( addop2(M), Exports).
addop(Prio,Assoc,Name) :-
(
current_op(OPrio, SimilarAssoc, Name),
op(Prio, Assoc, Name),
matched_op(Assoc, SimilarAssoc)
->
assertz( undo(op( OPrio, Assoc, Name ) ) )
;
assertz( undo(op( 0, Assoc, Name ) ) )
).
addop2(M, op(Prio, Assoc, Name)) :-
addop( Prio, Assoc, M:Name ).
matched_op(A, B) :-
optype( A, T),
optype( B, T).
optype(fx,pre).
optype(fy,pre).
optype(xfx,in).
optype(xfy,in).
optype(yfx,in).
optype(yfy,in).
optype(xf,pos).
optype(yf,pos).
:- dynamic user:portray_message/2.
:- multifile user:portray_message/2.
:- dynamic syntax_error/2, undo/1.
open_events(Self, Text, Stream) :-
Self.errors := [],
open_mem_read_stream( Text, Stream ),
assert((user:portray_message(_Severity, error(error(syntax_error(_),info(between(_,LN,_), _FileName, CharPos, _Details)))) :-
assert( syntax_error(LN,CharPos) )
)).
close_events( Self ) :-
retract( undo(G) ),
call(G),
fail.
close_events( Self ) :-
retract( syntax_error( L, N )),
Self.errors := [t(L,N)] + Self.errors,
fail.
close_events( _ ).
cell2pq( Cell, ``, ``) :-
sub_string(Cell, 0, 2, _, `%%`),
string_code(3, Cell, Code),
code_type(Code, alpha),
!.
cell2pq( Cell, P, Q, N) :-
sub_string(Cell, 0, 1, _, `%`),
string_codes(Cell, [Code|Codes]),
code_type(Code, alpha),
skip(10, Codes, Rest, LineF,Line1),
skip_blanks(Rest, Body, Line1,Line0),
reverse(Body, RBody),
cell2pq2(RBody, Ps, Qs, N),
extend(Ps, Qs, LineF, Line0, NPs, NQs),
string_codes(P, NPs),
string_codes(Q, NQs).
cell2pq( Cell, P, Q, N) :-
string_codes(Cell, Codes),
reverse(Codes, RCodes),
cell2pq2(RCodes, NPs, NQs, N),
string_codes(P, NPs),
string_codes(Q, NQs).
%
% terminates with dot
%
cell2pq2(RCodes, NP, NQ, N) :-
skip_allblanks( RCodes, [C|Rest], L1, L0),
( C =:= "."
->
N = 1,
RP = RCodes,
RQ = ""
;
skip_to_blank_line( [C|Rest], RP, L0, []),
RQ = L1,
(
C =:= "*"
->
N = -1
;
N=1
)
),
reverse(RP,NP),
reverse(RQ,NQ).
/**
* @pred skip( Char, Input, Remainder, Begin, End)
*
* split the list according to character _Char_:
*
* - _Remainder_ is what is after chars
* - _Begin_-_End_ represents what is before char.
*
*/
skip(_, "", "") -->
!,
[].
skip(C, [C|Cs], Cs) -->
!,
[C].
skip(C, [OC|Cs], Line) -->
[OC],
skip(C,Cs, Line).
skip_to_blank_line("", "") -->
!.
skip_to_blank_line(Cs, Left) -->
blank_line(Cs, Left),
!,
[].
skip_to_blank_line(Cs, Line) -->
line(Cs, Line),
!.
blank_line("", []) --> [].
blank_line([10|Cs], Cs) -->
[10],
!.
blank_line([C|Cs], Rest) -->
{ code_type(C, white)},
!,
[C],
blank_line(Cs, Rest).
line("", []) -->
[].
line([10|Cs], Cs) -->
[10],
!.
line([C|Cs], Rest) -->
[C],
line(Cs,Rest).
jupyter_cell(_Self, Cell, _) :-
% stop_low_level_trace,
jupyter_consult(Cell),
fail.
jupyter_cell( _Self, _, Line ) :-
blank( Line ),
!.
jupyter_cell( Self, _, [] ) :- !.
jupyter_cell( Self, _, Line ) :-
% start_low_level_trace,
python_query( Self, Line ).
jupyter_consult(Text) :-
@@ -250,14 +73,14 @@ exit_cell(_Self) :-
close( user_error).
completions(S, Self) :-
user:completions(S, Self) :-
open_mem_read_stream(S, St),
scan_to_list(St, Tokens),
close(St),
reverse(Tokens, RTokens),
strip_final_tokens(RTokens, MyTokens),
setof( Completion, complete(MyTokens, Completion), Cs),
Self.completions := Cs.
Self.matches := Cs.
strip_final_tokens(['EOT'|Ts], Ts) :- !.
@@ -347,3 +170,88 @@ cont(0, F, P, P0) :-
atom_concat( F, P, P0 ).
cont( _, F, P, PB ):-
atom_concat( [F, P, '('], PB ).
ready(_Self, Line ) :-
blank( Line ),
!.
ready(Self, Line ) :-
errors( Self, Line ),
\+ syntax_error(_,_).
user:errors( Self, Text ) :-
setup_call_cleanup(
open_events( Self, Text, Stream),
clauses(Self, Stream),
close_events( Self )
).
clauses(Self, Stream) :-
repeat,
read_clause(Stream, Cl, [term_position(_Pos), syntax_errors(fail)] ),
command( Self, Cl ),
Cl == end_of_file,
!.
command(_, end_of_file) :- !.
command( _Self, ( :- op(Prio,Assoc,Name) ) ) :-
addop(Prio,Assoc,Name).
command( _Self, ( :- module(Name, Exports) )) :-
retract( active_module( M0 ) ),
atom_concat( '__m0_', Name, M ),
assert( active_module(M) ),
assert( undo( active_module(M0) ) ),
maplist( addop2(M), Exports).
addop(Prio,Assoc,Name) :-
(
current_op(OPrio, SimilarAssoc, Name),
op(Prio, Assoc, Name),
matched_op(Assoc, SimilarAssoc)
->
assertz( undo(op( OPrio, Assoc, Name ) ) )
;
assertz( undo(op( 0, Assoc, Name ) ) )
).
addop2(M, op(Prio, Assoc, Name)) :-
addop( Prio, Assoc, M:Name ).
matched_op(A, B) :-
optype( A, T),
optype( B, T).
optype(fx,pre).
optype(fy,pre).
optype(xfx,in).
optype(xfy,in).
optype(yfx,in).
optype(yfy,in).
optype(xf,pos).
optype(yf,pos).
:- dynamic user:portray_message/2.
:- multifile user:portray_message/2.
:- dynamic syntax_error/4, undo/1.
open_events(Self, Text, Stream) :-
Self.errors := [],
open_mem_read_stream( Text, Stream ),
assert((user:portray_message(_Severity, error(syntax_error(Cause),info(between(_,LN,_), _FileName, CharPos, Details))) :-
assert( syntax_error(Cause,LN,CharPos,Details) )
)).
close_events( Self ) :-
retract( undo(G) ),
call(G),
fail.
close_events( Self ) :-
retract( syntax_error( C, L, N, A )),
Self.errors := [t(C,L,N,A)] + Self.errors,
fail.
close_events( _ ).

View File

@@ -3,8 +3,8 @@ import sys
from yap_ipython.core.debugger import Pdb
from yap_ipython.core.completer import IPCompleter
from .ptutils import IPythonPTCompleter
from yap_ipython.yapi import YAPCompleter
#from .ptutils import IPythonPTCompleter
from .shortcuts import suspend_to_bg, cursor_in_leading_ws
from prompt_toolkit.enums import DEFAULT_BUFFER

View File

@@ -33,7 +33,7 @@ from .debugger import TerminalPdb, Pdb
from .magics import TerminalMagics
from .pt_inputhooks import get_inputhook_name_and_func
from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
from .ptutils import IPythonPTCompleter, IPythonPTLexer
#from .ptutils import IPythonPTCompleter, IPythonPTLexer
from .shortcuts import register_ipython_shortcuts
DISPLAY_BANNER_DEPRECATED = object()
@@ -269,8 +269,8 @@ class TerminalInteractiveShell(InteractiveShell):
editing_mode=editing_mode,
key_bindings_registry=kbmanager.registry,
history=history,
completer=IPythonPTCompleter(shell=self,
patch_stdout=patch_stdout),
# completer=IPythonPTCompleter(shell=self,
# patch_stdout=patch_stdout),
enable_history_search=True,
style=self.style,
mouse_support=self.mouse_support,

View File

@@ -18,7 +18,7 @@ from traitlets.config.loader import Config
from traitlets.config.application import boolean_flag, catch_config_error
from yap_ipython.core import release
from yap_ipython.core import usage
from yap_ipython.core.completer import IPCompleter
from yap_ipython.yapi import YAPCompleter
from yap_ipython.core.crashhandler import CrashHandler
from yap_ipython.core.formatters import PlainTextFormatter
from yap_ipython.core.history import HistoryManager
@@ -177,7 +177,7 @@ class LocateIPythonApp(BaseYAPApplication):
class TerminalIPythonApp(BaseYAPApplication, InteractiveShellApp):
name = u'ipython'
name = u'yap'
description = usage.cl_usage
crash_handler_class = IPAppCrashHandler
examples = _examples
@@ -202,7 +202,7 @@ class TerminalIPythonApp(BaseYAPApplication, InteractiveShellApp):
HistoryManager,
ProfileDir,
PlainTextFormatter,
IPCompleter,
YAPCompleter,
ScriptMagics,
LoggingMagics,
StoreMagics,
@@ -301,7 +301,7 @@ class TerminalIPythonApp(BaseYAPApplication, InteractiveShellApp):
argv[idx] = '--pylab'
return super(TerminalIPythonApp, self).parse_command_line(argv)
@catch_config_error
def initialize(self, argv=None):
"""Do actions after construct, but before starting the app."""

View File

@@ -2,17 +2,23 @@ import os
import sys
import abc
import math
import itertools
from typing import Iterator, List, Tuple, Iterable, Union
from traitlets import Bool, Enum, observe, Int
try:
import yap4py.yapi
from yap4py.yapi import Engine
except:
print("Could not load _yap dll.")
from yap_ipython.core import interactiveshell
from yap_ipython.core.completer import IPCompleter
from yap_ipython.core.completer import Completer, Completion
from yap_ipython.utils.strdispatch import StrDispatch
# import yap_ipython.core
from traitlets import Instance
from yap_ipython.core.inputsplitter import *
from yap_ipython.core.inputtransformer import *
from pygments import highlight
from pygments.lexers.prolog import PrologLexer
from pygments.formatters import HtmlFormatter
@@ -26,18 +32,278 @@ library = namedtuple('library', 'list')
v = namedtuple('_', 'slot')
load_files = namedtuple('load_files', 'file ofile args')
python_query= namedtuple('python_query', 'query_mgr string')
JupyterQuery = namedtuple('jupyter_query', 'self text query')
jupyter_query = namedtuple('jupyter_query', 'self text query')
enter_cell = namedtuple('enter_cell', 'self' )
exit_cell = namedtuple('exit_cell', 'self' )
completions = namedtuple('completions', 'txt self' )
errors = namedtuple('errors', 'self text' )
class YAPCompleter:
def __init__(self,
shell=None, namespace=None, global_namespace=None,
parent=None,
):
self.completions = None
class YAPInputSplitter(InputSplitter):
"""An input splitter that recognizes all of iyap's special syntax."""
# String with raw, untransformed input.
source_raw = ''
# Flag to track when a transformer has stored input that it hasn't given
# back yet.
transformer_accumulating = False
# Flag to track when assemble_yap_lines has stored input that it hasn't
# given back yet.
within_yap_line = False
# Private attributes
# List with lines of raw input accumulated so far.
_buffer_raw = None
def __init__(self, line_input_checker=True, physical_line_transforms=None,
logical_line_transforms=None):
self._buffer_raw = []
self._validate = True
self.yapeng = None
if physical_line_transforms is not None:
self.physical_line_transforms = physical_line_transforms
else:
self.physical_line_transforms = [
leading_indent(),
classic_prompt(),
ipy_prompt(),
cellmagic(end_on_blank_line=line_input_checker),
]
self.assemble_logical_lines = assemble_logical_lines()
if logical_line_transforms is not None:
self.logical_line_transforms = logical_line_transforms
else:
self.logical_line_transforms = [
help_end(),
escaped_commands(),
assign_from_magic(),
assign_from_system(),
]
@property
def transforms(self):
"Quick access to all transformers."
return self.physical_line_transforms + \
[self.assemble_logical_lines] + self.logical_line_transforms
@property
def transforms_in_use(self):
"""Transformers, excluding logical line transformers if we're in a
Python line."""
t = self.physical_line_transforms + \
[self.assemble_logical_lines] + self.logical_line_transforms
def engine(self, engine):
self.yapeng = engine
def validQuery(self, text, line=None):
"""Return whether a legal query
"""
if not line:
(_,line,_) = self.shell.prolog_cell(text)
line = line.strip().rstrip()
if not line:
return False
self.errors = []
self.yapeng.mgoal(errors(self, line),"user")
return self.errors != []
def reset(self):
"""Reset the input buffer and associated state."""
#super(YAPInputSplitter, self).reset()
self._buffer_raw[:] = []
self.source_raw = ''
self.transformer_accumulating = False
for t in self.transforms:
try:
t.reset()
except SyntaxError:
# Nothing that calls reset() expects to handle transformer
# errors
pass
def flush_transformers(self):
def _flush(transform, outs):
"""yield transformed lines
always strings, never None
transform: the current transform
outs: an iterable of previously transformed inputs.
Each may be multiline, which will be passed
one line at a time to transform.
"""
for out in outs:
for line in out.splitlines():
# push one line at a time
tmp = transform.push(line)
if tmp is not None:
yield tmp
# reset the transform
tmp = transform.reset()
if tmp is not None:
yield tmp
out = []
for t in self.transforms:
out = _flush(t, out)
out = list(out)
if out:
self._store('\n'.join(out))
def raw_reset(self):
"""Return raw input only and perform a full reset.
"""
out = self.source_raw
self.reset()
return out
def source_reset(self):
try:
self.flush_transformers()
return self.source
finally:
self.reset()
def push_accepts_more(self):
if self.transformer_accumulating:
return True
else:
return self,validQuery(self.source)
def transform_cell(self, cell):
"""Process and translate a cell of input.
"""
self.reset()
try:
self.push(cell)
self.flush_transformers()
return self.source
finally:
self.reset()
def push(self, lines):
"""Push one or more lines of yap_ipython input.
This stores the given lines and returns a status code indicating
whether the code forms a complete Python block or not, after processing
all input lines for special yap_ipython syntax.
Any exceptions generated in compilation are swallowed, but if an
exception was produced, the method returns True.
Parameters
----------
lines : string
One or more lines of Python input.
Returns
-------
is_complete : boolean
True if the current input source (the result of the current input
plus prior inputs) forms a complete Python execution block. Note that
this value is also stored as a private attribute (_is_complete), so it
can be queried at any time.
"""
# We must ensure all input is pure unicode
lines = cast_unicode(lines, self.encoding)
# ''.splitlines() --> [], but we need to push the empty line to transformers
lines_list = lines.splitlines()
if not lines_list:
lines_list = ['']
# Store raw source before applying any transformations to it. Note
# that this must be done *after* the reset() call that would otherwise
# flush the buffer.
self._store(lines, self._buffer_raw, 'source_raw')
transformed_lines_list = []
for line in lines_list:
transformed = self._transform_line(line)
if transformed is not None:
transformed_lines_list.append(transformed)
if transformed_lines_list:
transformed_lines = '\n'.join(transformed_lines_list)
else:
# Got nothing back from transformers - they must be waiting for
# more input.
return False
def _transform_line(self, line):
"""Push a line of input code through the various transformers.
Returns any output from the transformers, or None if a transformer
is accumulating lines.
Sets self.transformer_accumulating as a side effect.
"""
def _accumulating(dbg):
#print(dbg)
self.transformer_accumulating = True
return None
for transformer in self.physical_line_transforms:
line = transformer.push(line)
if line is None:
return _accumulating(transformer)
for transformer in self.logical_line_transforms:
line = transformer.push(line)
if line is None:
return _accumulating(transformer)
#print("transformers clear") #debug
self.transformer_accumulating = False
return line
class YAPCompleter(Completer):
greedy = Bool(False,
help="""Activate greedy completion
PENDING DEPRECTION. this is now mostly taken care of with Jedi.
This will enable completion on elements of lists, results of function calls, etc.,
but can be unsafe because the code is actually evaluated on TAB.
"""
).tag(config=True)
debug = Bool(default_value=False,
help='Enable debug for the Completer. Mostly print extra '
'information for experimental jedi integration.') \
.tag(config=True)
backslash_combining_completions = Bool(True,
help="Enable unicode completions, e.g. \\alpha<tab> . "
"Includes completion of latex commands, unicode names, and expanding "
"unicode characters back to latex commands.").tag(config=True)
def __init__(self, namespace=None, global_namespace=None, shell=None, **kwargs):
"""Create a new completer for the command line.
Completer(namespace=ns, global_namespace=ns2) -> completer instance.
"""
self.shell = shell
self.magic_escape = ESC_MAGIC
super(Completer, self).__init__(**kwargs)
def complete(self, text, line=None, cursor_pos=None):
"""Return the completed text and a list of completions.
@@ -50,6 +316,9 @@ class YAPCompleter:
instead a line/position pair are given. In this case, the
completer itself will split the line like readline does.
This is called successively with state == 0, 1, 2, ... until it
returns None. The completion should begin with 'text'.
line : string, optional
The complete line that text is part of.
@@ -79,65 +348,197 @@ class YAPCompleter:
In [2]: _ip.complete('x.l')
Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
"""
if not text:
text = line[:cursor_pos]
self.yapeng.goal(completions(text, self))
return text, self.completions
return self.completions(text, cursor_pos)
# def _init__(self, **kwargs) -> None:
# PyCompleter.__init__(**kwargs__)
def magic_matches(self, text):
"""Match magics"""
# Get all shell magics now rather than statically, so magics loaded at
# runtime show up too.
lsm = self.shell.magics_manager.lsmagic()
line_magics = lsm['line']
cell_magics = lsm['cell']
pre = self.magic_escape
pre2 = pre+pre
explicit_magic = text.startswith(pre)
# Completion logic:
# - user gives %%: only do cell magics
# - user gives %: do both line and cell magics
# - no prefix: do both
# In other words, line magics are skipped if the user gives %% explicitly
#
# We also exclude magics that match any currently visible names:
# https://github.com/ipython/ipython/issues/4877, unless the user has
# typed a %:
# https://github.com/ipython/ipython/issues/10754
bare_text = text.lstrip(pre)
global_matches = []
if not explicit_magic:
def matches(magic):
"""
Filter magics, in particular remove magics that match
a name present in global namespace.
"""
return ( magic.startswith(bare_text) and
magic not in global_matches )
else:
def matches(magic):
return magic.startswith(bare_text)
comp = [ pre2+m for m in cell_magics if matches(m)]
if not text.startswith(pre2):
comp += [ pre+m for m in line_magics if matches(m)]
return comp
def magic_config_matches(self, text:str) -> List[str]:
""" Match class names and attributes for %config magic """
texts = text.strip().split()
if len(texts) > 0 and (texts[0] == 'config' or texts[0] == '%config'):
# get all configuration classes
classes = sorted(set([ c for c in self.shell.configurables
if c.__class__.class_traits(config=True)
]), key=lambda x: x.__class__.__name__)
classnames = [ c.__class__.__name__ for c in classes ]
# return all classnames if config or %config is given
if len(texts) == 1:
return classnames
# match classname
classname_texts = texts[1].split('.')
classname = classname_texts[0]
classname_matches = [ c for c in classnames
if c.startswith(classname) ]
# return matched classes or the matched class with attributes
if texts[1].find('.') < 0:
return classname_matches
elif len(classname_matches) == 1 and \
classname_matches[0] == classname:
cls = classes[classnames.index(classname)].__class__
help = cls.class_get_help()
# strip leading '--' from cl-args:
help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
return [ attr.split('=')[0]
for attr in help.strip().splitlines()
if attr.startswith(texts[1]) ]
return []
def magic_color_matches(self, text:str) -> List[str] :
""" Match color schemes for %colors magic"""
texts = text.split()
if text.endswith(' '):
# .split() strips off the trailing whitespace. Add '' back
# so that: '%colors ' -> ['%colors', '']
texts.append('')
if len(texts) == 2 and (texts[0] == 'colors' or texts[0] == '%colors'):
prefix = texts[1]
return [ color for color in InspectColors.keys()
if color.startswith(prefix) ]
return []
class YAPLineProcessor:
def __init__(self,
shell
):
self.engine = shell.engine
def validQuery(self, text, line=None, cursor_pos=None):
"""Return whether a legal query
def completions(self, text, offset):
"""
if not line:
(_,line,_) = self.prolog_cell(text)
line = line.strip().rstrip()
if not line:
return False
self.yapeng.goal(errors(text, line))
return not self.errors
Returns an iterator over the possible completions
# def _init__(self, **kwargs) -> None:
# PyCompleter.__init__(**kwargs__)
.. warning:: Unstable
This function is unstable, API may change without warning.
It will also raise unless use in proper context manager.
Parameters
----------
text:str
Full text of the current input, multi line string.
offset:int
Integer representing the position of the cursor in ``text``. Offset
is 0-based indexed.
Yields
------
:any:`Completion` object
The cursor on a text can either be seen as being "in between"
characters or "On" a character depending on the interface visible to
the user. For consistency the cursor being on "in between" characters X
and Y is equivalent to the cursor being "on" character Y, that is to say
the character the cursor is on is considered as being after the cursor.
Combining characters may span more that one position in the
text.
.. note::
If ``IPCompleter.debug`` is :any:`True` will yield a ``--jedi/ipython--``
fake Completion token to distinguish completion returned by Jedi
and usual yap_ipython completion.
.. note::
Completions are not completely deduplicated yet. If identical
completions are coming from different sources this function does not
ensure that each completion object will only be present once.
"""
self.matches = []
prolog_res = self.shell.yapeng.mgoal(completions(text, self), "user")
magic_res = self.magic_matches(text)
return text, self.matches+magic_res
class YAPRun():
class YAPRun:
"""An enhanced, interactive shell for YAP."""
def init(self):
self.yapeng = yap4py.yapi.Engine()
def __init__(self, shell):
self.shell = shell
self.yapeng = Engine()
self.yapeng.goal(use_module(library("jupyter")))
self.q = None
self.run = False
self.port = None
self.shell.port = None
self.shell.yapeng = self.yapeng
self._get_exc_info = shell._get_exc_info
def syntaxErrors(self, text):
"""Return whether a legal query
"""
if not text:
return []
self.errors=[]
self.yapeng.mgoal(errors(self,text),"user")
return self.errors
def jupyter_query(self, s):
# import pdb; pdb.set_trace()
#
# construct a self.query from a one-line string
# self.q is opaque to Python
self.bindings = {}
iterations = 0
self.shell.bindings = {}
if self.q and s != self.os:
self.q.close()
self.q = None
if not self.q:
#import pdb; pdb.set_trace()
self.port = "call"
program,query,iterations = YAPRun.prolog_cell(self,s)
self.q = self.yapeng.query(JupyterQuery(self, program, query))
self.Solutions = []
self.shell.port = "call"
program,query,_ = self.prolog_cell(s)
self.q = self.yapeng.query(jupyter_query(self, program, query))
self.shell.Solutions = []
if not self.q:
return True, []
self.os = s
@@ -162,27 +563,26 @@ class YAPRun():
# deterministic = one solution
#Dict = {}
#engine.goal(show_answer( q.namedVars(), Dict))
self.Solutions += [self.bindings]
if self.port == "exit":
self.shell.Solutions += [self.shell.bindings]
if self.shell.port == "exit":
# done
self.q.close()
self.q = None
self.os = ""
return True, self.Solutions
return True, self.shell.Solutions
if iterations == 0:
return True, self.Solutions
return True, self.shell.Solutions
else:
print("No (more) answers")
self.q.close()
self.q = None
self.os = ''
return True, self.Solutions
return True, self.shell.Solutions
def answer(self, q):
try:
return q.next()
except Exception as e:
print(e.args[1])
self.yapeng.goal(exit_cell(self))
return False, None
@@ -236,69 +636,75 @@ class YAPRun():
result = interactiveshell.ExecutionResult(info)
if (raw_cell == "") or raw_cell.isspace():
self.last_execution_succeeded = True
self.shell.last_execution_succeeded = True
return result
if silent:
store_history = False
if store_history:
result.execution_count = self.execution_count+1
result.execution_count = self.shell.execution_count+1
def error_before_exec(value):
result.error_before_exec = value
self.last_execution_succeeded = False
self.shell.last_execution_succeeded = False
return result
self.events.trigger('pre_execute')
self.shell.events.trigger('pre_execute')
if not silent:
self.events.trigger('pre_run_cell')
self.shell.events.trigger('pre_run_cell')
# If any of our input transformation (input_transformer_manager or
# prefilter_manager) raises an exception, we store it in this variable
# so that we can display the error after logging the input and storing
# it in the history.
preprocessing_exc_tuple = None
try:
# Static input transformations
cell = self.input_transformer_manager.transform_cell(raw_cell)
except SyntaxError:
preprocessing_exc_tuple = self.syntax_error() # sys.exc_info()
# try:
# # Static input transformations
# cell = self.shell.input_transformer_manager.transform_cell(raw_cell)
# except SyntaxError:
# preprocessing_exc_tuple = self.shell.syntax_error() # sys.exc_info()
cell = raw_cell # cell has to exist so it can be stored/logged
# else:
# # import pdb; pdb.set_trace()
# if False and len(cell.splitlines()) == 1:
# # Dynamic transformations - only applied for single line commands
# with self.builtin_trap:
# with self.shell.builtin_trap:
# try:
# # use prefilter_lines to handle trailing newlines
# # restore trailing newline for ast.parse
# cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
# cell = self.shell.prefilter_manager.prefilter_lines(cell) + '\n'
# except Exception:
# # don't allow prefilter errors to crash IPython
# preprocessing_exc_tuple = sys.exc_info()
e for i in self.syntaxErrors(raw_cell):
try:
(what,lin,_,text) = i
e = SyntaxError(what, ("<string>", lin, 1, text))
raise e
except SyntaxError:
self.shell.showsyntaxerror( )
preprocessing_exc_tuple = sys.exc_info()
# Store raw and processed history
if store_history:
self.history_manager.store_inputs(self.execution_count,
self.shell.history_manager.store_inputs(self.shell.execution_count,
cell, raw_cell)
if not silent:
self.logger.log(cell, raw_cell)
self.shell.logger.log(cell, raw_cell)
# # Display the exception if input processing failed.
# if preprocessing_exc_tuple is not None:
# self.showtraceback(preprocessing_exc_tuple)
# if store_history:
# self.execution_count += 1
# self.shell.execution_count += 1
# return error_before_exec(preprocessing_exc_tuple[2])
# Our own compiler remembers the __future__ environment. If we want to
# run code with a separate __future__ environment, use the default
# compiler
# compiler = self.compile if shell_futures else CachingCompiler()
cell_name = str( self.execution_count)
# compiler = self.shell.compile if shell_futures else CachingCompiler()
cell_name = str( self.shell.execution_count)
if cell[0] == '%':
if cell[1] == '%':
@@ -309,53 +715,53 @@ class YAPRun():
mcell = cell.lstrip('%')
txt0 = mcell.split(maxsplit = 2, sep = '\n')
txt = txt0[0].split(maxsplit = 2)
magic = txt[0]
magic = txt[0]
if len(txt) == 2:
line = txt[1]
else:
line = ""
if linec:
self.run_line_magic(magic, line)
self.shell.run_line_magic(magic, line)
if len(txt0) == 2:
cell = txt0[1]
else:
cellArea = ""
else:
self.run_cell_magic(magic, line, cell)
self.shell.run_cell_magic(magic, line, cell)
return
# Give the displayhook a reference to our ExecutionResult so it
# can fill in the output value.
self.displayhook.exec_result = result
self.shell.displayhook.exec_result = result
has_raised = False
try:
self.bindings = dict = {}
state = YAPRun.jupyter_query(self, cell)
self.shell.bindings = dict = {}
state = self.jupyter_query( cell)
if state:
self.last_execution_succeeded = True
self.shell.last_execution_succeeded = True
result.result = (True, dict)
else:
self.last_execution_succeeded = True
self.shell.last_execution_succeeded = True
result.result = (True, {})
except Exception as e:
print(e)
has_raised = True
result.result = False
self.last_execution_succeeded = not has_raised
self.shell.last_execution_succeeded = not has_raised
# Reset this so later displayed values do not modify the
# ExecutionResult
self.displayhook.exec_result = None
self.events.trigger('post_execute')
self.shell.displayhook.exec_result = None
self.shell.events.trigger('post_execute')
if not silent:
self.events.trigger('post_run_cell')
self.shell.events.trigger('post_run_cell')
if store_history:
# Write output to the database. Does nothing unless
# history output logging is enabled.
self.history_manager.store_output(self.execution_count)
self.shell.history_manager.store_output(self.shell.execution_count)
# Each cell is a *single* input, regardless of how many lines it has
self.execution_count += 1
self.shell.execution_count += 1
return result
@@ -377,12 +783,14 @@ class YAPRun():
its = 0
s0 = ''
for c in s:
if c == '\n' or c.isblank():
s0 += [c]
if c == '\n' or c.isspace():
s0 += c
break
sf = ''
for c in reversed(s):
if c == '\n' or c.isblank():
sf += [c]+sf
if c == '\n' or c.isspace():
sf += c
break
[program,x,query] = s.rpartition('\n')
if query == '':
query = program

View File

@@ -15,7 +15,7 @@ from .zmqshell import ZMQInteractiveShell
try:
from yap_ipython.core.completer import rectify_completions as _rectify_completions, provisionalcompleter as _provisionalcompleter
_use_experimental_60_completion = True
_use_experimental_60_completion = False
except ImportError:
_use_experimental_60_completion = False
@@ -203,6 +203,7 @@ class YAPKernel(KernelBase):
self._forward_input(allow_stdin)
reply_content = {}
import trace;
try:
res = shell.run_cell(code, store_history=store_history, silent=silent)
finally:

View File

@@ -35,14 +35,14 @@ from jupyter_client import write_connection_file
from jupyter_client.connect import ConnectionFileMixin
# local imports
from .iostream import IOPubThread
from .heartbeat import Heartbeat
from .ipkernel import YAPKernel
from .parentpoller import ParentPollerUnix, ParentPollerWindows
from yap_kernel.iostream import IOPubThread
from yap_kernel.heartbeat import Heartbeat
from yap_kernel.ipkernel import YAPKernel
from yap_kernel.parentpoller import ParentPollerUnix, ParentPollerWindows
from jupyter_client.session import (
Session, session_flags, session_aliases,
)
from .zmqshell import ZMQInteractiveShell
from yap_kernel.zmqshell import ZMQInteractiveShell
#-----------------------------------------------------------------------------
# Flags and Aliases

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -235,7 +235,7 @@ class KernelMagics(Magics):
-n <number>
Open the editor at a specified line number. By default, the yap_ipython
editor hook uses the unix syntax 'editor +N filename', but you can
editor hook uses the unix syntax//i 'editor +N filename', but you can
configure this by providing your own modified hook if your favorite
editor supports line-number specifications with a different syntax.