Merge 192.168.1.79:github/yap-6.3
This commit is contained in:
109
packages/python/yap_kernel/yap_ipython/core/backcall.py
Normal file
109
packages/python/yap_kernel/yap_ipython/core/backcall.py
Normal file
@@ -0,0 +1,109 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Mon Jan 13 18:17:15 2014
|
||||
|
||||
@author: takluyver
|
||||
"""
|
||||
import sys
|
||||
PY3 = (sys.version_info[0] >= 3)
|
||||
|
||||
try:
|
||||
from inspect import signature, Parameter # Python >= 3.3
|
||||
except ImportError:
|
||||
from ._signatures import signature, Parameter
|
||||
|
||||
if PY3:
|
||||
from functools import wraps
|
||||
else:
|
||||
from functools import wraps as _wraps
|
||||
def wraps(f):
|
||||
def dec(func):
|
||||
_wraps(f)(func)
|
||||
func.__wrapped__ = f
|
||||
return func
|
||||
|
||||
return dec
|
||||
|
||||
def callback_prototype(prototype):
|
||||
"""Decorator to process a callback prototype.
|
||||
|
||||
A callback prototype is a function whose signature includes all the values
|
||||
that will be passed by the callback API in question.
|
||||
|
||||
The original function will be returned, with a ``prototype.adapt`` attribute
|
||||
which can be used to prepare third party callbacks.
|
||||
"""
|
||||
protosig = signature(prototype)
|
||||
positional, keyword = [], []
|
||||
for name, param in protosig.parameters.items():
|
||||
if param.kind in (Parameter.VAR_POSITIONAL, Parameter.VAR_KEYWORD):
|
||||
raise TypeError("*args/**kwargs not supported in prototypes")
|
||||
|
||||
if (param.default is not Parameter.empty) \
|
||||
or (param.kind == Parameter.KEYWORD_ONLY):
|
||||
keyword.append(name)
|
||||
else:
|
||||
positional.append(name)
|
||||
|
||||
kwargs = dict.fromkeys(keyword)
|
||||
def adapt(callback):
|
||||
"""Introspect and prepare a third party callback."""
|
||||
sig = signature(callback)
|
||||
try:
|
||||
# XXX: callback can have extra optional parameters - OK?
|
||||
sig.bind(*positional, **kwargs)
|
||||
return callback
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
# Match up arguments
|
||||
unmatched_pos = positional[:]
|
||||
unmatched_kw = kwargs.copy()
|
||||
unrecognised = []
|
||||
# TODO: unrecognised parameters with default values - OK?
|
||||
for name, param in sig.parameters.items():
|
||||
# print(name, param.kind) #DBG
|
||||
if param.kind == Parameter.POSITIONAL_ONLY:
|
||||
if len(unmatched_pos) > 0:
|
||||
unmatched_pos.pop(0)
|
||||
else:
|
||||
unrecognised.append(name)
|
||||
elif param.kind == Parameter.POSITIONAL_OR_KEYWORD:
|
||||
if (param.default is not Parameter.empty) and (name in unmatched_kw):
|
||||
unmatched_kw.pop(name)
|
||||
elif len(unmatched_pos) > 0:
|
||||
unmatched_pos.pop(0)
|
||||
else:
|
||||
unrecognised.append(name)
|
||||
elif param.kind == Parameter.VAR_POSITIONAL:
|
||||
unmatched_pos = []
|
||||
elif param.kind == Parameter.KEYWORD_ONLY:
|
||||
if name in unmatched_kw:
|
||||
unmatched_kw.pop(name)
|
||||
else:
|
||||
unrecognised.append(name)
|
||||
else: # VAR_KEYWORD
|
||||
unmatched_kw = {}
|
||||
|
||||
# print(unmatched_pos, unmatched_kw, unrecognised) #DBG
|
||||
|
||||
if unrecognised:
|
||||
raise TypeError("Function {!r} had unmatched arguments: {}".format(callback, unrecognised))
|
||||
|
||||
n_positional = len(positional) - len(unmatched_pos)
|
||||
|
||||
@wraps(callback)
|
||||
def adapted(*args, **kwargs):
|
||||
"""Wrapper for third party callbacks that discards excess arguments"""
|
||||
# print(args, kwargs)
|
||||
args = args[:n_positional]
|
||||
for name in unmatched_kw:
|
||||
# XXX: Could name not be in kwargs?
|
||||
kwargs.pop(name)
|
||||
# print(args, kwargs, unmatched_pos, cut_positional, unmatched_kw)
|
||||
return callback(*args, **kwargs)
|
||||
|
||||
return adapted
|
||||
|
||||
prototype.adapt = adapt
|
||||
return prototype
|
@@ -13,7 +13,7 @@ events and the arguments which will be passed to them.
|
||||
This API is experimental in yap_ipython 2.0, and may be revised in future versions.
|
||||
"""
|
||||
|
||||
from backcall import callback_prototype
|
||||
from yap_ipython.core.backcall import callback_prototype
|
||||
|
||||
|
||||
class EventManager(object):
|
||||
|
@@ -1,4 +1,4 @@
|
||||
from backcall import callback_prototype
|
||||
from yap_ipython.core.backcall import callback_prototype
|
||||
import unittest
|
||||
from unittest.mock import Mock
|
||||
import nose.tools as nt
|
||||
|
258
packages/python/yap_kernel/yap_ipython/prolog/#jupyter.yap#
Normal file
258
packages/python/yap_kernel/yap_ipython/prolog/#jupyter.yap#
Normal file
@@ -0,0 +1,258 @@
|
||||
|
||||
/**
|
||||
* @file jupyter.yap
|
||||
*
|
||||
* @brief allow interaction between Jupyter and YAP.
|
||||
*
|
||||
* @long The code in here:
|
||||
* - establishes communication between Prolog and Python Streams
|
||||
* - inputs Prolog code and queries
|
||||
* - supports completion of Prolog programs.
|
||||
* -
|
||||
*/
|
||||
|
||||
%% :- module( jupyter,
|
||||
%% [jupyter_query/3,
|
||||
%% errors/2,
|
||||
%% ready/2,
|
||||
%% completion/2,
|
||||
|
||||
%% ]
|
||||
%% ).
|
||||
|
||||
|
||||
:- reexport(library(yapi)).
|
||||
:- use_module(library(lists)).
|
||||
:- use_module(library(maplist)).
|
||||
:- use_module(library(python)).
|
||||
|
||||
:- python_import(sys).
|
||||
|
||||
jupyter_query(Self, Cell, Line ) :-
|
||||
setup_call_cleanup(
|
||||
enter_cell(Self),
|
||||
jupyter_cell(Self, Cell, Line),
|
||||
exit_cell(Self)
|
||||
).
|
||||
|
||||
jupyter_cell(_Self, Cell, _) :-
|
||||
jupyter_consult(Cell),
|
||||
fail.
|
||||
jupyter_cell( _Self, _, Line ) :-
|
||||
blank( Line ),
|
||||
!.
|
||||
jupyter_cell( _Self, _, [] ) :- !.
|
||||
jupyter_cell( Self, _, Line ) :-
|
||||
python_query( Self, Line ).
|
||||
|
||||
jupyter_consult(Text) :-
|
||||
blank( Text ),
|
||||
!.
|
||||
jupyter_consult(Cell) :-
|
||||
open_mem_read_stream( Cell, Stream),
|
||||
load_files(user:'jupyter cell',[stream(Stream)]).
|
||||
%should load_files close?
|
||||
|
||||
blank(Text) :-
|
||||
atom_codes(Text, L),
|
||||
maplist( blankc, L).
|
||||
|
||||
blankc(' ').
|
||||
blankc('\n').
|
||||
blankc('\t').
|
||||
|
||||
enter_cell(_Self) :-
|
||||
%open('//python/input', read, _Input, []),
|
||||
open('//python/sys.stdout', append, _Output, []),
|
||||
open('//python/sys.stdout', append, _Error, []),
|
||||
%set_prolog_flag(user_input, _Input),
|
||||
set_prolog_flag(user_output, _Output),
|
||||
set_prolog_flag(user_error, _Error).
|
||||
|
||||
exit_cell(_Self) :-
|
||||
%close( user_input),
|
||||
close( user_output),
|
||||
close( user_error).
|
||||
|
||||
|
||||
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.matches := Cs.
|
||||
|
||||
|
||||
strip_final_tokens(['EOT'|Ts], Ts) :- !.
|
||||
strip_final_tokens( Ts, Ts ).
|
||||
|
||||
complete([E,l,C,l,A|More],
|
||||
isconsult(A),
|
||||
%B = l,
|
||||
library(C,Lib),
|
||||
%D=l,
|
||||
E=atom(Prefix),
|
||||
\+ arg( Rest ),
|
||||
check_library( Prefix, Lib, C).
|
||||
complete([E,l,C,l,-,'['|More],
|
||||
isconsult(A),
|
||||
%B = l,
|
||||
library(C,Lib),
|
||||
%D=l,
|
||||
E=atom(Prefix),
|
||||
\+ arg( Rest ),
|
||||
check_library( Prefix, Lib, C).
|
||||
complete([C,l,A|More],
|
||||
isconsult(A),
|
||||
%B = l,
|
||||
C=atom(Prefix),
|
||||
\+ arg( Rest ),
|
||||
file_or_library( Prefix, C).
|
||||
complete([C,l,-,'['|More],
|
||||
isconsult(A),
|
||||
%B = l,
|
||||
C=atom(Prefix),
|
||||
\+ arg( Rest ),
|
||||
file_or_library( Prefix, C).
|
||||
complete( [atom(F)|Rest], C) :-
|
||||
\+ arg( Rest ),
|
||||
predicate( F, Pred, Arity ),
|
||||
cont( Arity, F, Pred, C).
|
||||
|
||||
isconsult( atom(use_module) ).
|
||||
isconsult( atom(ensure_loaded) ).
|
||||
isconsult( atom(compile) ).
|
||||
isconsult( atom(consult) ).
|
||||
isconsult( atom(reconsult) ).
|
||||
isconsult( atom(load_files) ).
|
||||
isconsult( '[' ).
|
||||
|
||||
arg([']'|_]).
|
||||
arg([l|_]).
|
||||
|
||||
file_or_library(F,C) :-
|
||||
libsym(C0),
|
||||
atom_cooncat(F,C,C0).
|
||||
file_or_library(F,C) :-
|
||||
check_file(F,C).
|
||||
|
||||
check_file(F0,C) :-
|
||||
atom_concat('\'',F,F0),
|
||||
!,
|
||||
absolute_file_name( F, FF, [access(none)] ),
|
||||
atom_concat( FF, '*' , Pat),
|
||||
absolute_file_name( Pat, C0, [glob(true)] ),
|
||||
atom_concat(Pat,C00,C0),
|
||||
atom_conct(C00,'\'',C).
|
||||
check_file(F0,C) :-
|
||||
atom_concat( F0, '*' , Pat),
|
||||
absolute_file_name( Pat, C0, [glob(true)] ),
|
||||
atom_concat(Pat,C,C0).
|
||||
|
||||
check_library( Lib, F, C) :-
|
||||
atom_concat( F, '*' , Pat),
|
||||
LibF =.. [Lib(Pat)],
|
||||
absolute_file_name( LibF, Lib, [glob(true)] ),
|
||||
file_directory_name( Lib, Name),
|
||||
( atom_concat(C, '.yap', Name) -> true ;
|
||||
atom_concat(C, '.ypp', Name) -> true ;
|
||||
atom_concat(C, '.prolog', Name) -> true
|
||||
).
|
||||
|
||||
predicate(N,P,A) :-
|
||||
system_predicate(P0/A),
|
||||
atom_concat(N,P,P0).
|
||||
predicate(N,P,A) :-
|
||||
current_predicate(P0/A),
|
||||
atom_concat(N,P,P0).
|
||||
|
||||
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(_,_).
|
||||
|
||||
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( _ ).
|
161
packages/python/yap_kernel/yap_ipython/terminal/#ptutils.py#
Normal file
161
packages/python/yap_kernel/yap_ipython/terminal/#ptutils.py#
Normal file
@@ -0,0 +1,161 @@
|
||||
"""prompt-toolkit utilities
|
||||
|
||||
Everything in this module is a private API,
|
||||
not to be used outside yap_ipython.
|
||||
"""
|
||||
|
||||
# Copyright (c) yap_ipython Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
|
||||
import unicodedata
|
||||
from wcwidth import wcwidth
|
||||
|
||||
from yap_ipython.core.completer import (
|
||||
provisionalcompleter, cursor_to_position,
|
||||
_deduplicate_completions)
|
||||
from prompt_toolkit.completion import Completer, Completion
|
||||
from prompt_toolkit.layout.lexers import Lexer
|
||||
from prompt_toolkit.layout.lexers import PygmentsLexer
|
||||
|
||||
import pygments.lexers as pygments_lexers
|
||||
|
||||
_completion_sentinel = object()
|
||||
|
||||
def _elide(string, *, min_elide=30):
|
||||
"""
|
||||
If a string is long enough, and has at least 2 dots,
|
||||
replace the middle part with ellipses.
|
||||
|
||||
If three consecutive dots, or two consecutive dots are encountered these are
|
||||
replaced by the equivalents HORIZONTAL ELLIPSIS or TWO DOT LEADER unicode
|
||||
equivalents
|
||||
"""
|
||||
string = string.replace('...','\N{HORIZONTAL ELLIPSIS}')
|
||||
string = string.replace('..','\N{TWO DOT LEADER}')
|
||||
if len(string) < min_elide:
|
||||
return string
|
||||
|
||||
parts = string.split('.')
|
||||
|
||||
if len(parts) <= 3:
|
||||
return string
|
||||
|
||||
return '{}.{}\N{HORIZONTAL ELLIPSIS}{}.{}'.format(parts[0], parts[1][0], parts[-2][-1], parts[-1])
|
||||
|
||||
|
||||
def _adjust_completion_text_based_on_context(text, body, offset):
|
||||
if text.endswith('=') and len(body) > offset and body[offset] is '=':
|
||||
return text[:-1]
|
||||
else:
|
||||
return text
|
||||
|
||||
|
||||
class IPythonPTCompleter(Completer):
|
||||
"""Adaptor to provide yap_ipython completions to prompt_toolkit"""
|
||||
def __init__(self, ipy_completer=None, shell=None, patch_stdout=None):
|
||||
if shell is None and ipy_completer is None:
|
||||
raise TypeError("Please pass shell=an InteractiveShell instance.")
|
||||
self._ipy_completer = ipy_completer
|
||||
self.shell = shell
|
||||
if patch_stdout is None:
|
||||
raise TypeError("Please pass patch_stdout")
|
||||
self.patch_stdout = patch_stdout
|
||||
|
||||
@property
|
||||
def ipy_completer(self):
|
||||
if self._ipy_completer:
|
||||
return self._ipy_completer
|
||||
else:
|
||||
return self.shell.Completer
|
||||
|
||||
def get_completions(self, document, complete_event):
|
||||
if not document.current_line.strip():
|
||||
return
|
||||
# Some bits of our completion system may print stuff (e.g. if a module
|
||||
# is imported). This context manager ensures that doesn't interfere with
|
||||
# the prompt.
|
||||
|
||||
with self.patch_stdout(), provisionalcompleter():
|
||||
body = document.text
|
||||
cursor_row = document.cursor_position_row
|
||||
cursor_col = document.cursor_position_col
|
||||
cursor_position = document.cursor_position
|
||||
offset = cursor_to_position(body, cursor_row, cursor_col)
|
||||
yield from self._get_completions(body, offset, cursor_position, self.ipy_completer)
|
||||
|
||||
@staticmethod
|
||||
def _get_completions(body, offset, cursor_position, ipyc):
|
||||
"""
|
||||
Private equivalent of get_completions() use only for unit_testing.
|
||||
"""
|
||||
debug = getattr(ipyc, 'debug', False)
|
||||
completions = _deduplicate_completions(
|
||||
body, ipyc.completions(body, offset))
|
||||
for c in completions:
|
||||
if not c.text:
|
||||
# Guard against completion machinery giving us an empty string.
|
||||
continue
|
||||
text = unicodedata.normalize('NFC', c.text)
|
||||
# When the first character of the completion has a zero length,
|
||||
# then it's probably a decomposed unicode character. E.g. caused by
|
||||
# the "\dot" completion. Try to compose again with the previous
|
||||
# character.
|
||||
if wcwidth(text[0]) == 0:
|
||||
if cursor_position + c.start > 0:
|
||||
char_before = body[c.start - 1]
|
||||
fixed_text = unicodedata.normalize(
|
||||
'NFC', char_before + text)
|
||||
|
||||
# Yield the modified completion instead, if this worked.
|
||||
if wcwidth(text[0:1]) == 1:
|
||||
yield Completion(fixed_text, start_position=c.start - offset - 1)
|
||||
continue
|
||||
|
||||
# TODO: Use Jedi to determine meta_text
|
||||
# (Jedi currently has a bug that results in incorrect information.)
|
||||
# meta_text = ''
|
||||
# yield Completion(m, start_position=start_pos,
|
||||
# display_meta=meta_text)
|
||||
display_text = c.text
|
||||
|
||||
adjusted_text = _adjust_completion_text_based_on_context(c.text, body, offset)
|
||||
if c.type == 'function':
|
||||
yield Completion(adjusted_text, start_position=c.start - offset, display=_elide(display_text+'()'), display_meta=c.type+c.signature)
|
||||
else:
|
||||
yield Completion(adjusted_text, start_position=c.start - offset, display=_elide(display_text), display_meta=c.type)
|
||||
|
||||
class IPythonPTLexer(Lexer):
|
||||
"""
|
||||
Wrapper around PythonLexer and BashLexer.
|
||||
"""
|
||||
def __init__(self):
|
||||
l = pygments_lexers
|
||||
self.python_lexer = PygmentsLexer(l.Python3Lexer)
|
||||
self.shell_lexer = PygmentsLexer(l.BashLexer)
|
||||
|
||||
self.magic_lexers = {
|
||||
'HTML': PygmentsLexer(l.HtmlLexer),
|
||||
'html': PygmentsLexer(l.HtmlLexer),
|
||||
'javascript': PygmentsLexer(l.JavascriptLexer),
|
||||
'js': PygmentsLexer(l.JavascriptLexer),
|
||||
'perl': PygmentsLexer(l.PerlLexer),
|
||||
'ruby': PygmentsLexer(l.RubyLexer),
|
||||
'latex': PygmentsLexer(l.TexLexer),
|
||||
'prolog': PygmentsLexer(l.PrologLexer),
|
||||
}
|
||||
|
||||
def lex_document(self, cli, document):
|
||||
text = document.text.lstrip()
|
||||
|
||||
lexer = self.python_lexer
|
||||
|
||||
if text.startswith('!') or text.startswith('%%bash'):
|
||||
lexer = self.shell_lexer
|
||||
|
||||
elif text.startswith('%%'):
|
||||
for magic, l in self.magic_lexers.items():
|
||||
if text.startswith('%%' + magic):
|
||||
lexer = l
|
||||
break
|
||||
|
||||
return lexer.lex_document(cli, document)
|
@@ -562,7 +562,7 @@ class YAPRun:
|
||||
self.os = None
|
||||
sys.stderr.writeln('Done, with', self.bindings)
|
||||
return True,self.bindings
|
||||
if self.bindings:
|
||||
if found:
|
||||
sys.stderr.write('Done, with', self.bindings, '\n')
|
||||
else:
|
||||
self.query.close()
|
||||
@@ -571,8 +571,9 @@ class YAPRun:
|
||||
sys.stderr.write('Fail\n')
|
||||
return True,{}
|
||||
except Exception as e:
|
||||
sys.stderr.write('Exception after', self.bindings, '\n')
|
||||
has_raised = True
|
||||
self.result.result = False
|
||||
return False,{}
|
||||
|
||||
|
||||
def _yrun_cell(self, raw_cell, store_history=True, silent=False,
|
||||
|
Reference in New Issue
Block a user