new jupiter intrface
This commit is contained in:
parent
54234c7e1d
commit
3e6c24cc0c
0
packages/__init__.py
Normal file
0
packages/__init__.py
Normal file
150
packages/packages/python/pl2pl.c
Normal file
150
packages/packages/python/pl2pl.c
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
|
||||||
|
#include "py4yap.h"
|
||||||
|
|
||||||
|
static foreign_t array_to_python_list(term_t addr, term_t type, term_t szt,
|
||||||
|
term_t py) {
|
||||||
|
void *src;
|
||||||
|
Py_ssize_t sz, i;
|
||||||
|
int is_float;
|
||||||
|
|
||||||
|
if (!PL_get_pointer(addr, &src) || !PL_get_bool(type, &is_float) ||
|
||||||
|
!PL_get_intptr(szt, &sz))
|
||||||
|
return false;
|
||||||
|
PyObject *list = PyList_New(sz);
|
||||||
|
if (!list)
|
||||||
|
return false;
|
||||||
|
if (is_float) {
|
||||||
|
double *v = (double *)src;
|
||||||
|
for (i = 0; i < sz; i++) {
|
||||||
|
PyObject *x = PyFloat_FromDouble(v[i]);
|
||||||
|
PyList_SET_ITEM(list, i, x);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
YAP_Int *v = (YAP_Int *)src;
|
||||||
|
for (i = 0; i < sz; i++) {
|
||||||
|
PyObject *x = PyFloat_FromDouble(v[i]);
|
||||||
|
PyList_SET_ITEM(list, i, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (PL_is_variable(py)) {
|
||||||
|
return address_to_term(list, py);
|
||||||
|
}
|
||||||
|
return assign_to_symbol(py, list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static foreign_t array_to_python_tuple(term_t addr, term_t type, term_t szt,
|
||||||
|
term_t py) {
|
||||||
|
void *src;
|
||||||
|
Py_ssize_t sz, i;
|
||||||
|
int is_float;
|
||||||
|
|
||||||
|
if (!PL_get_pointer(addr, &src) || !PL_get_bool(type, &is_float) ||
|
||||||
|
!PL_get_intptr(szt, &sz))
|
||||||
|
return false;
|
||||||
|
PyObject *list = PyTuple_New(sz);
|
||||||
|
if (!list)
|
||||||
|
return false;
|
||||||
|
if (is_float) {
|
||||||
|
double *v = (double *)src;
|
||||||
|
|
||||||
|
for (i = 0; i < sz; i++) {
|
||||||
|
PyObject *x;
|
||||||
|
x = PyFloat_FromDouble(v[i]);
|
||||||
|
if (PyTuple_SetItem(list, i, x)) {
|
||||||
|
PyErr_Print();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int32_t *v = (int32_t *)src;
|
||||||
|
PyObject *x;
|
||||||
|
for (i = 0; i < sz; i++) {
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
x = PyInt_FromLong(v[i]);
|
||||||
|
#else
|
||||||
|
x = PyLong_FromLong(v[i]);
|
||||||
|
#endif
|
||||||
|
if (PyTuple_SetItem(list, i, x)) {
|
||||||
|
PyErr_Print();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (PL_is_variable(py)) {
|
||||||
|
return address_to_term(list, py);
|
||||||
|
}
|
||||||
|
return assign_to_symbol(py, list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static foreign_t array_to_python_view(term_t addr, term_t type, term_t szt,
|
||||||
|
term_t colt, term_t py) {
|
||||||
|
void *src;
|
||||||
|
Py_ssize_t sz, rows;
|
||||||
|
int is_float;
|
||||||
|
Py_ssize_t shape[2];
|
||||||
|
|
||||||
|
if (!PL_get_pointer(addr, &src) || !PL_get_bool(type, &is_float) ||
|
||||||
|
!PL_get_intptr(szt, &sz) || !PL_get_intptr(colt, &rows))
|
||||||
|
return false;
|
||||||
|
Py_buffer buf;
|
||||||
|
buf.buf = src;
|
||||||
|
if (is_float) {
|
||||||
|
buf.len = sz * sizeof(double);
|
||||||
|
buf.itemsize = sizeof(double);
|
||||||
|
} else {
|
||||||
|
buf.len = sz * sizeof(YAP_Int);
|
||||||
|
buf.itemsize = sizeof(YAP_Int);
|
||||||
|
}
|
||||||
|
buf.readonly = false;
|
||||||
|
buf.format = NULL;
|
||||||
|
buf.ndim = 2;
|
||||||
|
buf.shape = shape;
|
||||||
|
buf.strides = NULL;
|
||||||
|
buf.suboffsets = NULL;
|
||||||
|
PyObject *o = PyMemoryView_FromBuffer(&buf);
|
||||||
|
if (!o) {
|
||||||
|
PyErr_Print();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (PL_is_variable(py)) {
|
||||||
|
return address_to_term(o, py);
|
||||||
|
}
|
||||||
|
return assign_to_symbol(py, o);
|
||||||
|
}
|
||||||
|
|
||||||
|
static foreign_t prolog_list_to_python_list(term_t plist, term_t pyt, term_t tlen) {
|
||||||
|
size_t sz, i;
|
||||||
|
PyErr_Clear();
|
||||||
|
PyObject *pyl = term_to_python(pyt, true, NULL);
|
||||||
|
term_t targ = PL_new_term_ref();
|
||||||
|
|
||||||
|
if (PL_skip_list(plist, targ, &sz) <0 || ! PL_get_nil(targ)) {
|
||||||
|
pyErrorAndReturn( false, false);
|
||||||
|
}
|
||||||
|
if (!PyList_Check(pyl))
|
||||||
|
{
|
||||||
|
pyErrorAndReturn( false, false);
|
||||||
|
}
|
||||||
|
if (sz > PyList_GET_SIZE(pyl))
|
||||||
|
pyErrorAndReturn( false, false);
|
||||||
|
for (i=0; i < sz; i++) {
|
||||||
|
if (!PL_get_list(plist, targ, plist)) {
|
||||||
|
pyErrorAndReturn( false, false);
|
||||||
|
}
|
||||||
|
PyObject *t = term_to_python(targ, true, NULL);
|
||||||
|
PyList_SET_ITEM(pyl, i, t);
|
||||||
|
}
|
||||||
|
if (PL_is_variable(tlen)) {
|
||||||
|
PL_unify_int64(tlen, sz);
|
||||||
|
} else {
|
||||||
|
python_assign(tlen, PyLong_FromUnsignedLong(sz), NULL);
|
||||||
|
}
|
||||||
|
pyErrorAndReturn( true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
install_t install_pl2pl(void) {
|
||||||
|
PL_register_foreign("array_to_python_list", 4, array_to_python_list, 0);
|
||||||
|
PL_register_foreign("array_to_python_tuple", 4, array_to_python_tuple, 0);
|
||||||
|
PL_register_foreign("array_to_python_view", 5, array_to_python_view, 0);
|
||||||
|
PL_register_foreign("prolog_list_to_python_list", 3, prolog_list_to_python_list, 0);
|
||||||
|
}
|
214
packages/packages/python/pl2py.c
Normal file
214
packages/packages/python/pl2py.c
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
|
||||||
|
|
||||||
|
#include "py4yap.h"
|
||||||
|
|
||||||
|
extern PyObject *py_Local, *py_Global;
|
||||||
|
|
||||||
|
PyObject *YE(term_t t, int line, const char *file, const char *code) {
|
||||||
|
YAPPy_ThrowError__(file, code, line, SYSTEM_ERROR_INTERNAL,t,"");
|
||||||
|
}
|
||||||
|
|
||||||
|
void YEM(const char *exp, int line, const char *file, const char *code) {
|
||||||
|
fprintf(stderr, "**** Warning,%s@%s:%d: failed while executing %s\n", code,
|
||||||
|
file, line, exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *s_to_python(const char *s, bool eval, PyObject *p0) {
|
||||||
|
PyObject *o;
|
||||||
|
if (eval) {
|
||||||
|
o = PythonLookup(s, p0);
|
||||||
|
/* if (!o)
|
||||||
|
return o;
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
o = PythonLookupSpecial(s);
|
||||||
|
}
|
||||||
|
if (o) {
|
||||||
|
Py_INCREF(o);
|
||||||
|
return CHECKNULL(YAP_MkStringTerm(s), o);
|
||||||
|
} else {
|
||||||
|
PyObject *pobj = PyUnicode_DecodeUTF8(s, strlen(s), NULL);
|
||||||
|
return pobj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* obtain the object matching a certain string.
|
||||||
|
*
|
||||||
|
* @param t handle to Prolog term
|
||||||
|
* @param t whether should try to evaluate evaluables.
|
||||||
|
*
|
||||||
|
* @return a Python object descriptor or NULL if failed
|
||||||
|
*/
|
||||||
|
X_API PyObject *string_to_python(const char *s, bool eval, PyObject *p0) {
|
||||||
|
char *buf = malloc(strlen(s) + 1), *child;
|
||||||
|
PyObject *p1;
|
||||||
|
while ((child = strchr(s, '.')) != NULL) {
|
||||||
|
size_t len = child - s;
|
||||||
|
strncpy(buf, s, len);
|
||||||
|
buf[len] = '\0';
|
||||||
|
p1 = s_to_python(buf, eval, p0);
|
||||||
|
Py_DecRef(p0);
|
||||||
|
Py_IncRef(p1)
|
||||||
|
s = child + 1;
|
||||||
|
p0 = p1;
|
||||||
|
}
|
||||||
|
p1 = s_to_python(s, eval, p0);
|
||||||
|
Py_DecRef(p0);
|
||||||
|
return p1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* term_to_python translates and evaluates from Prolog to Python
|
||||||
|
*
|
||||||
|
* @param t handle to Prolog term
|
||||||
|
* @param t whether should try to evaluate evaluables.
|
||||||
|
*
|
||||||
|
* @return a Python object descriptor or NULL if failed
|
||||||
|
*/
|
||||||
|
PyObject *term_to_python(term_t t, bool eval, PyObject *o) {
|
||||||
|
// o≈
|
||||||
|
PyObject *o;\
|
||||||
|
YAP_Term yt = YAP_GetFromSlot(t);
|
||||||
|
// Yap_DebugPlWriteln(yt);
|
||||||
|
switch (PL_term_type(t)) {
|
||||||
|
case PL_VARIABLE: {
|
||||||
|
if (t == 0) {
|
||||||
|
YAPPy_ThrowErrorYA(SYSTEM_ERROR_INTERNAL,t,"");
|
||||||
|
t }
|
||||||
|
PyObject *out = PyTuple_New(1);
|
||||||
|
PyTuple_SET_ITEM(out, 0, PyLong_FromLong(t));
|
||||||
|
Py_IncRef(out);
|
||||||
|
rc = term_to_nametuple("v", 1, out);
|
||||||
|
Py_IncRef(rc);
|
||||||
|
};
|
||||||
|
case PL_ATOM: {
|
||||||
|
YAP_Atom at = YAP_AtomOfTerm(yt);
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
s = YAP_AtomName(at);
|
||||||
|
if (eval) {
|
||||||
|
o = PythonLookup(s, o);
|
||||||
|
/* if (!o)
|
||||||
|
return o;
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
o = PythonLookupSpecial(s);
|
||||||
|
}
|
||||||
|
if (o) {
|
||||||
|
Py_INCREF(o);
|
||||||
|
return CHECKNULL(t, o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case PL_STRING: {
|
||||||
|
const char *s = NULL;
|
||||||
|
if (YAP_IsAtomTerm(yt)) {
|
||||||
|
s = YAP_AtomName(YAP_AtomOfTerm(yt));
|
||||||
|
} else if (YAP_IsStringTerm(yt)) {
|
||||||
|
s = YAP_StringOfTerm(yt);
|
||||||
|
} else {
|
||||||
|
return CHECKNULL(t, NULL);
|
||||||
|
}
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
if (proper_ascii_string(s)) {
|
||||||
|
PyObject *o = PyString_FromStringAndSize(s, strlen(s));
|
||||||
|
Py_IncRef(o)
|
||||||
|
return CHECKNULL(t, o);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
// char *p = malloc(strlen(s)+1);
|
||||||
|
//strcpy(p, s);
|
||||||
|
PyObject *pobj = PyUnicode_FromString(s);
|
||||||
|
Py_IncRef(pobj);
|
||||||
|
return CHECKNULL(t, pobj);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case PL_INTEGER: {
|
||||||
|
int64_t j;
|
||||||
|
if (!PL_get_int64_ex(t, &j))
|
||||||
|
return CHECKNULL(t, NULL);
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
PyObject *o = PyInt_FromLong(j);
|
||||||
|
return CHECKNULL(t, o);
|
||||||
|
#else
|
||||||
|
PyObject *o = PyLong_FromLong(j);
|
||||||
|
return CHECKNULL(t, o);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
case PL_FLOAT: {
|
||||||
|
PyObject *out;
|
||||||
|
double fl;
|
||||||
|
if (!PL_get_float(t, &fl))
|
||||||
|
return CHECKNULL(t, NULL);
|
||||||
|
out = PyFloat_FromDouble(fl);
|
||||||
|
return CHECKNULL(t, out);
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
term_t tail = PL_new_term_ref(), arg;
|
||||||
|
size_t len, i;
|
||||||
|
if (PL_skip_list(t, tail, &len) && PL_get_nil(tail)) {
|
||||||
|
PyObject *out, *a;
|
||||||
|
|
||||||
|
arg = tail;
|
||||||
|
out = PyList_New(len);
|
||||||
|
if (!out) {
|
||||||
|
PL_reset_term_refs(tail);
|
||||||
|
return CHECKNULL(t, Py_None);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (!PL_get_list(t, arg, t)) {
|
||||||
|
YAPPy_ThrowErrorYA(SYSTEM_ERROR_INTERNAL,t,"");
|
||||||
|
}
|
||||||
|
a = term_to_python(arg, eval, o);
|
||||||
|
if (a) {
|
||||||
|
if (PyList_SetItem(out, i, a) < 0) {
|
||||||
|
YAPPy_ThrowErrorYA(SYSTEM_ERROR_INTERNAL,t,"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PL_reset_term_refs(tail);
|
||||||
|
return CHECKNULL(t, out);
|
||||||
|
} else {
|
||||||
|
functor_t fun;
|
||||||
|
PyObject *rc;
|
||||||
|
|
||||||
|
if (!PL_get_functor(t, &fun)) {
|
||||||
|
PL_reset_term_refs(tail);
|
||||||
|
return CHECKNULL(t, Py_None);
|
||||||
|
}
|
||||||
|
if (eval)
|
||||||
|
rc = compound_to_pyeval(t, o);
|
||||||
|
else
|
||||||
|
rc = compound_to_pytree(t, o);
|
||||||
|
PL_reset_term_refs(tail);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CHECKNULL(t, Py_None);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *yap_to_python(YAP_Term t, bool eval, PyObject *o) {
|
||||||
|
if (t == 0)
|
||||||
|
return NULL;
|
||||||
|
term_t yt = YAP_InitSlot(t);
|
||||||
|
o = term_to_python(yt, eval, o);
|
||||||
|
PL_reset_term_refs(yt);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *deref_term_to_python(term_t t) {
|
||||||
|
// Yap_DebugPlWrite(YAP_GetFromSlot(t)); fprintf(stderr, " here I
|
||||||
|
// am\n");
|
||||||
|
YAP_Term yt = YAP_GetFromSlot(t);
|
||||||
|
if (YAP_IsVarTerm(yt)) {
|
||||||
|
char s[32];
|
||||||
|
char *o = YAP_WriteBuffer(yt, s, 31, 0);
|
||||||
|
PyObject *p = PyUnicode_FromString(o);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
return term_to_python(t, false, NULL);
|
||||||
|
}
|
319
packages/packages/python/py2pl.c
Normal file
319
packages/packages/python/py2pl.c
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
|
||||||
|
#include "py4yap.h"
|
||||||
|
|
||||||
|
static foreign_t repr_term(PyObject *pVal, term_t t) {
|
||||||
|
term_t to = PL_new_term_ref(), t1 = PL_new_term_ref();
|
||||||
|
PL_put_pointer(t1, pVal);
|
||||||
|
PL_cons_functor(to, FUNCTOR_pointer1, t1);
|
||||||
|
Py_INCREF(pVal);
|
||||||
|
return PL_unify(t, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreign_t assign_to_symbol(term_t t, PyObject *e);
|
||||||
|
|
||||||
|
foreign_t assign_to_symbol(term_t t, PyObject *e) {
|
||||||
|
char *s = NULL;
|
||||||
|
if (!PL_get_atom_chars(t, &s)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PyObject *dic;
|
||||||
|
if (!lookupPySymbol(s, NULL, &dic))
|
||||||
|
dic = py_Main;
|
||||||
|
return PyObject_SetAttrString(dic, s, e) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreign_t python_to_term(PyObject *pVal, term_t t) {
|
||||||
|
bool rc = true;
|
||||||
|
term_t to = PL_new_term_ref();
|
||||||
|
// fputs(" <<*** ",stderr); PyObject_Print(pVal,stderr,0);
|
||||||
|
// fputs("<<***\n",stderr);
|
||||||
|
if (pVal == Py_None) {
|
||||||
|
// fputs("<<*** ",stderr);Yap_DebugPlWrite(YAP_GetFromSlot(t)); fputs("
|
||||||
|
// >>***\n",stderr);
|
||||||
|
rc = PL_unify_atom(t, ATOM_none);
|
||||||
|
// fputs("<<*** ",stderr);Yap_DebugPlWrite(YAP_GetFromSlot(t)); fputs("
|
||||||
|
// >>***\n",stderr);
|
||||||
|
} else if (PyBool_Check(pVal)) {
|
||||||
|
rc = rc && PL_unify_bool(t, PyObject_IsTrue(pVal));
|
||||||
|
} else if (PyLong_Check(pVal)) {
|
||||||
|
rc = rc && PL_unify_int64(t, PyLong_AsLong(pVal));
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
} else if (PyInt_Check(pVal)) {
|
||||||
|
rc = rc && PL_unify_int64(t, PyInt_AsLong(pVal));
|
||||||
|
#endif
|
||||||
|
} else if (PyFloat_Check(pVal)) {
|
||||||
|
rc = rc && PL_unify_float(t, PyFloat_AsDouble(pVal));
|
||||||
|
} else if (PyComplex_Check(pVal)) {
|
||||||
|
term_t t1 = PL_new_term_ref(), t2 = PL_new_term_ref();
|
||||||
|
if (!PL_put_float(t1, PyComplex_RealAsDouble(pVal)) ||
|
||||||
|
!PL_put_float(t2, PyComplex_ImagAsDouble(pVal)) ||
|
||||||
|
!PL_cons_functor(to, FUNCTOR_complex2, t1, t2)) {
|
||||||
|
rc = false;
|
||||||
|
} else {
|
||||||
|
rc = rc && PL_unify(t, to);
|
||||||
|
}
|
||||||
|
} else if (PyUnicode_Check(pVal)) {
|
||||||
|
atom_t tmp_atom;
|
||||||
|
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
size_t sz = PyUnicode_GetSize(pVal) + 1;
|
||||||
|
wchar_t *ptr = malloc(sizeof(wchar_t) * sz);
|
||||||
|
sz = PyUnicode_AsWideChar((PyUnicodeObject *)pVal, ptr, sz - 1);
|
||||||
|
tmp_atom = PL_new_atom_wchars(sz, ptr);
|
||||||
|
free(ptr);
|
||||||
|
#else
|
||||||
|
const char *s = PyUnicode_AsUTF8(pVal);
|
||||||
|
tmp_atom = PL_new_atom(s);
|
||||||
|
#endif
|
||||||
|
rc = rc && PL_unify_atom(t, tmp_atom);
|
||||||
|
} else if (PyByteArray_Check(pVal)) {
|
||||||
|
atom_t tmp_atom = PL_new_atom(PyByteArray_AsString(pVal));
|
||||||
|
rc = rc && PL_unify_atom(t, tmp_atom);
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
} else if (PyString_Check(pVal)) {
|
||||||
|
atom_t tmp_atom = PL_new_atom(PyString_AsString(pVal));
|
||||||
|
rc = rc && PL_unify_atom(t, tmp_atom);
|
||||||
|
#endif
|
||||||
|
} else if (PyTuple_Check(pVal)) {
|
||||||
|
Py_ssize_t i, sz = PyTuple_Size(pVal);
|
||||||
|
functor_t f;
|
||||||
|
const char *s;
|
||||||
|
if (sz == 0) {
|
||||||
|
rc = rc && PL_unify_atom(t, ATOM_brackets);
|
||||||
|
} else {
|
||||||
|
if ((s = (Py_TYPE(pVal)->tp_name))) {
|
||||||
|
if (!strcmp(s, "H")) {
|
||||||
|
pVal = PyTuple_GetItem(pVal, 0);
|
||||||
|
if (pVal == NULL) {
|
||||||
|
pVal = Py_None;
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (s[0] == '$') {
|
||||||
|
char *ns = malloc(strlen(s) + 5);
|
||||||
|
strcpy(ns, "__");
|
||||||
|
strcat(ns, s + 1);
|
||||||
|
strcat(ns, "__");
|
||||||
|
f = PL_new_functor(PL_new_atom(ns), sz);
|
||||||
|
} else {
|
||||||
|
f = PL_new_functor(PL_new_atom(s), sz);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
f = PL_new_functor(ATOM_t, sz);
|
||||||
|
}
|
||||||
|
if (PL_unify_functor(t, f)) {
|
||||||
|
for (i = 0; i < sz; i++) {
|
||||||
|
if (!PL_get_arg(i + 1, t, to))
|
||||||
|
rc = false;
|
||||||
|
PyObject *p = PyTuple_GetItem(pVal, i);
|
||||||
|
if (p == NULL) {
|
||||||
|
PyErr_Clear();
|
||||||
|
p = Py_None;
|
||||||
|
}
|
||||||
|
rc = rc && python_to_term(p, to);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc = false;
|
||||||
|
}
|
||||||
|
// fputs(" ||*** ",stderr); Yap_DebugPlWrite(YAP_GetFromSlot(t)); fputs("
|
||||||
|
// ||***\n",stderr);
|
||||||
|
}
|
||||||
|
} else if (PyList_Check(pVal)) {
|
||||||
|
Py_ssize_t i, sz = PyList_GET_SIZE(pVal);
|
||||||
|
|
||||||
|
if (sz == 0) {
|
||||||
|
rc = rc && PL_unify_nil(t);
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < sz; i++) {
|
||||||
|
PyObject *obj;
|
||||||
|
if (!PL_unify_list(t, to, t)) {
|
||||||
|
rc = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((obj = PyList_GetItem(pVal, i)) == NULL) {
|
||||||
|
obj = Py_None;
|
||||||
|
}
|
||||||
|
rc = rc && python_to_term(obj, to);
|
||||||
|
}
|
||||||
|
rc = rc && PL_unify_nil(t);
|
||||||
|
}
|
||||||
|
// fputs("[***] ", stderr);
|
||||||
|
// Yap_DebugPlWrite(yt); fputs("[***]\n", stderr);
|
||||||
|
} else if (PyDict_Check(pVal)) {
|
||||||
|
Py_ssize_t pos = 0;
|
||||||
|
term_t to = PL_new_term_ref(), ti = to;
|
||||||
|
int left = PyDict_Size(pVal);
|
||||||
|
PyObject *key, *value;
|
||||||
|
|
||||||
|
if (left == 0) {
|
||||||
|
rc = rc && PL_unify_atom(t, ATOM_curly_brackets);
|
||||||
|
} else {
|
||||||
|
while (PyDict_Next(pVal, &pos, &key, &value)) {
|
||||||
|
term_t tkey = PL_new_term_ref(), tval = PL_new_term_ref(), tint,
|
||||||
|
tnew = PL_new_term_ref();
|
||||||
|
/* do something interesting with the values... */
|
||||||
|
if (!python_to_term(key, tkey)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!python_to_term(value, tval)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* reuse */
|
||||||
|
tint = tkey;
|
||||||
|
if (!PL_cons_functor(tint, FUNCTOR_colon2, tkey, tval)) {
|
||||||
|
rc = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (--left) {
|
||||||
|
if (!PL_cons_functor(tint, FUNCTOR_comma2, tint, tnew))
|
||||||
|
PL_reset_term_refs(tkey);
|
||||||
|
rc = false;
|
||||||
|
}
|
||||||
|
if (!PL_unify(ti, tint)) {
|
||||||
|
rc = false;
|
||||||
|
}
|
||||||
|
ti = tnew;
|
||||||
|
PL_reset_term_refs(tkey);
|
||||||
|
}
|
||||||
|
rc = rc && PL_unify(t, to);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc = rc && repr_term(pVal, t);
|
||||||
|
}
|
||||||
|
PL_reset_term_refs(to);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
X_API YAP_Term pythonToYAP(PyObject *pVal) {
|
||||||
|
term_t t = PL_new_term_ref();
|
||||||
|
if (pVal == NULL || !python_to_term(pVal, t)) {
|
||||||
|
PL_reset_term_refs(t);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
YAP_Term tt = YAP_GetFromSlot(t);
|
||||||
|
PL_reset_term_refs(t);
|
||||||
|
Py_DECREF(pVal);
|
||||||
|
return tt;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *py_Local, *py_Global;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* assigns the Python RHS to a Prolog term LHS, ie LHS = RHS
|
||||||
|
*
|
||||||
|
* @param root Python environment
|
||||||
|
* @param t left hand side, in Prolog, may be
|
||||||
|
* - a Prolog variable, exports the term to Prolog, A <- RHS
|
||||||
|
* - Python variable A, A <- RHS
|
||||||
|
* - Python variable $A, A <- RHS
|
||||||
|
* - Python string "A", A <- RHS
|
||||||
|
* - Python array range
|
||||||
|
* @param e the right-hand side
|
||||||
|
*
|
||||||
|
* @return -1 on failure.
|
||||||
|
*
|
||||||
|
* Note that this is an auxiliary routine to the Prolog
|
||||||
|
*python_assign.
|
||||||
|
*/
|
||||||
|
bool python_assign(term_t t, PyObject *exp, PyObject *context) {
|
||||||
|
context = find_obj(context, t, false);
|
||||||
|
// Yap_DebugPlWriteln(yt);
|
||||||
|
switch (PL_term_type(t)) {
|
||||||
|
case PL_VARIABLE: {
|
||||||
|
if (context == NULL) // prevent a.V= N*N[N-1]
|
||||||
|
return python_to_term(exp, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
case PL_ATOM: {
|
||||||
|
char *s = NULL;
|
||||||
|
PL_get_atom_chars(t, &s);
|
||||||
|
if (!context)
|
||||||
|
context = py_Main;
|
||||||
|
return PyObject_SetAttrString(context, s, exp) == 0;
|
||||||
|
}
|
||||||
|
case PL_STRING:
|
||||||
|
case PL_INTEGER:
|
||||||
|
case PL_FLOAT:
|
||||||
|
// domain or type erro?
|
||||||
|
return false;
|
||||||
|
default: {
|
||||||
|
term_t tail = PL_new_term_ref(), arg = PL_new_term_ref();
|
||||||
|
size_t len, i;
|
||||||
|
if (PL_skip_list(t, tail, &len) &&
|
||||||
|
PL_get_nil(tail)) { // true list
|
||||||
|
|
||||||
|
bool o = true;
|
||||||
|
if (PySequence_Check(exp) && PySequence_Length(exp) == len)
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
PyObject *p;
|
||||||
|
if (!PL_get_list(t, arg, t)) {
|
||||||
|
PL_reset_term_refs(tail);
|
||||||
|
o = false;
|
||||||
|
p = Py_None;
|
||||||
|
}
|
||||||
|
if ((p = PySequence_GetItem(exp, i)) == NULL)
|
||||||
|
p = Py_None;
|
||||||
|
if (!python_assign(arg, p, context)) {
|
||||||
|
PL_reset_term_refs(tail);
|
||||||
|
o = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PL_reset_term_refs(tail);
|
||||||
|
return o;
|
||||||
|
} else {
|
||||||
|
functor_t fun;
|
||||||
|
|
||||||
|
if (!PL_get_functor(t, &fun)) {
|
||||||
|
PL_reset_term_refs(tail);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fun == FUNCTOR_sqbrackets2) {
|
||||||
|
if (!PL_get_arg(2, t, tail)) {
|
||||||
|
PL_reset_term_refs(tail);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *o = term_to_python(tail, true, context);
|
||||||
|
if (!PL_get_arg(2, t, tail) && !PL_get_nil(tail)) {
|
||||||
|
PL_reset_term_refs(tail);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!PL_get_arg(1, t, t)) {
|
||||||
|
PL_reset_term_refs(tail);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PL_reset_term_refs(tail);
|
||||||
|
PyObject *i = term_to_python(t, true, NULL);
|
||||||
|
if (!i) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (PyList_Check(i)) {
|
||||||
|
i = PyList_GetItem(i, 0);
|
||||||
|
if (i == NULL)
|
||||||
|
i = Py_None;
|
||||||
|
long int j;
|
||||||
|
if (PyList_Check(o)) {
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
if (PyInt_Check(i))
|
||||||
|
j = PyInt_AsLong(i);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (PyLong_Check(i))
|
||||||
|
j = PyLong_AsLong(i);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
return PyList_SetItem(o, j, exp) == 0;
|
||||||
|
}
|
||||||
|
if (PyDict_Check(i)) {
|
||||||
|
return PyDict_SetItem(o, i, exp) == 0;
|
||||||
|
}
|
||||||
|
return PyObject_SetAttr(o, i, exp) == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
1239
packages/packages/python/pybips.c
Normal file
1239
packages/packages/python/pybips.c
Normal file
File diff suppressed because it is too large
Load Diff
687
packages/packages/python/pypreds.c
Normal file
687
packages/packages/python/pypreds.c
Normal file
@ -0,0 +1,687 @@
|
|||||||
|
|
||||||
|
#include "py4yap.h"
|
||||||
|
|
||||||
|
PyObject *py_Main;
|
||||||
|
|
||||||
|
void pyErrorHandler__(int line, const char *file, const char *code) {
|
||||||
|
// this code is called if a Python error is found.
|
||||||
|
fprintf(stderr, " Python error detected at %s %s:%d\n\n", code, file, line);
|
||||||
|
PyErr_Print();
|
||||||
|
}
|
||||||
|
static foreign_t python_len(term_t tobj, term_t tf) {
|
||||||
|
Py_ssize_t len;
|
||||||
|
PyObject *o;
|
||||||
|
|
||||||
|
o = term_to_python(tobj, true, NULL);
|
||||||
|
if (o == NULL) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
len = PyObject_Length(o);
|
||||||
|
pyErrorAndReturn(PL_unify_int64(tf, len), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static foreign_t python_dir(term_t tobj, term_t tf) {
|
||||||
|
PyObject *dir;
|
||||||
|
PyObject *o;
|
||||||
|
|
||||||
|
o = term_to_python(tobj, true, NULL);
|
||||||
|
if (o == NULL) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
dir = PyObject_Dir(o);
|
||||||
|
{
|
||||||
|
foreign_t rc = address_to_term(dir, tf);
|
||||||
|
;
|
||||||
|
pyErrorAndReturn(rc, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static foreign_t python_index(term_t tobj, term_t tindex, term_t val) {
|
||||||
|
PyObject *i;
|
||||||
|
PyObject *o;
|
||||||
|
PyObject *f;
|
||||||
|
|
||||||
|
o = term_to_python(tobj, true, NULL);
|
||||||
|
if (o == NULL) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
if (!PySequence_Check(o)) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
i = term_to_python(tindex, true, NULL);
|
||||||
|
if (i == NULL) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
f = PyObject_CallMethodObjArgs(o, PyString_FromString("getitem"), i);
|
||||||
|
#else
|
||||||
|
f = PyObject_CallMethodObjArgs(o, PyUnicode_FromString("getitem"), i);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
foreign_t rc = address_to_term(f, val);
|
||||||
|
;
|
||||||
|
pyErrorAndReturn(rc, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static foreign_t python_is(term_t tobj, term_t tf) {
|
||||||
|
PyObject *o;
|
||||||
|
|
||||||
|
term_t lim = python_acquire_GIL();
|
||||||
|
|
||||||
|
o = term_to_python(tobj, true, NULL);
|
||||||
|
if (!o) {
|
||||||
|
python_release_GIL(lim);
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
foreign_t rc = python_to_term(o, tf);
|
||||||
|
if (rc)
|
||||||
|
PyErr_Clear();
|
||||||
|
python_release_GIL(lim);
|
||||||
|
pyErrorAndReturn(rc, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static foreign_t python_proc(term_t tobj) {
|
||||||
|
PyObject *o;
|
||||||
|
|
||||||
|
term_t lim = python_acquire_GIL();
|
||||||
|
|
||||||
|
o = term_to_python(tobj, true, NULL);
|
||||||
|
python_release_GIL(lim);
|
||||||
|
bool rc = o != NULL;
|
||||||
|
pyErrorAndReturn(rc , false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static foreign_t python_slice(term_t parent, term_t indx, term_t tobj) {
|
||||||
|
PyObject *pF, *pI;
|
||||||
|
|
||||||
|
PyObject *p;
|
||||||
|
|
||||||
|
// get Scope ...
|
||||||
|
pI = term_to_python(indx, true, NULL);
|
||||||
|
// got Scope.Exp
|
||||||
|
// get Scope ...
|
||||||
|
p = term_to_python(parent, true, NULL);
|
||||||
|
// Exp
|
||||||
|
if (!pI || !p) {
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
} else if ((pF = PySequence_GetSlice(p, 0, 0)) == NULL) {
|
||||||
|
PyErr_Print();
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
Py_DecRef(pI);
|
||||||
|
Py_DecRef(p);
|
||||||
|
Py_INCREF(pF);
|
||||||
|
{
|
||||||
|
foreign_t rc;
|
||||||
|
rc = address_to_term(pF, tobj);
|
||||||
|
pyErrorAndReturn(rc, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static foreign_t python_apply(term_t tin, term_t targs, term_t keywds,
|
||||||
|
term_t tf) {
|
||||||
|
PyObject *pF;
|
||||||
|
PyObject *pArgs, *pKeywords;
|
||||||
|
PyObject *pValue;
|
||||||
|
int i, arity;
|
||||||
|
atom_t aname;
|
||||||
|
foreign_t out;
|
||||||
|
term_t targ = PL_new_term_ref();
|
||||||
|
|
||||||
|
pF = term_to_python(tin, true, NULL);
|
||||||
|
PyErr_Clear();
|
||||||
|
if (pF == NULL) {
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
if (PL_is_atom(targs)) {
|
||||||
|
pArgs = NULL;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (!PL_get_name_arity(targs, &aname, &arity)) {
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
if (arity == 1 && PL_get_arg(1, targs, targ) && PL_is_variable(targ)) {
|
||||||
|
/* ignore (_) */
|
||||||
|
pArgs = NULL;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
pArgs = PyTuple_New(arity);
|
||||||
|
DebugPrintf("Tuple %p\n", pArgs);
|
||||||
|
|
||||||
|
if (!pArgs) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
for (i = 0; i < arity; i++) {
|
||||||
|
PyObject *pArg;
|
||||||
|
if (!PL_get_arg(i + 1, targs, targ)) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
pArg = term_to_python(targ, true, NULL);
|
||||||
|
if (pArg == NULL) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
/* pArg reference stolen here: */
|
||||||
|
PyTuple_SetItem(pArgs, i, pArg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (PL_is_atom(keywds)) {
|
||||||
|
pKeywords = NULL;
|
||||||
|
} else {
|
||||||
|
pKeywords = term_to_python(keywds, true, NULL);
|
||||||
|
}
|
||||||
|
if (PyCallable_Check(pF)) {
|
||||||
|
pValue = PyEval_CallObjectWithKeywords(pF, pArgs, pKeywords);
|
||||||
|
// PyObject_Print(pF,stderr,0);fprintf(stderr, "\n");
|
||||||
|
// PyObject_Print(pArgs,stderr,0);fprintf(stderr, " ");
|
||||||
|
// PyObject_Print(pKeywords,stderr,0);fprintf(stderr, "\n");
|
||||||
|
if (!pValue)
|
||||||
|
PyErr_Print();
|
||||||
|
else
|
||||||
|
Py_IncRef(pValue);
|
||||||
|
} else if (pArgs == NULL) {
|
||||||
|
pValue = pF;
|
||||||
|
|
||||||
|
if (pF) {
|
||||||
|
Py_IncRef(pValue);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PyErr_Print();
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
if (pArgs)
|
||||||
|
Py_DECREF(pArgs);
|
||||||
|
Py_DECREF(pF);
|
||||||
|
if (pValue == NULL) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
out = address_to_term(pValue, tf);
|
||||||
|
pyErrorAndReturn(out, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static foreign_t assign_python(term_t exp, term_t name) {
|
||||||
|
term_t stackp = python_acquire_GIL();
|
||||||
|
PyObject *e = term_to_python(exp, true, NULL);
|
||||||
|
|
||||||
|
if (e == NULL) {
|
||||||
|
python_release_GIL(stackp);
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
bool b = python_assign(name, e, NULL);
|
||||||
|
python_release_GIL(stackp);
|
||||||
|
pyErrorAndReturn(b, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static foreign_t python_builtin_eval(term_t caller, term_t dict, term_t out) {
|
||||||
|
PyErr_Clear();
|
||||||
|
PyObject *pI, *pArgs, *pOut;
|
||||||
|
PyObject *env;
|
||||||
|
atom_t name;
|
||||||
|
char *s;
|
||||||
|
int i, arity;
|
||||||
|
term_t targ = PL_new_term_ref();
|
||||||
|
|
||||||
|
if ((env = py_Builtin) == NULL) {
|
||||||
|
// no point in even trying
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
if (PL_get_name_arity(caller, &name, &arity)) {
|
||||||
|
if (!(s = PL_atom_chars(name))) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
if ((pI = PyObject_GetAttrString(env, s)) == NULL) {
|
||||||
|
PyErr_Print();
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
Py_INCREF(pI);
|
||||||
|
} else {
|
||||||
|
// Prolog should make sure this never happens.
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
pArgs = PyTuple_New(arity);
|
||||||
|
DebugPrintf("Tuple %p\n", pArgs);
|
||||||
|
for (i = 0; i < arity; i++) {
|
||||||
|
PyObject *pArg;
|
||||||
|
if (!PL_get_arg(i + 1, caller, targ)) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
/* ignore (_) */
|
||||||
|
if (i == 0 && PL_is_variable(targ)) {
|
||||||
|
pArg = Py_None;
|
||||||
|
} else {
|
||||||
|
pArg = term_to_python(targ, true, NULL);
|
||||||
|
if (pArg == NULL) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* pArg reference stolen here: */
|
||||||
|
if (PyTuple_SetItem(pArgs, i, pArg)) {
|
||||||
|
PyErr_Print();
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pOut = PyObject_CallObject(pI, pArgs);
|
||||||
|
Py_DECREF(pArgs);
|
||||||
|
Py_DECREF(pI);
|
||||||
|
if (pOut == NULL) {
|
||||||
|
PyErr_Print();
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
{
|
||||||
|
foreign_t rc = address_to_term(pOut, out);
|
||||||
|
;
|
||||||
|
pyErrorAndReturn(rc, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static foreign_t python_access(term_t obj, term_t f, term_t out) {
|
||||||
|
PyErr_Clear();
|
||||||
|
PyObject *o = term_to_python(obj, true, NULL), *pValue, *pArgs, *pF;
|
||||||
|
atom_t name;
|
||||||
|
char *s = NULL;
|
||||||
|
int i, arity;
|
||||||
|
term_t targ = PL_new_term_ref();
|
||||||
|
|
||||||
|
if (o == NULL) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
if (PL_is_atom(f)) {
|
||||||
|
if (!PL_get_atom_chars(f, &s)) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
if ((pValue = PyObject_GetAttrString(o, s)) == NULL) {
|
||||||
|
PyErr_Print();
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
Py_INCREF(pValue);
|
||||||
|
{ pyErrorAndReturn(python_to_term(pValue, out), false); }
|
||||||
|
}
|
||||||
|
if (!PL_get_name_arity(f, &name, &arity)) {
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
s = PL_atom_chars(name);
|
||||||
|
if (!s) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
if ((pF = PyObject_GetAttrString(o, s)) == NULL) {
|
||||||
|
DebugPrintf("Function %p\n", pArgs);
|
||||||
|
PyErr_Print();
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
pArgs = PyTuple_New(arity);
|
||||||
|
DebugPrintf("Tuple %p\n", pArgs);
|
||||||
|
for (i = 0; i < arity; i++) {
|
||||||
|
PyObject *pArg;
|
||||||
|
if (!PL_get_arg(i + 1, f, targ)) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
/* ignore (_) */
|
||||||
|
if (i == 0 && PL_is_variable(targ)) {
|
||||||
|
pArgs = Py_None;
|
||||||
|
}
|
||||||
|
pArg = term_to_python(targ, true, NULL);
|
||||||
|
if (pArg == NULL) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
/* pArg reference stolen here: */
|
||||||
|
PyTuple_SetItem(pArgs, i, pArg);
|
||||||
|
}
|
||||||
|
pValue = PyObject_CallObject(pF, pArgs);
|
||||||
|
Py_DECREF(pArgs);
|
||||||
|
Py_DECREF(pF);
|
||||||
|
if (pValue == NULL) {
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
{ pyErrorAndReturn(python_to_term(pValue, out), false); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static foreign_t python_field(term_t parent, term_t att, term_t tobj) {
|
||||||
|
PyObject *pF;
|
||||||
|
atom_t name;
|
||||||
|
char *s;
|
||||||
|
int arity;
|
||||||
|
|
||||||
|
if (!PL_get_name_arity(att, &name, &arity)) {
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
} else {
|
||||||
|
PyObject *p;
|
||||||
|
|
||||||
|
// got Scope.Exp
|
||||||
|
// get Scope ...
|
||||||
|
p = term_to_python(parent, true, NULL);
|
||||||
|
// Exp
|
||||||
|
if (!PL_get_name_arity(att, &name, &arity)) {
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
s = PL_atom_chars(name);
|
||||||
|
if (arity == 1 && !strcmp(s, "()")) {
|
||||||
|
if (!PL_get_arg(1, att, att)) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
if (!PL_get_name_arity(att, &name, &arity)) {
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
s = PL_atom_chars(name);
|
||||||
|
}
|
||||||
|
if (!s || !p) {
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
} else if ((pF = PyObject_GetAttrString(p, s)) == NULL) {
|
||||||
|
PyErr_Clear();
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
foreign_t rc;
|
||||||
|
rc = address_to_term(pF, tobj);
|
||||||
|
pyErrorAndReturn(rc, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static foreign_t python_main_module(term_t mod) {
|
||||||
|
{
|
||||||
|
foreign_t rc;
|
||||||
|
PyErr_Clear();
|
||||||
|
rc = address_to_term(py_Main, mod);
|
||||||
|
pyErrorAndReturn(rc, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static foreign_t python_function(term_t tobj) {
|
||||||
|
PyErr_Clear();
|
||||||
|
PyObject *obj = term_to_python(tobj, true, NULL);
|
||||||
|
foreign_t rc = PyFunction_Check(obj);
|
||||||
|
|
||||||
|
pyErrorAndReturn(rc, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreign_t python_builtin(term_t out) {
|
||||||
|
{
|
||||||
|
foreign_t rc;
|
||||||
|
PyErr_Clear();
|
||||||
|
rc = address_to_term(py_Builtin, out);
|
||||||
|
pyErrorAndReturn(rc, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static foreign_t python_run_file(term_t file) {
|
||||||
|
char *s;
|
||||||
|
size_t len;
|
||||||
|
char si[256];
|
||||||
|
s = si;
|
||||||
|
PyErr_Clear();
|
||||||
|
if (PL_get_nchars(file, &len, &s, CVT_ALL | CVT_EXCEPTION)) {
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
PyObject *PyFileObject = PyFile_FromString(si, "r");
|
||||||
|
PyRun_SimpleFileEx(PyFile_AsFile(PyFileObject), "test.py", 1);
|
||||||
|
#else
|
||||||
|
FILE *f = fopen(s, "r");
|
||||||
|
if (f == NULL) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
PyRun_SimpleFileEx(f, s, 1);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
{ pyErrorAndReturn(true, false); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
|
||||||
|
extern PyThreadState *YAP_save;
|
||||||
|
|
||||||
|
static foreign_t python_run_command(term_t cmd) {
|
||||||
|
char *s;
|
||||||
|
bool rc = false;
|
||||||
|
size_t len;
|
||||||
|
char si[256];
|
||||||
|
|
||||||
|
PyErr_Clear();
|
||||||
|
s = si;
|
||||||
|
if (PL_get_nchars(cmd, &len, &s, CVT_ALL | CVT_EXCEPTION)) {
|
||||||
|
PyRun_SimpleString(s);
|
||||||
|
rc = true;
|
||||||
|
}
|
||||||
|
pyErrorAndReturn(rc, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static foreign_t python_run_script(term_t cmd, term_t fun) {
|
||||||
|
char si[256], sf[256];
|
||||||
|
size_t len = 255, len1 = 255;
|
||||||
|
PyObject *pName, *pModule, *pFunc;
|
||||||
|
PyObject *pArgs = NULL, *pValue;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
PyErr_Clear();
|
||||||
|
s = si;
|
||||||
|
if (PL_get_nchars(cmd, &len, &s, CVT_ALL | CVT_EXCEPTION) &&
|
||||||
|
(s = sf) != NULL &&
|
||||||
|
PL_get_nchars(fun, &len1, &s, CVT_ALL | CVT_EXCEPTION)) {
|
||||||
|
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
pName = PyString_FromString("rbm");
|
||||||
|
#else
|
||||||
|
// asssumes UTF-8
|
||||||
|
pName = PyUnicode_FromString("rbm");
|
||||||
|
#endif
|
||||||
|
/* Error checking of pName left out */
|
||||||
|
|
||||||
|
pModule = PyImport_Import(pName);
|
||||||
|
PyErr_Clear();
|
||||||
|
Py_DECREF(pName);
|
||||||
|
|
||||||
|
if (pModule != NULL) {
|
||||||
|
pFunc = PyObject_GetAttrString(pModule, sf);
|
||||||
|
/* pFunc is a new reference */
|
||||||
|
|
||||||
|
if (pFunc && PyCallable_Check(pFunc)) {
|
||||||
|
pValue = PyObject_CallObject(pFunc, pArgs);
|
||||||
|
if (pValue != NULL) {
|
||||||
|
Py_DECREF(pValue);
|
||||||
|
} else {
|
||||||
|
Py_DECREF(pFunc);
|
||||||
|
Py_DECREF(pModule);
|
||||||
|
PyErr_Print();
|
||||||
|
fprintf(stderr, "Call failed\n");
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pyErrorHandler();
|
||||||
|
if (PyErr_Occurred())
|
||||||
|
PyErr_Print();
|
||||||
|
fprintf(stderr, "Cannot find function \"%s\"\n", sf);
|
||||||
|
}
|
||||||
|
Py_XDECREF(pFunc);
|
||||||
|
Py_DECREF(pModule);
|
||||||
|
} else {
|
||||||
|
PyErr_Print();
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
{ pyErrorAndReturn(true, false); }
|
||||||
|
}
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static foreign_t python_export(term_t t, term_t pl) {
|
||||||
|
foreign_t rc = false;
|
||||||
|
PyErr_Clear();
|
||||||
|
if (PL_is_functor(t, FUNCTOR_pointer1)) {
|
||||||
|
void *ptr;
|
||||||
|
term_t targ = PL_new_term_ref();
|
||||||
|
|
||||||
|
if (!PL_get_arg(1, t, targ)) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
if (!PL_get_pointer(targ, &ptr)) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
Py_INCREF((PyObject *)ptr);
|
||||||
|
/* pyErrorAndReturn( __main__, false) */
|
||||||
|
rc = python_to_term((PyObject *)ptr, pl);
|
||||||
|
}
|
||||||
|
pyErrorAndReturn(rc, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @pred python_import(MName, Mod)
|
||||||
|
* Import a python module to the YAP environment.
|
||||||
|
*
|
||||||
|
* @param mname module name, either an atom or a sequence of atoms,
|
||||||
|
* eg os.sys
|
||||||
|
* @param mod the pointer to the Python object
|
||||||
|
* @return success?
|
||||||
|
*/
|
||||||
|
static int python_import(term_t mname, term_t mod) {
|
||||||
|
PyObject *pName;
|
||||||
|
|
||||||
|
term_t t0 = python_acquire_GIL();
|
||||||
|
term_t arg = PL_new_term_ref();
|
||||||
|
char s0[MAXPATHLEN], *s = s0;
|
||||||
|
while (true) {
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
len = (MAXPATHLEN - 1) - (s - s0);
|
||||||
|
if (PL_is_pair(mname)) {
|
||||||
|
char *sa = NULL;
|
||||||
|
if (!PL_get_arg(1, mname, arg) || !PL_get_atom_chars(arg, &sa) ||
|
||||||
|
!PL_get_arg(2, mname, mname)) {
|
||||||
|
python_release_GIL(t0);
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
PL_get_atom_chars(arg, &sa);
|
||||||
|
strcpy(s, sa);
|
||||||
|
s += strlen(s);
|
||||||
|
*s++ = '.';
|
||||||
|
s[0] = '\0';
|
||||||
|
} else if (!PL_get_nchars(mname, &len, &s,
|
||||||
|
CVT_ATOM | CVT_EXCEPTION | REP_UTF8)) {
|
||||||
|
python_release_GIL(t0);
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
pName = PyString_FromString(s0);
|
||||||
|
#else
|
||||||
|
pName = PyUnicode_FromString(s0);
|
||||||
|
#endif
|
||||||
|
python_release_GIL(t0);
|
||||||
|
if (pName == NULL) {
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *pModule = PyImport_Import(pName);
|
||||||
|
|
||||||
|
Py_DECREF(pName);
|
||||||
|
if (pModule == NULL) {
|
||||||
|
#if EXTRA_MESSSAGES
|
||||||
|
if (PyErr_Occurred())
|
||||||
|
PyErr_Print();
|
||||||
|
PyErr_Clear();
|
||||||
|
#endif
|
||||||
|
{ pyErrorAndReturn(false, false); }
|
||||||
|
}
|
||||||
|
{
|
||||||
|
foreign_t rc = address_to_term(pModule, mod);
|
||||||
|
pyErrorAndReturn(rc, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static foreign_t python_to_rhs(term_t inp, term_t t) {
|
||||||
|
PyObject *pVal;
|
||||||
|
PyErr_Clear();
|
||||||
|
pVal = term_to_python(inp, true, NULL);
|
||||||
|
if (pVal == NULL)
|
||||||
|
pyErrorAndReturn(false, false);
|
||||||
|
pyErrorAndReturn(address_to_term(pVal, t), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static PyThreadState *_saveP = NULL;
|
||||||
|
static bool _threaded = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
static YAP_Int
|
||||||
|
p_python_ensure(term_t ptr)
|
||||||
|
{
|
||||||
|
PyGILState_STATE _tState = PyGILState_Ensure();
|
||||||
|
pyErrorAndReturn( PL_unify_int64(ptr, _tState), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static YAP_Int
|
||||||
|
p_python_release(term_t ptr)
|
||||||
|
{
|
||||||
|
|
||||||
|
PyGILState_STATE _tState;
|
||||||
|
PL_get_int64( ptr, &_tState);
|
||||||
|
PyGILState_Release( _tState );
|
||||||
|
pyErrorAndReturn( true, false);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
int _locked = 0;
|
||||||
|
PyThreadState *tstate;
|
||||||
|
|
||||||
|
static YAP_Int p_python_threaded(void) {
|
||||||
|
|
||||||
|
PyErr_Clear();
|
||||||
|
// PyEval_ReleaseThread(tstate);
|
||||||
|
// _threaded = true;
|
||||||
|
// _locked = 0;
|
||||||
|
pyErrorAndReturn(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyGILState_STATE gstate;
|
||||||
|
|
||||||
|
term_t python_acquire_GIL(void) {
|
||||||
|
term_t curSlot = PL_new_term_ref();
|
||||||
|
if (!_threaded)
|
||||||
|
pyErrorAndReturn(curSlot, false);
|
||||||
|
// extern int Yap_do_low_level_trace;
|
||||||
|
// Yap_do_low_level_trace = 1;
|
||||||
|
// f[rintf( stderr, "++%d\n", ++_locked);
|
||||||
|
// if (_locked > 0) { _locked++ ; }
|
||||||
|
// else
|
||||||
|
gstate = PyGILState_Ensure();
|
||||||
|
pyErrorAndReturn(curSlot, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool python_release_GIL(term_t curBlock) {
|
||||||
|
PyErr_Clear();
|
||||||
|
PL_reset_term_refs(curBlock);
|
||||||
|
if (_threaded) {
|
||||||
|
PyGILState_Release(gstate);
|
||||||
|
}
|
||||||
|
pyErrorAndReturn(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//: prolog: release python
|
||||||
|
|
||||||
|
install_t install_pypreds(void) {
|
||||||
|
PL_register_foreign("python_builtin_eval", 3, python_builtin_eval, 0);
|
||||||
|
PL_register_foreign("python_builtin", 1, python_builtin, 0);
|
||||||
|
PL_register_foreign("python_import", 2, python_import, 0);
|
||||||
|
PL_register_foreign("python_to_rhs", 2, python_to_rhs, 0);
|
||||||
|
PL_register_foreign("python_len", 2, python_len, 0);
|
||||||
|
PL_register_foreign("python_is", 2, python_is, 0);
|
||||||
|
PL_register_foreign("python_dir", 2, python_dir, 0);
|
||||||
|
PL_register_foreign("python_apply", 4, python_apply, 0);
|
||||||
|
PL_register_foreign("python_index", 3, python_index, 0);
|
||||||
|
PL_register_foreign("python_field", 3, python_field, 0);
|
||||||
|
PL_register_foreign("python_assign", 2, assign_python, 0);
|
||||||
|
PL_register_foreign("python_export", 2, python_export, 0);
|
||||||
|
PL_register_foreign("python_function", 1, python_function, 0);
|
||||||
|
PL_register_foreign("python_slice", 4, python_slice, 0);
|
||||||
|
PL_register_foreign("python_run_file", 1, python_run_file, 0);
|
||||||
|
PL_register_foreign("python_proc", 1, python_proc, 0);
|
||||||
|
PL_register_foreign("python_run_command", 1, python_run_command, 0);
|
||||||
|
PL_register_foreign("python_run_script", 2, python_run_script, 0);
|
||||||
|
PL_register_foreign("python_main_module", 1, python_main_module, 0);
|
||||||
|
PL_register_foreign("python_import", 2, python_import, 0);
|
||||||
|
PL_register_foreign("python_access", 3, python_access, 0);
|
||||||
|
PL_register_foreign("python_threaded", 0, p_python_threaded, 0);
|
||||||
|
}
|
@ -115,7 +115,7 @@ static foreign_t array_to_python_view(term_t addr, term_t type, term_t szt,
|
|||||||
static foreign_t prolog_list_to_python_list(term_t plist, term_t pyt, term_t tlen) {
|
static foreign_t prolog_list_to_python_list(term_t plist, term_t pyt, term_t tlen) {
|
||||||
size_t sz, i;
|
size_t sz, i;
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
PyObject *pyl = term_to_python(pyt, true, NULL);
|
PyObject *pyl = term_to_python(pyt, true, NULL, true);
|
||||||
term_t targ = PL_new_term_ref();
|
term_t targ = PL_new_term_ref();
|
||||||
|
|
||||||
if (PL_skip_list(plist, targ, &sz) <0 || ! PL_get_nil(targ)) {
|
if (PL_skip_list(plist, targ, &sz) <0 || ! PL_get_nil(targ)) {
|
||||||
@ -131,7 +131,7 @@ static foreign_t prolog_list_to_python_list(term_t plist, term_t pyt, term_t tle
|
|||||||
if (!PL_get_list(plist, targ, plist)) {
|
if (!PL_get_list(plist, targ, plist)) {
|
||||||
pyErrorAndReturn( false, false);
|
pyErrorAndReturn( false, false);
|
||||||
}
|
}
|
||||||
PyObject *t = term_to_python(targ, true, NULL);
|
PyObject *t = term_to_python(targ, true, NULL, true);
|
||||||
PyList_SET_ITEM(pyl, i, t);
|
PyList_SET_ITEM(pyl, i, t);
|
||||||
}
|
}
|
||||||
if (PL_is_variable(tlen)) {
|
if (PL_is_variable(tlen)) {
|
||||||
|
@ -32,8 +32,8 @@ static PyObject *s_to_python(const char *s, bool eval, PyObject *p0) {
|
|||||||
Py_INCREF(o);
|
Py_INCREF(o);
|
||||||
return CHECKNULL(YAP_MkStringTerm(s), o);
|
return CHECKNULL(YAP_MkStringTerm(s), o);
|
||||||
} else {
|
} else {
|
||||||
//char *ns = Py_Malloc(strlen(s)+1);
|
// char *ns = Py_Malloc(strlen(s)+1);
|
||||||
///strcpy(ns,s);
|
/// strcpy(ns,s);
|
||||||
PyObject *pobj = PyUnicode_FromString(s);
|
PyObject *pobj = PyUnicode_FromString(s);
|
||||||
return pobj;
|
return pobj;
|
||||||
}
|
}
|
||||||
@ -59,6 +59,42 @@ X_API PyObject *string_to_python(const char *s, bool eval, PyObject *p0) {
|
|||||||
return s_to_python(s, eval, p0);
|
return s_to_python(s, eval, p0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool copy_to_dictionary(PyObject *dict, term_t targ, term_t taux,
|
||||||
|
bool eval, bool cvt) {
|
||||||
|
PyObject *lhs, *rhs;
|
||||||
|
term_t tleft = PL_new_term_ref(), tright = PL_new_term_ref();
|
||||||
|
|
||||||
|
functor_t fun;
|
||||||
|
|
||||||
|
AOK(PL_get_functor(targ, &fun), false);
|
||||||
|
while (fun == FUNCTOR_comma2) {
|
||||||
|
AOK(PL_get_arg(1, targ, tleft), false);
|
||||||
|
if (!copy_to_dictionary(dict, tleft, taux, eval, cvt))
|
||||||
|
return false;
|
||||||
|
AOK(PL_get_arg(2, targ, targ), false);
|
||||||
|
return copy_to_dictionary(dict, tright, taux, eval, cvt);
|
||||||
|
}
|
||||||
|
// PyObject_Print(dict, stderr, 0); fprintf(stderr,"\n");
|
||||||
|
// Py_DECREF(lhs);
|
||||||
|
// Py_DECREF(rhs);
|
||||||
|
|
||||||
|
AOK(PL_get_arg(1, targ, tleft), false);
|
||||||
|
lhs = atom_to_python_string(tleft);
|
||||||
|
if (lhs == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
AOK(PL_get_arg(2, targ, tright), false);
|
||||||
|
rhs = term_to_python(tright, eval, NULL, cvt);
|
||||||
|
if (rhs == NULL) {
|
||||||
|
PyErr_Print();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return PyDict_SetItem(dict, lhs, rhs) >= 0;
|
||||||
|
// PyObject_Print(dict, stderr, 0); fprintf(stderr,"\n");
|
||||||
|
// Py_DECREF(lhs);
|
||||||
|
// Py_DECREF(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* term_to_python translates and evaluates from Prolog to Python
|
* term_to_python translates and evaluates from Prolog to Python
|
||||||
*
|
*
|
||||||
@ -67,7 +103,7 @@ X_API PyObject *string_to_python(const char *s, bool eval, PyObject *p0) {
|
|||||||
*
|
*
|
||||||
* @return a Python object descriptor or NULL if failed
|
* @return a Python object descriptor or NULL if failed
|
||||||
*/
|
*/
|
||||||
PyObject *term_to_python(term_t t, bool eval, PyObject *o) {
|
PyObject *term_to_python(term_t t, bool eval, PyObject *o, bool cvt) {
|
||||||
// o≈
|
// o≈
|
||||||
YAP_Term yt = YAP_GetFromSlot(t);
|
YAP_Term yt = YAP_GetFromSlot(t);
|
||||||
// Yap_DebugPlWriteln(yt);
|
// Yap_DebugPlWriteln(yt);
|
||||||
@ -77,7 +113,9 @@ PyObject *term_to_python(term_t t, bool eval, PyObject *o) {
|
|||||||
Yap_ThrowError(SYSTEM_ERROR_INTERNAL, yt, "in term_to_python");
|
Yap_ThrowError(SYSTEM_ERROR_INTERNAL, yt, "in term_to_python");
|
||||||
}
|
}
|
||||||
PyObject *out = PyTuple_New(1);
|
PyObject *out = PyTuple_New(1);
|
||||||
PyTuple_SET_ITEM(out, 0, PyLong_FromLong(t));
|
PyTuple_SET_ITEM(out, 0, PyLong_FromLong((YAP_Int)YAP_GetFromSlot(t)));
|
||||||
|
if (!cvt)
|
||||||
|
return out;
|
||||||
return term_to_nametuple("v", 1, out);
|
return term_to_nametuple("v", 1, out);
|
||||||
};
|
};
|
||||||
case PL_ATOM: {
|
case PL_ATOM: {
|
||||||
@ -90,12 +128,13 @@ PyObject *term_to_python(term_t t, bool eval, PyObject *o) {
|
|||||||
/* if (!o)
|
/* if (!o)
|
||||||
return o;
|
return o;
|
||||||
*/
|
*/
|
||||||
} else {
|
}
|
||||||
o = PythonLookupSpecial(s);
|
if (!o) {
|
||||||
|
o = PyUnicode_FromString(s);
|
||||||
}
|
}
|
||||||
if (o) {
|
if (o) {
|
||||||
Py_INCREF(o);
|
Py_INCREF(o);
|
||||||
return CHECKNULL(t, o);
|
return o;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case PL_STRING: {
|
case PL_STRING: {
|
||||||
@ -115,7 +154,7 @@ PyObject *term_to_python(term_t t, bool eval, PyObject *o) {
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
// char *p = malloc(strlen(s)+1);
|
// char *p = malloc(strlen(s)+1);
|
||||||
//strcpy(p, s);
|
// strcpy(p, s);
|
||||||
PyObject *pobj = PyUnicode_FromString(s);
|
PyObject *pobj = PyUnicode_FromString(s);
|
||||||
Py_IncRef(pobj);
|
Py_IncRef(pobj);
|
||||||
return CHECKNULL(t, pobj);
|
return CHECKNULL(t, pobj);
|
||||||
@ -142,81 +181,218 @@ PyObject *term_to_python(term_t t, bool eval, PyObject *o) {
|
|||||||
out = PyFloat_FromDouble(fl);
|
out = PyFloat_FromDouble(fl);
|
||||||
return CHECKNULL(t, out);
|
return CHECKNULL(t, out);
|
||||||
}
|
}
|
||||||
default: {
|
default:
|
||||||
term_t tail = PL_new_term_ref(), arg;
|
if (PL_is_pair(t)) {
|
||||||
size_t len, i;
|
term_t tail = PL_new_term_ref();
|
||||||
if (PL_skip_list(t, tail, &len) && PL_get_nil(tail)) {
|
term_t arg = PL_new_term_ref();
|
||||||
PyObject *out, *a;
|
size_t len, i;
|
||||||
|
if (PL_skip_list(t, tail, &len) && PL_get_nil(tail)) {
|
||||||
|
PyObject *out, *a;
|
||||||
|
|
||||||
arg = tail;
|
out = PyList_New(len);
|
||||||
out = PyList_New(len);
|
if (!out) {
|
||||||
if (!out) {
|
PL_reset_term_refs(tail);
|
||||||
PL_reset_term_refs(tail);
|
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "list->python");
|
||||||
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "list->python");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
if (!PL_get_list(t, arg, t)) {
|
if (!PL_get_list(t, arg, t)) {
|
||||||
PL_reset_term_refs(tail);
|
PL_reset_term_refs(tail);
|
||||||
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "list->python");
|
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "list->python");
|
||||||
}
|
}
|
||||||
a = term_to_python(arg, eval, o);
|
a = term_to_python(arg, eval, o, cvt);
|
||||||
if (a) {
|
if (a) {
|
||||||
if (PyList_SetItem(out, i, a) < 0) {
|
if (PyList_SetItem(out, i, a) < 0) {
|
||||||
PL_reset_term_refs(tail);
|
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "list->python");
|
||||||
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "list->python");
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PL_reset_term_refs(tail);
|
||||||
|
return out;
|
||||||
|
} else {
|
||||||
|
PyObject *no = find_obj(o, t, false);
|
||||||
|
if (no == o)
|
||||||
|
return NULL;
|
||||||
|
return term_to_python(t, eval, no, cvt);
|
||||||
}
|
}
|
||||||
PL_reset_term_refs(tail);
|
|
||||||
return CHECKNULL(t, out);
|
|
||||||
} else {
|
} else {
|
||||||
functor_t fun;
|
{
|
||||||
atom_t name;
|
term_t tail = PL_new_term_ref();
|
||||||
int arity;
|
functor_t fun;
|
||||||
PyObject *rc;
|
atom_t name;
|
||||||
|
int arity;
|
||||||
|
PyObject *rc;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
if (!PL_get_functor(t, &fun)) {
|
if (!PL_get_functor(t, &fun)) {
|
||||||
PL_reset_term_refs(tail);
|
PL_reset_term_refs(tail);
|
||||||
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "list->python");
|
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "list->python");
|
||||||
|
}
|
||||||
|
if (fun == FUNCTOR_pointer1) {
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
AOK(PL_get_arg(1, t, t), NULL);
|
||||||
|
AOK(PL_get_pointer(t, &ptr), NULL)
|
||||||
|
/* return __main__,s */
|
||||||
|
return (PyObject *)ptr;
|
||||||
|
}
|
||||||
|
if (fun == FUNCTOR_sqbrackets2) {
|
||||||
|
term_t targ = PL_new_term_ref(), trhs = PL_new_term_ref();
|
||||||
|
PyObject *v;
|
||||||
|
Py_ssize_t min, max;
|
||||||
|
AOK(PL_get_arg(2, t, targ), NULL);
|
||||||
|
v = term_to_python(targ, eval, o, false);
|
||||||
|
|
||||||
|
AOK(PL_get_arg(1, t, targ), NULL);
|
||||||
|
AOK(PL_get_list(targ, trhs, targ), NULL);
|
||||||
|
if (PL_is_functor(trhs, FUNCTOR_colon2)) {
|
||||||
|
if (!PySequence_Check(v))
|
||||||
|
return NULL;
|
||||||
|
min = get_p_int(term_to_python(targ, true, NULL, false), 0);
|
||||||
|
AOK(PL_get_arg(1, trhs, targ), NULL);
|
||||||
|
if (PL_is_functor(targ, FUNCTOR_colon2)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
max = get_p_int(term_to_python(targ, true, o, false),
|
||||||
|
PyObject_Size(v));
|
||||||
|
return PySequence_GetSlice(v, min, max);
|
||||||
|
} else {
|
||||||
|
PyObject *ip = term_to_python(trhs, eval, o, cvt);
|
||||||
|
if (PySequence_Check(v)) {
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
if (PyLong_Check(ip) {
|
||||||
|
min = PyLong_AsLong(ip);
|
||||||
|
} else if (PyInt_Check(ip) {
|
||||||
|
min = PyInt_asInt(ip);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (PyLong_Check(ip)) {
|
||||||
|
PyObject *o = PySequence_GetItem(v, PyLong_AsLong(ip));
|
||||||
|
if (o == NULL)
|
||||||
|
o = Py_None;
|
||||||
|
if (CHECKNULL(t, o) == NULL)
|
||||||
|
return NULL;
|
||||||
|
Py_INCREF(o);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
o = PyObject_GetItem(v, ip);
|
||||||
|
if (o == NULL)
|
||||||
|
o = Py_None;
|
||||||
|
Py_INCREF(o);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fun == FUNCTOR_dollar1) {
|
||||||
|
char *s = NULL;
|
||||||
|
term_t targ = PL_new_term_ref();
|
||||||
|
AOK(PL_get_arg(1, t, targ), NULL);
|
||||||
|
AOK(PL_get_atom_chars(targ, &s), NULL);
|
||||||
|
/* return __main__,s */
|
||||||
|
PyObject *o = PyObject_GetAttrString(py_Main, s);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
if (fun == FUNCTOR_brackets1) {
|
||||||
|
AOK(PL_get_arg(1, t, t), NULL);
|
||||||
|
return term_to_python(t, true, NULL, true);
|
||||||
|
}
|
||||||
|
if (fun == FUNCTOR_complex2) {
|
||||||
|
term_t targ = PL_new_term_ref();
|
||||||
|
PyObject *lhs, *rhs;
|
||||||
|
double d1, d2;
|
||||||
|
|
||||||
|
AOK(PL_get_arg(1, t, targ), NULL);
|
||||||
|
lhs = term_to_python(targ, eval, NULL, cvt);
|
||||||
|
AOK(PyNumber_Check(lhs), NULL);
|
||||||
|
if (PyFloat_Check(lhs)) {
|
||||||
|
d1 = PyFloat_AsDouble(lhs);
|
||||||
|
} else if (PyLong_Check(lhs)) {
|
||||||
|
d1 = PyLong_AsLong(lhs);
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
} else if (PyInt_Check(lhs)) {
|
||||||
|
d1 = PyInt_AsLong(lhs);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
AOK(PL_get_arg(2, t, targ), NULL);
|
||||||
|
rhs = term_to_python(targ, eval, NULL, cvt);
|
||||||
|
AOK(PyNumber_Check(rhs), NULL);
|
||||||
|
if (PyFloat_Check(rhs)) {
|
||||||
|
d2 = PyFloat_AsDouble(rhs);
|
||||||
|
} else if (PyLong_Check(rhs)) {
|
||||||
|
d2 = PyLong_AsLong(rhs);
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
} else if (PyInt_Check(rhs)) {
|
||||||
|
d2 = PyInt_AsLong(rhs);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PyComplex_FromDoubles(d1, d2);
|
||||||
|
}
|
||||||
|
if (fun == FUNCTOR_curly1) {
|
||||||
|
term_t targ = PL_new_term_ref(), taux = PL_new_term_ref();
|
||||||
|
PyObject *dict;
|
||||||
|
|
||||||
|
AOK(PL_get_arg(1, t, t), NULL);
|
||||||
|
if (!(dict = PyDict_New()))
|
||||||
|
return NULL;
|
||||||
|
DebugPrintf("Dict %p\n", dict);
|
||||||
|
|
||||||
|
while (PL_is_functor(t, FUNCTOR_comma2)) {
|
||||||
|
AOK(PL_get_arg(1, t, targ), NULL);
|
||||||
|
AOK(PL_is_functor(targ, FUNCTOR_colon2), NULL);
|
||||||
|
|
||||||
|
AOK(copy_to_dictionary(dict, targ, taux, eval, cvt), NULL);
|
||||||
|
AOK(PL_get_arg(2, t, t), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PL_is_functor(t, FUNCTOR_colon2)) {
|
||||||
|
AOK(copy_to_dictionary(dict, t, taux, eval, cvt), NULL);
|
||||||
|
}
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
AOK(PL_get_name_arity(t, &name, &arity), NULL);
|
||||||
|
if (name == ATOM_t) {
|
||||||
|
int i;
|
||||||
|
rc = PyTuple_New(arity);
|
||||||
|
for (i = 0; i < arity; i++) {
|
||||||
|
term_t arg = PL_new_term_ref();
|
||||||
|
if (!PL_get_arg(i + 1, t, arg)) {
|
||||||
|
PL_reset_term_refs(arg);
|
||||||
|
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "t(...)->python");
|
||||||
|
}
|
||||||
|
PyObject *a = term_to_python(arg, eval, o, cvt);
|
||||||
|
if (a) {
|
||||||
|
if (PyTuple_SetItem(rc, i, a) < 0) {
|
||||||
|
PL_reset_term_refs(arg);
|
||||||
|
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "t(...)->python");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PL_reset_term_refs(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (eval)
|
||||||
|
rc = compound_to_pyeval(t, o, cvt);
|
||||||
|
else
|
||||||
|
rc = compound_to_pytree(t, o, cvt);
|
||||||
|
PL_reset_term_refs(tail);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
AOK(PL_get_name_arity(t, &name, &arity), NULL);
|
|
||||||
if (name == ATOM_t) {
|
|
||||||
int i;
|
|
||||||
rc = PyTuple_New(arity);
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
term_t arg = PL_new_term_ref();
|
|
||||||
if (!PL_get_arg(i+1, t, arg)) {
|
|
||||||
PL_reset_term_refs(arg);
|
|
||||||
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "t(...)->python");
|
|
||||||
}
|
|
||||||
PyObject *a = term_to_python(arg, eval, o);
|
|
||||||
if (a) {
|
|
||||||
if (PyTuple_SetItem(rc, i, a) < 0) {
|
|
||||||
PL_reset_term_refs(arg);
|
|
||||||
YAPPy_ThrowError(SYSTEM_ERROR_INTERNAL, t, "t(...)->python");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PL_reset_term_refs(arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (eval)
|
|
||||||
rc = compound_to_pyeval(t, o);
|
|
||||||
else
|
|
||||||
rc = compound_to_pytree(t, o);
|
|
||||||
PL_reset_term_refs(tail);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return Py_None;
|
return Py_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *yap_to_python(YAP_Term t, bool eval, PyObject *o) {
|
PyObject *yap_to_python(YAP_Term t, bool eval, PyObject *o, bool cvt) {
|
||||||
if (t == 0)
|
if (t == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
term_t yt = YAP_InitSlot(t);
|
term_t yt = YAP_InitSlot(t);
|
||||||
o = term_to_python(yt, eval, o);
|
o = term_to_python(yt, eval, o, cvt);
|
||||||
PL_reset_term_refs(yt);
|
PL_reset_term_refs(yt);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
@ -231,9 +407,8 @@ PyObject *deref_term_to_python(term_t t) {
|
|||||||
PyObject *p = PyUnicode_FromString(o);
|
PyObject *p = PyUnicode_FromString(o);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
return term_to_python(t, false, NULL);
|
return term_to_python(t, true, NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void YAPPy_ThrowError__(const char *file, const char *function, int lineno,
|
void YAPPy_ThrowError__(const char *file, const char *function, int lineno,
|
||||||
yap_error_number type, term_t where, ...);
|
yap_error_number type, term_t where, ...);
|
||||||
|
@ -3,52 +3,29 @@
|
|||||||
#include <frameobject.h>
|
#include <frameobject.h>
|
||||||
|
|
||||||
void YAPPy_ThrowError__(const char *file, const char *function, int lineno,
|
void YAPPy_ThrowError__(const char *file, const char *function, int lineno,
|
||||||
yap_error_number type, term_t where, ...) {
|
yap_error_number type, term_t where, ...) {
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char tmpbuf[MAXPATHLEN];
|
char tmpbuf[MAXPATHLEN];
|
||||||
YAP_Term wheret = YAP_GetFromSlot(where);
|
YAP_Term wheret = YAP_GetFromSlot(where);
|
||||||
|
PyObject *ptype;
|
||||||
|
|
||||||
if (PyErr_Occurred()) {
|
if ((ptype = PyErr_Occurred()) == NULL) {
|
||||||
PyErr_Print();
|
PyErr_Print();
|
||||||
} else {
|
}
|
||||||
PyObject *ptype, *pvalue, *ptraceback;
|
|
||||||
PyObject *pystr, *module_name, *pyth_module, *pyth_func;
|
|
||||||
|
|
||||||
/* See if we can get a full traceback */
|
va_start(ap, where);
|
||||||
module_name = PyUnicode_FromString("traceback");
|
char *format = va_arg(ap, char *);
|
||||||
pyth_module = PyImport_Import(module_name);
|
if (format != NULL) {
|
||||||
Py_DECREF(module_name);
|
|
||||||
|
|
||||||
if (pyth_module != NULL) {
|
|
||||||
pyth_func = PyObject_GetAttrString(pyth_module, "format_exception");
|
|
||||||
if (pyth_func && PyCallable_Check(pyth_func)) {
|
|
||||||
PyObject *pyth_val;
|
|
||||||
|
|
||||||
pyth_val = PyObject_CallFunctionObjArgs(pyth_func, ptype, pvalue, ptraceback, NULL);
|
|
||||||
|
|
||||||
pystr = PyObject_Str(pyth_val);
|
|
||||||
fprintf(stderr, "%s", PyUnicode_AsUTF8(pystr));
|
|
||||||
Py_DECREF(pyth_val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PyFrameObject *fr;
|
|
||||||
if ((fr = PyEval_GetFrame())) {
|
|
||||||
fprintf(stderr, "at frame %p, line %d\n", fr, PyFrame_GetLineNumber(fr));
|
|
||||||
}
|
|
||||||
va_start(ap, where);
|
|
||||||
char *format = va_arg(ap, char *);
|
|
||||||
if (format != NULL) {
|
|
||||||
#if HAVE_VSNPRINTF
|
#if HAVE_VSNPRINTF
|
||||||
(void)vsnprintf(tmpbuf, MAXPATHLEN - 1, format, ap);
|
(void)vsnprintf(tmpbuf, MAXPATHLEN - 1, format, ap);
|
||||||
#else
|
#else
|
||||||
(void)vsprintf(tnpbuf, format, ap);
|
(void)vsprintf(tnpbuf, format, ap);
|
||||||
#endif
|
#endif
|
||||||
// fprintf(stderr, "warning: ");
|
// fprintf(stderr, "warning: ");
|
||||||
Yap_ThrowError__(file, function, lineno, type, wheret, tmpbuf);
|
Yap_ThrowError__(file, function, lineno, type, wheret, tmpbuf);
|
||||||
} else {
|
} else {
|
||||||
Yap_ThrowError__(file, function, lineno, type, wheret);
|
Yap_ThrowError__(file, function, lineno, type, wheret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static foreign_t repr_term(PyObject *pVal, term_t t) {
|
static foreign_t repr_term(PyObject *pVal, term_t t) {
|
||||||
@ -132,12 +109,14 @@ foreign_t python_to_term(PyObject *pVal, term_t t) {
|
|||||||
rc = rc && PL_unify_atom(t, ATOM_brackets);
|
rc = rc && PL_unify_atom(t, ATOM_brackets);
|
||||||
} else {
|
} else {
|
||||||
if ((s = (Py_TYPE(pVal)->tp_name))) {
|
if ((s = (Py_TYPE(pVal)->tp_name))) {
|
||||||
if (!strcmp(s, "H")) {
|
if (!strcmp(s, "v")) {
|
||||||
pVal = PyTuple_GetItem(pVal, 0);
|
pVal = PyTuple_GetItem(pVal, 0);
|
||||||
if (pVal == NULL) {
|
if (pVal == NULL) {
|
||||||
pVal = Py_None;
|
pVal = Py_None;
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
}
|
}
|
||||||
|
term_t v = YAP_InitSlot(PyLong_AsLong(pVal));
|
||||||
|
return PL_unify(v, t);
|
||||||
}
|
}
|
||||||
if (s[0] == '$') {
|
if (s[0] == '$') {
|
||||||
char *ns = malloc(strlen(s) + 5);
|
char *ns = malloc(strlen(s) + 5);
|
||||||
@ -171,22 +150,17 @@ foreign_t python_to_term(PyObject *pVal, term_t t) {
|
|||||||
} else if (PyList_Check(pVal)) {
|
} else if (PyList_Check(pVal)) {
|
||||||
Py_ssize_t i, sz = PyList_GET_SIZE(pVal);
|
Py_ssize_t i, sz = PyList_GET_SIZE(pVal);
|
||||||
|
|
||||||
if (sz == 0) {
|
for (i = 0; i < sz; i++) {
|
||||||
rc = rc && PL_unify_nil(t);
|
PyObject *obj;
|
||||||
} else {
|
rc = rc && PL_unify_list(t, to, t);
|
||||||
for (i = 0; i < sz; i++) {
|
if ((obj = PyList_GetItem(pVal, i - 1)) == NULL) {
|
||||||
PyObject *obj;
|
obj = Py_None;
|
||||||
if (!PL_unify_list(t, to, t)) {
|
|
||||||
rc = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((obj = PyList_GetItem(pVal, i)) == NULL) {
|
|
||||||
obj = Py_None;
|
|
||||||
}
|
|
||||||
rc = rc && python_to_term(obj, to);
|
|
||||||
}
|
}
|
||||||
rc = rc && PL_unify_nil(t);
|
rc = rc && python_to_term(obj, to);
|
||||||
|
if (!rc)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
return rc && PL_unify_nil(t);
|
||||||
// fputs("[***] ", stderr);
|
// fputs("[***] ", stderr);
|
||||||
// Yap_DebugPlWrite(yt); fputs("[***]\n", stderr);
|
// Yap_DebugPlWrite(yt); fputs("[***]\n", stderr);
|
||||||
} else if (PyDict_Check(pVal)) {
|
} else if (PyDict_Check(pVal)) {
|
||||||
@ -279,7 +253,10 @@ bool python_assign(term_t t, PyObject *exp, PyObject *context) {
|
|||||||
PL_get_atom_chars(t, &s);
|
PL_get_atom_chars(t, &s);
|
||||||
if (!context)
|
if (!context)
|
||||||
context = py_Main;
|
context = py_Main;
|
||||||
return PyObject_SetAttrString(context, s, exp) == 0;
|
if (PyObject_SetAttrString(context, s, exp) == 0)
|
||||||
|
return true;
|
||||||
|
PyErr_Print();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
case PL_STRING:
|
case PL_STRING:
|
||||||
case PL_INTEGER:
|
case PL_INTEGER:
|
||||||
@ -289,28 +266,29 @@ bool python_assign(term_t t, PyObject *exp, PyObject *context) {
|
|||||||
default: {
|
default: {
|
||||||
term_t tail = PL_new_term_ref(), arg = PL_new_term_ref();
|
term_t tail = PL_new_term_ref(), arg = PL_new_term_ref();
|
||||||
size_t len, i;
|
size_t len, i;
|
||||||
if (PL_skip_list(t, tail, &len) &&
|
|
||||||
PL_get_nil(tail)) { // true list
|
|
||||||
|
|
||||||
bool o = true;
|
if (PL_is_pair(t)) {
|
||||||
if (PySequence_Check(exp) && PySequence_Length(exp) == len)
|
if (PL_skip_list(t, tail, &len) &&
|
||||||
|
PL_get_nil(tail)) { // true list
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
bool o = true;
|
||||||
PyObject *p;
|
if (PySequence_Check(exp) && PySequence_Length(exp) == len)
|
||||||
if (!PL_get_list(t, arg, t)) {
|
|
||||||
PL_reset_term_refs(tail);
|
for (i = 0; i < len; i++) {
|
||||||
o = false;
|
PyObject *p;
|
||||||
p = Py_None;
|
if (!PL_get_list(t, arg, t)) {
|
||||||
|
PL_reset_term_refs(tail);
|
||||||
|
o = false;
|
||||||
|
p = Py_None;
|
||||||
|
}
|
||||||
|
if ((p = PySequence_GetItem(exp, i)) == NULL)
|
||||||
|
p = Py_None;
|
||||||
|
if (!python_assign(arg, p, context)) {
|
||||||
|
PL_reset_term_refs(tail);
|
||||||
|
o = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ((p = PySequence_GetItem(exp, i)) == NULL)
|
}
|
||||||
p = Py_None;
|
|
||||||
if (!python_assign(arg, p, context)) {
|
|
||||||
PL_reset_term_refs(tail);
|
|
||||||
o = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PL_reset_term_refs(tail);
|
|
||||||
return o;
|
|
||||||
} else {
|
} else {
|
||||||
functor_t fun;
|
functor_t fun;
|
||||||
|
|
||||||
@ -320,50 +298,65 @@ bool python_assign(term_t t, PyObject *exp, PyObject *context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fun == FUNCTOR_sqbrackets2) {
|
if (fun == FUNCTOR_sqbrackets2) {
|
||||||
|
// tail is the object o
|
||||||
if (!PL_get_arg(2, t, tail)) {
|
if (!PL_get_arg(2, t, tail)) {
|
||||||
PL_reset_term_refs(tail);
|
PL_reset_term_refs(tail);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
PyObject *o = term_to_python(tail, true, context, false);
|
||||||
PyObject *o = term_to_python(tail, true, context);
|
// t now refers to the index
|
||||||
if (!PL_get_arg(2, t, tail) && !PL_get_nil(tail)) {
|
if (!PL_get_arg(1, t, t) || !PL_get_list(t, t, tail) ||
|
||||||
|
!PL_get_nil(tail)) {
|
||||||
PL_reset_term_refs(tail);
|
PL_reset_term_refs(tail);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!PL_get_arg(1, t, t)) {
|
PyObject *i = term_to_python(t, true, NULL, false);
|
||||||
PL_reset_term_refs(tail);
|
// check numeric
|
||||||
return false;
|
if (PySequence_Check(o) && PyLong_Check(i)) {
|
||||||
}
|
|
||||||
PL_reset_term_refs(tail);
|
|
||||||
PyObject *i = term_to_python(t, true, NULL);
|
|
||||||
if (!i) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (PyList_Check(i)) {
|
|
||||||
i = PyList_GetItem(i, 0);
|
|
||||||
if (i == NULL)
|
|
||||||
i = Py_None;
|
|
||||||
long int j;
|
long int j;
|
||||||
if (PyList_Check(o)) {
|
j = PyLong_AsLong(i);
|
||||||
|
return PySequence_SetItem(o, j, exp) == 0;
|
||||||
|
}
|
||||||
#if PY_MAJOR_VERSION < 3
|
#if PY_MAJOR_VERSION < 3
|
||||||
if (PyInt_Check(i))
|
if (PySequence_Check(o) && PyInt_Check(i)) {
|
||||||
j = PyInt_AsLong(i);
|
long int j;
|
||||||
else
|
j = PyInt_AsLong(i);
|
||||||
|
return PySequence_SetItem(o, i, exp) == 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (PyLong_Check(i))
|
if (PyDict_Check(o)) {
|
||||||
j = PyLong_AsLong(i);
|
if (PyDict_SetItem(o, i, exp) == 0)
|
||||||
else
|
return true;
|
||||||
return NULL;
|
}
|
||||||
return PyList_SetItem(o, j, exp) == 0;
|
if (PyObject_SetAttr(o, i, exp) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
atom_t s;
|
||||||
|
int n, i;
|
||||||
|
PL_get_name_arity(t, &s, &n);
|
||||||
|
PyObject *o = term_to_python(t, true, context, true);
|
||||||
|
if (PySequence_Check(o) && PySequence_Length(o) == n) {
|
||||||
|
for (i = 1; i <= n; i++) {
|
||||||
|
PyObject *p;
|
||||||
|
if (!PL_get_arg(i, t, arg)) {
|
||||||
|
PL_reset_term_refs(tail);
|
||||||
|
o = false;
|
||||||
|
p = Py_None;
|
||||||
|
}
|
||||||
|
if ((p = PySequence_GetItem(exp, i - 1)) == NULL)
|
||||||
|
p = Py_None;
|
||||||
|
else if (!python_assign(arg, p, NULL)) {
|
||||||
|
PL_reset_term_refs(tail);
|
||||||
|
o = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (PyDict_Check(i)) {
|
return true;
|
||||||
return PyDict_SetItem(o, i, exp) == 0;
|
|
||||||
}
|
|
||||||
return PyObject_SetAttr(o, i, exp) == 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PL_reset_term_refs(tail);
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
|
|
||||||
|
#ifndef PY4YAP_H
|
||||||
|
#define PY4YAP_H 1
|
||||||
|
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
/** @brief Prolog to Python library
|
/** @brief Prolog to Python library
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Please look at python.pl for more information, and to real.pl and real.c
|
* Please look at python.pl for more information, and to real.pl and real.c
|
||||||
* for related work.
|
* for related work.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef _XOPEN_SOURCE
|
#ifdef _XOPEN_SOURCE
|
||||||
#undef _XOPEN_SOURCE // python does its own thing
|
#undef _XOPEN_SOURCE // python does its own thing
|
||||||
@ -28,7 +31,6 @@
|
|||||||
#define I_API
|
#define I_API
|
||||||
#define O_API
|
#define O_API
|
||||||
|
|
||||||
|
|
||||||
#define PYTHON_H 1
|
#define PYTHON_H 1
|
||||||
|
|
||||||
PyObject *find_obj(PyObject *ob, term_t lhs, bool eval);
|
PyObject *find_obj(PyObject *ob, term_t lhs, bool eval);
|
||||||
@ -50,12 +52,15 @@ typedef struct s_mod_t {
|
|||||||
} Py_mod;
|
} Py_mod;
|
||||||
|
|
||||||
extern X_API YAP_Term pythonToYAP(PyObject *pVal);
|
extern X_API YAP_Term pythonToYAP(PyObject *pVal);
|
||||||
extern X_API PyObject *yap_to_python(YAP_Term t, bool eval, PyObject *o);
|
extern X_API PyObject *yap_to_python(YAP_Term t, bool eval, PyObject *o,
|
||||||
extern X_API PyObject *string_to_python( const char *s, bool eval, PyObject *p0);
|
bool cvt);
|
||||||
|
extern X_API PyObject *string_to_python(const char *s, bool eval, PyObject *p0);
|
||||||
typedef YAP_Arity arity_t;
|
typedef YAP_Arity arity_t;
|
||||||
|
|
||||||
extern atom_t ATOM_true, ATOM_false, ATOM_colon, ATOM_dot, ATOM_none, ATOM_t,
|
extern atom_t ATOM_true, ATOM_false, ATOM_colon, ATOM_dot, ATOM_none, ATOM_t,
|
||||||
ATOM_comma, ATOM_builtin, ATOM_V, ATOM_A, ATOM_self, ATOM_nil, ATOM_brackets, ATOM_curly_brackets;;
|
ATOM_comma, ATOM_builtin, ATOM_V, ATOM_A, ATOM_self, ATOM_nil,
|
||||||
|
ATOM_brackets, ATOM_curly_brackets;
|
||||||
|
;
|
||||||
|
|
||||||
extern functor_t FUNCTOR_dollar1, FUNCTOR_abs1, FUNCTOR_all1, FUNCTOR_any1,
|
extern functor_t FUNCTOR_dollar1, FUNCTOR_abs1, FUNCTOR_all1, FUNCTOR_any1,
|
||||||
FUNCTOR_bin1, FUNCTOR_brackets1, FUNCTOR_comma2, FUNCTOR_dir1,
|
FUNCTOR_bin1, FUNCTOR_brackets1, FUNCTOR_comma2, FUNCTOR_dir1,
|
||||||
@ -72,7 +77,7 @@ extern X_API PyObject *py_Yapex;
|
|||||||
extern X_API PyObject *py_Local;
|
extern X_API PyObject *py_Local;
|
||||||
extern X_API PyObject *py_Global;
|
extern X_API PyObject *py_Global;
|
||||||
extern X_API PyObject *py_Context;
|
extern X_API PyObject *py_Context;
|
||||||
extern PyObject *py_F2P;
|
extern PyObject *Py_f2p;
|
||||||
extern PyObject *py_Sys;
|
extern PyObject *py_Sys;
|
||||||
extern PyObject *py_ModDict;
|
extern PyObject *py_ModDict;
|
||||||
|
|
||||||
@ -133,20 +138,25 @@ static inline PyObject *atom_to_python_string(term_t t) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_CALL(rc, t, call) \
|
#define CHECK_CALL(rc, t, call) \
|
||||||
PyErr_Clear();\
|
PyErr_Clear(); \
|
||||||
rc = call; \
|
rc = call; \
|
||||||
if (rc == NULL || PyErr_Occurred()) {\
|
if (rc == NULL || PyErr_Occurred()) { \
|
||||||
YE(t,__LINE__,__FILE__,__FUNCTION__);\
|
YE(t, __LINE__, __FILE__, __FUNCTION__); \
|
||||||
PyErr_Print(); PyErr_Clear();\
|
PyErr_Print(); \
|
||||||
}
|
PyErr_Clear(); \
|
||||||
|
}
|
||||||
#define CHECKNULL(t,rc) (rc != NULL ? rc : YE(t,__LINE__,__FILE__,__FUNCTION__) )
|
|
||||||
#define AOK(rc, err) { if (!rc) YEM( #rc ,__LINE__,__FILE__,__FUNCTION__); }
|
|
||||||
|
|
||||||
|
#define CHECKNULL(t, rc) \
|
||||||
|
(rc != NULL ? rc : YE(t, __LINE__, __FILE__, __FUNCTION__))
|
||||||
|
#define AOK(rc, err) \
|
||||||
|
{ \
|
||||||
|
if (!rc) \
|
||||||
|
YEM(#rc, __LINE__, __FILE__, __FUNCTION__); \
|
||||||
|
}
|
||||||
|
|
||||||
extern PyObject *YE(term_t t, int line, const char *file, const char *code);
|
extern PyObject *YE(term_t t, int line, const char *file, const char *code);
|
||||||
extern void YEM( const char *ex, int line, const char *file, const char *code);
|
extern void YEM(const char *ex, int line, const char *file, const char *code);
|
||||||
extern void pyErrorHandler__(int line, const char *file, const char *code);
|
extern void pyErrorHandler__(int line, const char *file, const char *code);
|
||||||
|
|
||||||
#define pyErrorHandler() \
|
#define pyErrorHandler() \
|
||||||
@ -167,10 +177,11 @@ extern void pyErrorHandler__(int line, const char *file, const char *code);
|
|||||||
}
|
}
|
||||||
// #define pyErrorAndReturn( x, y ) return x
|
// #define pyErrorAndReturn( x, y ) return x
|
||||||
|
|
||||||
extern PyObject *compound_to_pyeval(term_t t, PyObject *context);
|
extern PyObject *compound_to_pyeval(term_t t, PyObject *context, bool cvt);
|
||||||
extern PyObject *compound_to_pytree(term_t t, PyObject *context);
|
extern PyObject *compound_to_pytree(term_t t, PyObject *context, bool cvt);
|
||||||
|
|
||||||
extern PyObject *term_to_python(term_t t, bool eval, PyObject *contextxs);
|
extern PyObject *term_to_python(term_t t, bool eval, PyObject *contextxs,
|
||||||
|
bool eval_atom);
|
||||||
|
|
||||||
extern PyObject *term_to_nametuple(const char *s, arity_t arity, PyObject *);
|
extern PyObject *term_to_nametuple(const char *s, arity_t arity, PyObject *);
|
||||||
|
|
||||||
@ -197,9 +208,12 @@ extern PyObject *PythonLookup(const char *s, PyObject *o);
|
|||||||
|
|
||||||
extern PyObject *PythonLookupSpecial(const char *s);
|
extern PyObject *PythonLookupSpecial(const char *s);
|
||||||
|
|
||||||
#define YAPPy_ThrowError(id, inp, ...) \
|
#define YAPPy_ThrowError(id, inp, ...) \
|
||||||
YAPPy_ThrowError__(__FILE__, __FUNCTION__, __LINE__, id, inp, __VA_ARGS__)
|
YAPPy_ThrowError__(__FILE__, __FUNCTION__, __LINE__, id, inp, __VA_ARGS__)
|
||||||
|
|
||||||
|
extern void YAPPy_ThrowError__(const char *file, const char *function,
|
||||||
|
int lineno, yap_error_number type, term_t where,
|
||||||
|
...);
|
||||||
|
#endif
|
||||||
|
|
||||||
extern void YAPPy_ThrowError__(const char *file, const char *function, int lineno,
|
|
||||||
yap_error_number type, term_t where, ...);
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -92,21 +92,23 @@ PyObject *PythonLookup(const char *s, PyObject *oo) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *find_obj(PyObject *ob, term_t l, bool eval) {
|
PyObject *
|
||||||
|
|
||||||
|
find_obj(PyObject *ob, term_t l, bool eval) {
|
||||||
YAP_Term hd, yt;
|
YAP_Term hd, yt;
|
||||||
|
|
||||||
py_Context = NULL;
|
py_Context = NULL;
|
||||||
yt = YAP_GetFromSlot(l);
|
yt = YAP_GetFromSlot(l);
|
||||||
|
// Yap_DebugPlWriteln(yt);
|
||||||
while (YAP_IsPairTerm(yt)) {
|
while (YAP_IsPairTerm(yt)) {
|
||||||
hd = YAP_HeadOfTerm(yt);
|
hd = YAP_HeadOfTerm(yt);
|
||||||
ob = yap_to_python(hd, true, ob);
|
yt = YAP_TailOfTerm(yt);
|
||||||
ob = CHECKNULL(yt, ob);
|
YAP_PutInSlot(l, yt);
|
||||||
|
ob = yap_to_python(hd, true, ob, false);
|
||||||
if (!ob) {
|
if (!ob) {
|
||||||
return Py_None;
|
return Py_None;
|
||||||
}
|
}
|
||||||
yt = YAP_TailOfTerm(yt);
|
|
||||||
}
|
}
|
||||||
YAP_PutInSlot(l, yt);
|
|
||||||
return ob;
|
return ob;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +124,7 @@ static PyObject *bip_abs(term_t t) {
|
|||||||
PyObject *pVal, *nVal;
|
PyObject *pVal, *nVal;
|
||||||
|
|
||||||
AOK(PL_get_arg(1, t, t), NULL);
|
AOK(PL_get_arg(1, t, t), NULL);
|
||||||
pVal = term_to_python(t, true, NULL);
|
pVal = term_to_python(t, true, NULL, true);
|
||||||
pVal = CHECKNULL(t, pVal);
|
pVal = CHECKNULL(t, pVal);
|
||||||
nVal = PyNumber_Absolute(pVal);
|
nVal = PyNumber_Absolute(pVal);
|
||||||
Py_DecRef(pVal);
|
Py_DecRef(pVal);
|
||||||
@ -143,7 +145,7 @@ static PyObject *bip_all(term_t t) {
|
|||||||
int cmp;
|
int cmp;
|
||||||
|
|
||||||
AOK(PL_get_arg(1, t, t), NULL);
|
AOK(PL_get_arg(1, t, t), NULL);
|
||||||
(v = term_to_python(t, true, NULL));
|
(v = term_to_python(t, true, NULL, true));
|
||||||
v = CHECKNULL(t, v);
|
v = CHECKNULL(t, v);
|
||||||
it = PyObject_GetIter(v);
|
it = PyObject_GetIter(v);
|
||||||
if (CHECKNULL(t, it) == NULL)
|
if (CHECKNULL(t, it) == NULL)
|
||||||
@ -190,7 +192,7 @@ static PyObject *bip_any(term_t t) {
|
|||||||
int cmp;
|
int cmp;
|
||||||
|
|
||||||
AOK(PL_get_arg(1, t, t), NULL);
|
AOK(PL_get_arg(1, t, t), NULL);
|
||||||
v = term_to_python(t, true, NULL);
|
v = term_to_python(t, true, NULL, true);
|
||||||
it = PyObject_GetIter(v);
|
it = PyObject_GetIter(v);
|
||||||
if (CHECKNULL(t, it) == NULL)
|
if (CHECKNULL(t, it) == NULL)
|
||||||
return Py_None;
|
return Py_None;
|
||||||
@ -225,7 +227,7 @@ static PyObject *bip_bin(term_t t) {
|
|||||||
PyObject *v;
|
PyObject *v;
|
||||||
|
|
||||||
AOK(PL_get_arg(1, t, t), NULL);
|
AOK(PL_get_arg(1, t, t), NULL);
|
||||||
v = term_to_python(t, true, NULL);
|
v = term_to_python(t, true, NULL, true);
|
||||||
return PyNumber_ToBase(v, 2);
|
return PyNumber_ToBase(v, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,7 +235,7 @@ static PyObject *bip_float(term_t t, bool eval) {
|
|||||||
PyObject *pVal, *o;
|
PyObject *pVal, *o;
|
||||||
|
|
||||||
AOK(PL_get_arg(1, t, t), NULL);
|
AOK(PL_get_arg(1, t, t), NULL);
|
||||||
pVal = term_to_python(t, eval, NULL);
|
pVal = term_to_python(t, eval, NULL, eval);
|
||||||
if (PyLong_Check(pVal)) {
|
if (PyLong_Check(pVal)) {
|
||||||
o = PyFloat_FromDouble(PyLong_AsLong(pVal));
|
o = PyFloat_FromDouble(PyLong_AsLong(pVal));
|
||||||
#if PY_MAJOR_VERSION < 3
|
#if PY_MAJOR_VERSION < 3
|
||||||
@ -252,7 +254,7 @@ static PyObject *bip_int(term_t t) {
|
|||||||
PyObject *pVal, *o;
|
PyObject *pVal, *o;
|
||||||
|
|
||||||
AOK(PL_get_arg(1, t, t), NULL);
|
AOK(PL_get_arg(1, t, t), NULL);
|
||||||
pVal = term_to_python(t, true, NULL);
|
pVal = term_to_python(t, true, NULL, true);
|
||||||
#if PY_MAJOR_VERSION < 3
|
#if PY_MAJOR_VERSION < 3
|
||||||
if (PyLong_Check(pVal)) {
|
if (PyLong_Check(pVal)) {
|
||||||
o = PyInt_FromLong(PyLong_AsLong(pVal));
|
o = PyInt_FromLong(PyLong_AsLong(pVal));
|
||||||
@ -278,7 +280,7 @@ static PyObject *bip_long(term_t t) {
|
|||||||
PyObject *pVal, *o;
|
PyObject *pVal, *o;
|
||||||
|
|
||||||
AOK(PL_get_arg(1, t, t), NULL);
|
AOK(PL_get_arg(1, t, t), NULL);
|
||||||
pVal = term_to_python(t, true, NULL);
|
pVal = term_to_python(t, true, NULL, true);
|
||||||
if (PyLong_Check(pVal)) {
|
if (PyLong_Check(pVal)) {
|
||||||
return pVal;
|
return pVal;
|
||||||
#if PY_MAJOR_VERSION < 3
|
#if PY_MAJOR_VERSION < 3
|
||||||
@ -297,7 +299,7 @@ static PyObject *bip_iter(term_t t) {
|
|||||||
PyObject *v;
|
PyObject *v;
|
||||||
|
|
||||||
AOK(PL_get_arg(1, t, t), NULL);
|
AOK(PL_get_arg(1, t, t), NULL);
|
||||||
v = term_to_python(t, true, NULL);
|
v = term_to_python(t, true, NULL, true);
|
||||||
return PyObject_GetIter(v);
|
return PyObject_GetIter(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +308,7 @@ static PyObject *bip_ord(term_t t) {
|
|||||||
Py_ssize_t size;
|
Py_ssize_t size;
|
||||||
|
|
||||||
AOK(PL_get_arg(1, t, t), NULL);
|
AOK(PL_get_arg(1, t, t), NULL);
|
||||||
pVal = term_to_python(t, true, NULL);
|
pVal = term_to_python(t, true, NULL, true);
|
||||||
if (PyUnicode_Check(pVal)) {
|
if (PyUnicode_Check(pVal)) {
|
||||||
#if PY_MAJOR_VERSION < 3
|
#if PY_MAJOR_VERSION < 3
|
||||||
size = PyUnicode_GET_SIZE(pVal);
|
size = PyUnicode_GET_SIZE(pVal);
|
||||||
@ -349,7 +351,7 @@ static PyObject *bip_sum(term_t t) {
|
|||||||
PyObject *temp, *item, *iter;
|
PyObject *temp, *item, *iter;
|
||||||
|
|
||||||
AOK(PL_get_arg(1, t, t), NULL);
|
AOK(PL_get_arg(1, t, t), NULL);
|
||||||
seq = term_to_python(t, true, NULL);
|
seq = term_to_python(t, true, NULL, true);
|
||||||
iter = PyObject_GetIter(seq);
|
iter = PyObject_GetIter(seq);
|
||||||
if (iter == NULL)
|
if (iter == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -517,7 +519,7 @@ static long get_int(term_t arg, bool eval) {
|
|||||||
long low;
|
long low;
|
||||||
|
|
||||||
if (!PL_get_long(arg, &low)) {
|
if (!PL_get_long(arg, &low)) {
|
||||||
PyObject *low = term_to_python(arg, eval, NULL);
|
PyObject *low = term_to_python(arg, eval, NULL, eval);
|
||||||
if (PyLong_Check(low)) {
|
if (PyLong_Check(low)) {
|
||||||
return PyLong_AsLong(low);
|
return PyLong_AsLong(low);
|
||||||
#if PY_MAJOR_VERSION < 3
|
#if PY_MAJOR_VERSION < 3
|
||||||
@ -696,546 +698,360 @@ static PyObject *structseq_repr(PyObject *iobj) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PyObject *term_to_nametuple(const char *s, arity_t arity, PyObject *tuple) {
|
static bool
|
||||||
PyObject *o;
|
legal_symbol( const char *s)
|
||||||
#if PY_MAJOR_VERSION >= 3
|
{
|
||||||
PyTypeObject *typp;
|
int ch;
|
||||||
PyObject *key = PyUnicode_FromString(s);
|
while(((ch = *s++) != '\0')) {
|
||||||
if (py_F2P && PyDict_Contains(py_F2P, key)) {
|
if (isalnum(ch) || ch == '_')
|
||||||
typp = (PyTypeObject *)PyDict_GetItem(py_F2P, key);
|
continue;
|
||||||
Py_INCREF(typp);
|
return false;
|
||||||
} else {
|
}
|
||||||
|
return true;
|
||||||
typp = calloc(sizeof(PyTypeObject), 1);
|
|
||||||
PyStructSequence_Desc *desc = calloc(sizeof(PyStructSequence_Desc), 1);
|
|
||||||
desc->name = PyMem_Malloc(strlen(s) + 1);
|
|
||||||
strcpy(desc->name, s);
|
|
||||||
Py_DECREF(key);
|
|
||||||
desc->doc = "YAPTerm";
|
|
||||||
desc->fields = pnull;
|
|
||||||
desc->n_in_sequence = arity;
|
|
||||||
if (PyStructSequence_InitType2(typp, desc) < 0)
|
|
||||||
return NULL;
|
|
||||||
// typp->tp_flags &= ~Py_TPFLAGS_HEAPTYPE;
|
|
||||||
// typp->tp_flags &= ~Py_TPFLAGS_HAVE_GC;
|
|
||||||
// typp->tp_str = structseq_str;
|
|
||||||
typp->tp_repr = structseq_repr;
|
|
||||||
// typp = PyStructSequence_NewType(desc);
|
|
||||||
// don't do this: we cannot add a type as an atribute.
|
|
||||||
// PyModule_AddGObject(py_Main, s, (PyObject *)typp);
|
|
||||||
if (py_F2P)
|
|
||||||
PyDict_SetItem(py_F2P, key, (PyObject *)typp);
|
|
||||||
Py_INCREF(typp);
|
|
||||||
}
|
|
||||||
o = PyStructSequence_New(typp);
|
|
||||||
Py_INCREF(typp);
|
|
||||||
arity_t i;
|
|
||||||
for (i = 0; i < arity; i++) {
|
|
||||||
PyObject *pArg = PyTuple_GET_ITEM(tuple, i);
|
|
||||||
Py_INCREF(pArg);
|
|
||||||
if (pArg)
|
|
||||||
PyStructSequence_SET_ITEM(o, i, pArg);
|
|
||||||
// PyObject_Print(pArg,stderr,0);fputc('\n',stderr);
|
|
||||||
}
|
|
||||||
//((PyStructSequence *)o)->ob_base.ob_size = arity;
|
|
||||||
// PyObject_Print(o,stderr,0);fputc('\n',stderr);
|
|
||||||
return o;
|
|
||||||
#else
|
|
||||||
PyObject *o1;
|
|
||||||
o1 = PyTuple_New(2);
|
|
||||||
PyTuple_SET_ITEM(o1, 0, PyUnicode_FromString(s));
|
|
||||||
PyTuple_SET_ITEM(o1, 1, tuple);
|
|
||||||
return o1;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *bip_range(term_t t) {
|
PyObject *term_to_nametuple(const char *s, arity_t arity, PyObject *tuple) {
|
||||||
long ilow = 0, ihigh = 0, istep = 1;
|
PyObject *o, *d = NULL;
|
||||||
long bign;
|
if (legal_symbol(s)) {
|
||||||
Py_ssize_t i, n;
|
PyTypeObject *typp;
|
||||||
int arity;
|
PyObject *key = PyUnicode_FromString(s);
|
||||||
atom_t name;
|
if (Py_f2p && (d = PyList_GetItem(Py_f2p, arity)) &&
|
||||||
term_t arg = PL_new_term_ref();
|
PyDict_Contains(d, key)) {
|
||||||
|
typp = (PyTypeObject *) PyDict_GetItem(d, key);
|
||||||
|
Py_INCREF(typp);
|
||||||
|
} else {
|
||||||
|
typp = calloc(sizeof(PyTypeObject), 1);
|
||||||
|
PyStructSequence_Desc *desc = calloc(sizeof(PyStructSequence_Desc), 1);
|
||||||
|
desc->name = PyMem_Malloc(strlen(s) + 1);
|
||||||
|
strcpy(desc->name, s);
|
||||||
|
desc->doc = "YAPTerm";
|
||||||
|
desc->fields = pnull;
|
||||||
|
desc->n_in_sequence = arity;
|
||||||
|
if (PyStructSequence_InitType2(typp, desc) < 0)
|
||||||
|
return NULL;
|
||||||
|
// typp->tp_flags &= ~Py_TPFLAGS_HEAPTYPE;
|
||||||
|
// typp->tp_flags &= ~Py_TPFLAGS_HAVE_GC;
|
||||||
|
// typp->tp_str = structseq_str;
|
||||||
|
typp->tp_repr = structseq_repr;
|
||||||
|
// typp = PyStructSequence_NewType(desc);
|
||||||
|
// don't do this: we cannot add a type as an atribute.
|
||||||
|
// PyModule_AddGObject(py_Main, s, (PyObject *)typp);
|
||||||
|
if (d && !PyDict_Contains(d, key))
|
||||||
|
PyDict_SetItem(d, key, (PyObject *) typp);
|
||||||
|
Py_DECREF(key);
|
||||||
|
Py_INCREF(typp);
|
||||||
|
}
|
||||||
|
o = PyStructSequence_New(typp);
|
||||||
|
Py_INCREF(typp);
|
||||||
|
arity_t i;
|
||||||
|
for (i = 0; i < arity; i++) {
|
||||||
|
PyObject *pArg = PyTuple_GET_ITEM(tuple, i);
|
||||||
|
Py_INCREF(pArg);
|
||||||
|
if (pArg)
|
||||||
|
PyStructSequence_SET_ITEM(o, i, pArg);
|
||||||
|
// PyObject_Print(pArg,stderr,0);fputc('\n',stderr);
|
||||||
|
}
|
||||||
|
//((PyStructSequence *)o)->ob_base.ob_size = arity;
|
||||||
|
// PyObject_Print(o,stderr,0);fputc('\n',stderr);
|
||||||
|
return o;
|
||||||
|
} else {
|
||||||
|
PyObject *o1;
|
||||||
|
o1 = PyTuple_New(2);
|
||||||
|
PyTuple_SET_ITEM(o1, 0, PyUnicode_FromString(s));
|
||||||
|
PyTuple_SET_ITEM(o1, 1, tuple);
|
||||||
|
return o1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PyObject *v;
|
static PyObject *bip_range(term_t t) {
|
||||||
|
long ilow = 0, ihigh = 0, istep = 1;
|
||||||
|
long bign;
|
||||||
|
Py_ssize_t i, n;
|
||||||
|
int arity;
|
||||||
|
atom_t name;
|
||||||
|
term_t arg = PL_new_term_ref();
|
||||||
|
|
||||||
if (!PL_get_name_arity(t, &name, &arity))
|
PyObject *v;
|
||||||
return NULL;
|
|
||||||
AOK(PL_get_arg(1, t, arg), NULL);
|
|
||||||
ilow = get_int(arg, true);
|
|
||||||
if (arity == 1) {
|
|
||||||
ihigh = ilow;
|
|
||||||
ilow = 0;
|
|
||||||
} else {
|
|
||||||
AOK(PL_get_arg(2, t, arg), NULL);
|
|
||||||
ihigh = get_int(arg, true);
|
|
||||||
if (arity == 3) {
|
|
||||||
AOK(PL_get_arg(3, t, arg), NULL);
|
|
||||||
istep = get_int(arg, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (istep == 0) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "range() step argument must not be zero");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (istep > 0)
|
|
||||||
bign = get_len_of_range(ilow, ihigh, istep);
|
|
||||||
else
|
|
||||||
bign = get_len_of_range(ihigh, ilow, -istep);
|
|
||||||
n = (Py_ssize_t)bign;
|
|
||||||
AOK(((bign >= 0 && (long)n == bign) || "range() result has too many items"),
|
|
||||||
NULL);
|
|
||||||
v = PyList_New(n);
|
|
||||||
|
|
||||||
if (v == NULL)
|
if (!PL_get_name_arity(t, &name, &arity))
|
||||||
return Py_None;
|
return NULL;
|
||||||
for (i = 0; i < n; i++) {
|
AOK(PL_get_arg(1, t, arg), NULL);
|
||||||
|
ilow = get_int(arg, true);
|
||||||
|
if (arity == 1) {
|
||||||
|
ihigh = ilow;
|
||||||
|
ilow = 0;
|
||||||
|
} else {
|
||||||
|
AOK(PL_get_arg(2, t, arg), NULL);
|
||||||
|
ihigh = get_int(arg, true);
|
||||||
|
if (arity == 3) {
|
||||||
|
AOK(PL_get_arg(3, t, arg), NULL);
|
||||||
|
istep = get_int(arg, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (istep == 0) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "range() step argument must not be zero");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (istep > 0)
|
||||||
|
bign = get_len_of_range(ilow, ihigh, istep);
|
||||||
|
else
|
||||||
|
bign = get_len_of_range(ihigh, ilow, -istep);
|
||||||
|
n = (Py_ssize_t)bign;
|
||||||
|
AOK(((bign >= 0 && (long)n == bign) || "range() result has too many items"),
|
||||||
|
NULL);
|
||||||
|
v = PyList_New(n);
|
||||||
|
|
||||||
|
if (v == NULL)
|
||||||
|
return Py_None;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
#if PY_MAJOR_VERSION < 3
|
#if PY_MAJOR_VERSION < 3
|
||||||
PyObject *w = PyInt_FromLong(ilow);
|
PyObject *w = PyInt_FromLong(ilow);
|
||||||
#else
|
#else
|
||||||
PyObject *w = PyLong_FromLong(ilow);
|
PyObject *w = PyLong_FromLong(ilow);
|
||||||
#endif
|
#endif
|
||||||
if (w == NULL) {
|
if (w == NULL) {
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyList_SET_ITEM(v, i, w);
|
PyList_SET_ITEM(v, i, w);
|
||||||
Py_INCREF(w);
|
Py_INCREF(w);
|
||||||
ilow += istep;
|
ilow += istep;
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool copy_to_dictionary(PyObject *dict, term_t targ, term_t taux,
|
PyObject *compound_to_pytree(term_t t, PyObject *context, bool cvt) {
|
||||||
bool eval) {
|
PyObject *o = py_Main;
|
||||||
PyObject *lhs, *rhs;
|
functor_t fun;
|
||||||
term_t tleft = PL_new_term_ref(), tright = PL_new_term_ref();
|
atom_t name;
|
||||||
|
int arity;
|
||||||
|
|
||||||
functor_t fun;
|
o = find_obj(context, t, false);
|
||||||
|
AOK(PL_get_name_arity(t, &name, &arity), NULL);
|
||||||
|
if (arity == 0)
|
||||||
|
return term_to_python(t, false, o, false);
|
||||||
|
AOK(PL_get_functor(t, &fun), NULL);
|
||||||
|
if (!arity) {
|
||||||
|
char *s = NULL;
|
||||||
|
|
||||||
AOK(PL_get_functor(targ, &fun), false);
|
AOK(!PL_get_atom_chars(t, &s), NULL);
|
||||||
while (fun == FUNCTOR_comma2) {
|
// this should never happen
|
||||||
AOK(PL_get_arg(1, targ, tleft), false);
|
return term_to_python(t, false, o, cvt);
|
||||||
if (!copy_to_dictionary(dict, tleft, taux, eval))
|
} else {
|
||||||
return false;
|
const char *s;
|
||||||
AOK(PL_get_arg(2, targ, targ), false);
|
if (!(s = PL_atom_chars(name))) {
|
||||||
return copy_to_dictionary(dict, tright, taux, eval);
|
return NULL;
|
||||||
}
|
}
|
||||||
// PyObject_Print(dict, stderr, 0); fprintf(stderr,"\n");
|
term_t tleft;
|
||||||
// Py_DECREF(lhs);
|
int i;
|
||||||
// Py_DECREF(rhs);
|
|
||||||
|
|
||||||
AOK(PL_get_arg(1, targ, tleft), false);
|
PyObject *out = PyTuple_New(arity);
|
||||||
lhs = atom_to_python_string(tleft);
|
DebugPrintf("Tuple %p\n", o);
|
||||||
if (lhs == NULL) {
|
tleft = PL_new_term_ref();
|
||||||
return FALSE;
|
for (i = 0; i < arity; i++) {
|
||||||
}
|
PyObject *pArg;
|
||||||
AOK(PL_get_arg(2, targ, tright), false);
|
AOK(PL_get_arg(i + 1, t, tleft), NULL);
|
||||||
rhs = term_to_python(tright, eval, NULL);
|
pArg = term_to_python(tleft, false, NULL, cvt);
|
||||||
if (rhs == NULL) {
|
if (pArg) {
|
||||||
PyErr_Print();
|
/* pArg reference stolen here: */
|
||||||
return false;
|
PyTuple_SET_ITEM(out, i, pArg);
|
||||||
}
|
Py_INCREF(pArg);
|
||||||
return PyDict_SetItem(dict, lhs, rhs) >= 0;
|
}
|
||||||
// PyObject_Print(dict, stderr, 0); fprintf(stderr,"\n");
|
}
|
||||||
// Py_DECREF(lhs);
|
if (CHECKNULL(t, out) == NULL) {
|
||||||
// Py_DECREF(rhs);
|
PyErr_Print();
|
||||||
}
|
return NULL;
|
||||||
|
}
|
||||||
|
PyObject *c = lookupPySymbol(s, o, NULL);
|
||||||
|
|
||||||
PyObject *compound_to_data(term_t t, PyObject *o, functor_t fun, bool exec) {
|
if (c && PyCallable_Check(c)) {
|
||||||
atom_t name;
|
PyObject *n = PyTuple_New(arity);
|
||||||
int len;
|
PyTuple_SET_ITEM(n, 0, c);
|
||||||
|
PyTuple_SET_ITEM(n, 1, out);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
return term_to_nametuple(s, arity, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AOK(PL_get_name_arity(t, &name, &len), o);
|
PyObject *compound_to_pyeval(term_t t, PyObject *context, bool cvt) {
|
||||||
|
PyObject *o = NULL;
|
||||||
|
atom_t name;
|
||||||
|
int arity;
|
||||||
|
functor_t fun;
|
||||||
|
PyObject *d = NULL;
|
||||||
|
|
||||||
if (fun == FUNCTOR_pointer1) {
|
o = find_obj(context, t, true);
|
||||||
void *ptr;
|
AOK(PL_get_name_arity(t, &name, &arity), NULL);
|
||||||
|
if (arity == 0) {
|
||||||
|
return term_to_python(t, true, o, cvt);
|
||||||
|
}
|
||||||
|
if (!PL_get_functor(t, &fun))
|
||||||
|
return NULL;
|
||||||
|
if (fun == FUNCTOR_abs1) {
|
||||||
|
return bip_abs(t);
|
||||||
|
} else if (fun == FUNCTOR_all1) {
|
||||||
|
return bip_all(t);
|
||||||
|
} else if (fun == FUNCTOR_any1) {
|
||||||
|
return bip_any(t);
|
||||||
|
} else if (fun == FUNCTOR_bin1) {
|
||||||
|
return bip_bin(t);
|
||||||
|
} else if (fun == FUNCTOR_ord1) {
|
||||||
|
return bip_ord(t);
|
||||||
|
} else if (fun == FUNCTOR_int1) {
|
||||||
|
return bip_int(t);
|
||||||
|
} else if (fun == FUNCTOR_long1) {
|
||||||
|
return bip_long(t);
|
||||||
|
} else if (fun == FUNCTOR_float1) {
|
||||||
|
return bip_float(t, true);
|
||||||
|
} else if (fun == FUNCTOR_iter1) {
|
||||||
|
return bip_iter(t);
|
||||||
|
} else if (fun == FUNCTOR_range1 || fun == FUNCTOR_range2 ||
|
||||||
|
fun == FUNCTOR_range3) {
|
||||||
|
return bip_range(t);
|
||||||
|
} else if (fun == FUNCTOR_sum1) {
|
||||||
|
return bip_sum(t);
|
||||||
|
}
|
||||||
|
if (fun == FUNCTOR_len1) {
|
||||||
|
term_t targ = PL_new_term_ref();
|
||||||
|
PyObject *ptr;
|
||||||
|
|
||||||
AOK(PL_get_arg(1, t, t), NULL);
|
AOK(PL_get_arg(1, t, targ), NULL);
|
||||||
AOK(PL_get_pointer(t, &ptr), NULL)
|
ptr = term_to_python(targ, true, NULL, true);
|
||||||
/* return __main__,s */
|
return PyLong_FromLong(PyObject_Length(ptr));
|
||||||
return (PyObject *)ptr;
|
}
|
||||||
}
|
|
||||||
if (name == ATOM_t) {
|
|
||||||
term_t targ = PL_new_term_ref();
|
|
||||||
PyObject *out;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
out = PyTuple_New(len);
|
if (fun == FUNCTOR_div2) {
|
||||||
DebugPrintf("Tuple %p\n", out);
|
term_t targ = PL_new_term_ref();
|
||||||
|
PyObject *lhs, *rhs;
|
||||||
|
|
||||||
if (!out)
|
AOK(PL_get_arg(1, t, targ), NULL);
|
||||||
return NULL;
|
lhs = term_to_python(targ, true, NULL, false);
|
||||||
for (i = 0; i < len; i++) {
|
if (!PyNumber_Check(lhs))
|
||||||
AOK(PL_get_arg(i + 1, t, targ), NULL);
|
return NULL;
|
||||||
PyErr_Clear();
|
AOK(PL_get_arg(2, t, targ), NULL);
|
||||||
PyObject *oa = term_to_python(targ, true, o);
|
rhs = term_to_python(targ, true, NULL, false);
|
||||||
bool rc = PyTuple_SET_ITEM(out, i, oa) == 0;
|
if (!PyNumber_Check(rhs))
|
||||||
if (rc) {
|
return NULL;
|
||||||
PyErr_Print();
|
|
||||||
}
|
|
||||||
Py_INCREF(oa);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
} else if (fun == FUNCTOR_div2) {
|
|
||||||
term_t targ = PL_new_term_ref();
|
|
||||||
PyObject *lhs, *rhs;
|
|
||||||
|
|
||||||
AOK(PL_get_arg(1, t, targ), NULL);
|
|
||||||
lhs = term_to_python(targ, true, NULL);
|
|
||||||
if (!PyNumber_Check(lhs))
|
|
||||||
return NULL;
|
|
||||||
AOK(PL_get_arg(2, t, targ), NULL);
|
|
||||||
rhs = term_to_python(targ, true, NULL);
|
|
||||||
if (!PyNumber_Check(rhs))
|
|
||||||
return NULL;
|
|
||||||
#if PY_MAJOR_VERSION < 3
|
#if PY_MAJOR_VERSION < 3
|
||||||
return PyNumber_Divide(lhs, rhs);
|
return PyNumber_Divide(lhs, rhs);
|
||||||
#else
|
#else
|
||||||
return PyNumber_TrueDivide(lhs, rhs);
|
return PyNumber_TrueDivide(lhs, rhs);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (fun == FUNCTOR_sqbrackets2) {
|
if (fun == FUNCTOR_dir1) {
|
||||||
term_t targ = PL_new_term_ref(), trhs = PL_new_term_ref();
|
term_t targ = PL_new_term_ref();
|
||||||
PyObject *v;
|
PyObject *ptr;
|
||||||
Py_ssize_t min, max;
|
|
||||||
AOK(PL_get_arg(2, t, targ), NULL);
|
|
||||||
v = term_to_python(targ, true, o);
|
|
||||||
|
|
||||||
AOK(PL_get_arg(1, t, targ), NULL);
|
AOK(PL_get_arg(1, t, targ), NULL);
|
||||||
AOK(PL_get_list(targ, trhs, targ), NULL);
|
ptr = term_to_python(targ, true, NULL, true);
|
||||||
if (PL_is_functor(trhs, FUNCTOR_colon2)) {
|
return PyObject_Dir(ptr);
|
||||||
if (!PySequence_Check(v))
|
|
||||||
return NULL;
|
}
|
||||||
min = get_p_int(term_to_python(targ, true, NULL), 0);
|
|
||||||
AOK(PL_get_arg(1, trhs, targ), NULL);
|
else if (fun == FUNCTOR_plus2) {
|
||||||
if (PL_is_functor(targ, FUNCTOR_colon2)) {
|
term_t targ = PL_new_term_ref();
|
||||||
return NULL;
|
PyObject *lhs, *rhs;
|
||||||
}
|
|
||||||
max = get_p_int(term_to_python(targ, true, o), PyObject_Size(v));
|
if (!PL_get_arg(1, t, targ))
|
||||||
return PySequence_GetSlice(v, min, max);
|
return NULL;
|
||||||
} else {
|
lhs = term_to_python(targ, true, NULL, true);
|
||||||
PyObject *ip = term_to_python(trhs, true, o);
|
AOK(PL_get_arg(2, t, targ), NULL);
|
||||||
if (PySequence_Check(v)) {
|
rhs = term_to_python(targ, true, NULL, true);
|
||||||
|
if (PySequence_Check(lhs) && PySequence_Check(rhs)) {
|
||||||
|
return PySequence_Concat(lhs, rhs);
|
||||||
|
}
|
||||||
|
if (!PyNumber_Check(lhs))
|
||||||
|
return NULL;
|
||||||
|
if (!PyNumber_Check(rhs))
|
||||||
|
return NULL;
|
||||||
|
return PyNumber_Add(lhs, rhs);
|
||||||
|
} else if (fun == FUNCTOR_sub2) {
|
||||||
|
term_t targ = PL_new_term_ref();
|
||||||
|
PyObject *lhs, *rhs;
|
||||||
|
|
||||||
|
if (!PL_get_arg(1, t, targ))
|
||||||
|
return NULL;
|
||||||
|
lhs = term_to_python(targ, true, NULL, true);
|
||||||
|
if (!PyNumber_Check(lhs))
|
||||||
|
return NULL;
|
||||||
|
if (!PL_get_arg(2, t, targ))
|
||||||
|
return NULL;
|
||||||
|
rhs = term_to_python(targ, true, NULL, true);
|
||||||
|
if (!PyNumber_Check(rhs))
|
||||||
|
return NULL;
|
||||||
|
return PyNumber_Subtract(lhs, rhs);
|
||||||
|
} else if (fun == FUNCTOR_mul2) {
|
||||||
|
term_t targ = PL_new_term_ref();
|
||||||
|
PyObject *lhs, *rhs;
|
||||||
|
|
||||||
|
AOK(PL_get_arg(1, t, targ), NULL);
|
||||||
|
(lhs = term_to_python(targ, true, NULL, true));
|
||||||
|
CHECKNULL(targ, lhs);
|
||||||
|
AOK(PL_get_arg(2, t, targ), NULL);
|
||||||
|
(rhs = term_to_python(targ, true, NULL, true));
|
||||||
|
CHECKNULL(targ, rhs);
|
||||||
|
if (PySequence_Check(lhs) && (
|
||||||
#if PY_MAJOR_VERSION < 3
|
#if PY_MAJOR_VERSION < 3
|
||||||
if (PyLong_Check(ip) {
|
PyInt_Check(rhs) ||
|
||||||
min = PyLong_AsLong(ip);
|
|
||||||
} else if (PyInt_Check(ip) {
|
|
||||||
min = PyInt_asInt(ip);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (PyLong_Check(ip)) {
|
|
||||||
PyObject *o = PySequence_GetItem(v, PyLong_AsLong(ip));
|
|
||||||
if (o == NULL)
|
|
||||||
o = Py_None;
|
|
||||||
if (CHECKNULL(t, o) == NULL)
|
|
||||||
return NULL;
|
|
||||||
Py_INCREF(o);
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
} else {
|
PyLong_Check(rhs))) {
|
||||||
o = PyObject_GetItem(v, ip);
|
return PySequence_Repeat(lhs, get_p_int(rhs, 0));
|
||||||
if (o == NULL)
|
}
|
||||||
o = Py_None;
|
if (!PyNumber_Check(lhs) + !PyNumber_Check(rhs))
|
||||||
Py_INCREF(o);
|
return NULL;
|
||||||
return o;
|
return PyNumber_Multiply(lhs, rhs);
|
||||||
}
|
}
|
||||||
}
|
if (!arity) {
|
||||||
}
|
char *s = NULL;
|
||||||
if (fun == FUNCTOR_dollar1) {
|
PyObject *pValue;
|
||||||
char *s = NULL;
|
|
||||||
term_t targ = PL_new_term_ref();
|
|
||||||
AOK(PL_get_arg(1, t, targ), NULL);
|
|
||||||
AOK(PL_get_atom_chars(targ, &s), NULL);
|
|
||||||
/* return __main__,s */
|
|
||||||
PyObject *o = PyObject_GetAttrString(py_Main, s);
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
if (fun == FUNCTOR_brackets1) {
|
|
||||||
AOK(PL_get_arg(1, t, t), NULL);
|
|
||||||
return term_to_python(t, true, NULL);
|
|
||||||
}
|
|
||||||
if (fun == FUNCTOR_complex2) {
|
|
||||||
term_t targ = PL_new_term_ref();
|
|
||||||
PyObject *lhs, *rhs;
|
|
||||||
double d1, d2;
|
|
||||||
|
|
||||||
AOK(PL_get_arg(1, t, targ), NULL);
|
AOK(PL_get_atom_chars(t, &s), NULL);
|
||||||
lhs = term_to_python(targ, true, NULL);
|
pValue = PyObject_GetAttrString(o, s);
|
||||||
AOK(PyNumber_Check(lhs), NULL);
|
if (CHECKNULL(t, pValue) == NULL) {
|
||||||
if (PyFloat_Check(lhs)) {
|
PyErr_Print();
|
||||||
d1 = PyFloat_AsDouble(lhs);
|
return NULL;
|
||||||
} else if (PyLong_Check(lhs)) {
|
}
|
||||||
d1 = PyLong_AsLong(lhs);
|
return pValue;
|
||||||
#if PY_MAJOR_VERSION < 3
|
} else {
|
||||||
} else if (PyInt_Check(lhs)) {
|
char *s = PL_atom_chars(name);
|
||||||
d1 = PyInt_AsLong(lhs);
|
PyObject *ys = lookupPySymbol(s, o, NULL);
|
||||||
#endif
|
PyObject *pArgs = PyTuple_New(arity);
|
||||||
} else {
|
DebugPrintf("Tuple %p\n", pArgs);
|
||||||
return NULL;
|
int i;
|
||||||
}
|
term_t tleft = PL_new_term_ref();
|
||||||
AOK(PL_get_arg(2, t, targ), NULL);
|
for (i = 0; i < arity; i++) {
|
||||||
rhs = term_to_python(targ, true, NULL);
|
PyObject *pArg;
|
||||||
AOK(PyNumber_Check(rhs), NULL);
|
AOK(PL_get_arg(i + 1, t, tleft), NULL);
|
||||||
if (PyFloat_Check(rhs)) {
|
/* ignore (_) */
|
||||||
d2 = PyFloat_AsDouble(rhs);
|
if (i == 0 && PL_is_variable(tleft)) {
|
||||||
} else if (PyLong_Check(rhs)) {
|
pArg = Py_None;
|
||||||
d2 = PyLong_AsLong(rhs);
|
} else {
|
||||||
#if PY_MAJOR_VERSION < 3
|
pArg = term_to_python(tleft, true, NULL, true);
|
||||||
} else if (PyInt_Check(rhs)) {
|
// PyObject_Print(pArg,fdopen(2,"w"),0);
|
||||||
d2 = PyInt_AsLong(rhs);
|
if (pArg == NULL) {
|
||||||
#endif
|
pArg = Py_None;
|
||||||
} else {
|
}
|
||||||
return NULL;
|
/* pArg reference stolen here: */
|
||||||
}
|
Py_INCREF(pArg);
|
||||||
|
}
|
||||||
|
|
||||||
return PyComplex_FromDoubles(d1, d2);
|
PyTuple_SetItem(pArgs, i, pArg);
|
||||||
}
|
}
|
||||||
if (fun == FUNCTOR_curly1) {
|
|
||||||
term_t targ = PL_new_term_ref(), taux = PL_new_term_ref();
|
|
||||||
PyObject *dict;
|
|
||||||
|
|
||||||
AOK(PL_get_arg(1, t, t), NULL);
|
PyObject *rc;
|
||||||
if (!(dict = PyDict_New()))
|
if (ys && PyCallable_Check(ys)) {
|
||||||
return NULL;
|
|
||||||
DebugPrintf("Dict %p\n", dict);
|
|
||||||
|
|
||||||
while (PL_is_functor(t, FUNCTOR_comma2)) {
|
// PyObject_Print(pArgs, stderr, 0);
|
||||||
AOK(PL_get_arg(1, t, targ), NULL);
|
// PyObject_Print(o, stderr, 0);
|
||||||
AOK(PL_is_functor(targ, FUNCTOR_colon2), NULL);
|
CHECK_CALL(rc, t, PyObject_CallObject(ys, pArgs));
|
||||||
|
Py_DECREF(pArgs);
|
||||||
AOK(copy_to_dictionary(dict, targ, taux, true), NULL);
|
Py_DECREF(ys);
|
||||||
AOK(PL_get_arg(2, t, t), NULL);
|
DebugPrintf("CallObject %p\n", rc);
|
||||||
}
|
} else {
|
||||||
|
rc = term_to_nametuple(s, arity, pArgs);
|
||||||
if (PL_is_functor(t, FUNCTOR_colon2)) {
|
}
|
||||||
AOK(copy_to_dictionary(dict, t, taux, true), NULL);
|
|
||||||
}
|
return rc;
|
||||||
return dict;
|
}
|
||||||
}
|
}
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *compound_to_pytree(term_t t, PyObject *context) {
|
|
||||||
PyObject *o = py_Main, *no;
|
|
||||||
functor_t fun;
|
|
||||||
atom_t name;
|
|
||||||
int arity;
|
|
||||||
|
|
||||||
o = find_obj(context, t, false);
|
|
||||||
AOK(PL_get_name_arity(t, &name, &arity), NULL);
|
|
||||||
if (arity == 0)
|
|
||||||
return term_to_python(t, false, o);
|
|
||||||
AOK(PL_get_functor(t, &fun), NULL);
|
|
||||||
if ((no = compound_to_data(t, o, fun, false)) != o && no) {
|
|
||||||
return no;
|
|
||||||
}
|
|
||||||
if (!arity) {
|
|
||||||
char *s = NULL;
|
|
||||||
|
|
||||||
AOK(!PL_get_atom_chars(t, &s), NULL);
|
|
||||||
// this should never happen
|
|
||||||
return term_to_python(t, false, o);
|
|
||||||
} else {
|
|
||||||
const char *s;
|
|
||||||
if (!(s = PL_atom_chars(name))) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
term_t tleft;
|
|
||||||
int i;
|
|
||||||
PyObject *out = PyTuple_New(arity);
|
|
||||||
DebugPrintf("Tuple %p\n", o);
|
|
||||||
tleft = PL_new_term_ref();
|
|
||||||
for (i = 0; i < arity; i++) {
|
|
||||||
PyObject *pArg;
|
|
||||||
AOK(PL_get_arg(i + 1, t, tleft), NULL);
|
|
||||||
pArg = term_to_python(tleft, false, NULL);
|
|
||||||
if (pArg) {
|
|
||||||
/* pArg reference stolen here: */
|
|
||||||
PyTuple_SET_ITEM(out, i, pArg);
|
|
||||||
Py_INCREF(pArg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (CHECKNULL(t, out) == NULL) {
|
|
||||||
PyErr_Print();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
PyObject *c = lookupPySymbol(s, o, NULL);
|
|
||||||
|
|
||||||
if (c && PyCallable_Check(c)) {
|
|
||||||
PyObject *n = PyTuple_New(arity);
|
|
||||||
PyTuple_SET_ITEM(n, 0, c);
|
|
||||||
PyTuple_SET_ITEM(n, 1, out);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
return term_to_nametuple(s, arity, out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *compound_to_pyeval(term_t t, PyObject *context) {
|
|
||||||
PyObject *o = NULL, *no;
|
|
||||||
atom_t name;
|
|
||||||
int arity;
|
|
||||||
functor_t fun;
|
|
||||||
|
|
||||||
o = find_obj(context, t, true);
|
|
||||||
AOK(PL_get_name_arity(t, &name, &arity), NULL);
|
|
||||||
if (arity == 0)
|
|
||||||
return term_to_python(t, true, o);
|
|
||||||
if (!PL_get_functor(t, &fun))
|
|
||||||
return NULL;
|
|
||||||
if ((no = compound_to_data(t, o, fun, true)) != o && no) {
|
|
||||||
return no;
|
|
||||||
}
|
|
||||||
if (fun == FUNCTOR_abs1) {
|
|
||||||
return bip_abs(t);
|
|
||||||
} else if (fun == FUNCTOR_all1) {
|
|
||||||
return bip_all(t);
|
|
||||||
} else if (fun == FUNCTOR_any1) {
|
|
||||||
return bip_any(t);
|
|
||||||
} else if (fun == FUNCTOR_bin1) {
|
|
||||||
return bip_bin(t);
|
|
||||||
} else if (fun == FUNCTOR_ord1) {
|
|
||||||
return bip_ord(t);
|
|
||||||
} else if (fun == FUNCTOR_int1) {
|
|
||||||
return bip_int(t);
|
|
||||||
} else if (fun == FUNCTOR_long1) {
|
|
||||||
return bip_long(t);
|
|
||||||
} else if (fun == FUNCTOR_float1) {
|
|
||||||
return bip_float(t, true);
|
|
||||||
} else if (fun == FUNCTOR_iter1) {
|
|
||||||
return bip_iter(t);
|
|
||||||
} else if (fun == FUNCTOR_range1 || fun == FUNCTOR_range2 ||
|
|
||||||
fun == FUNCTOR_range3) {
|
|
||||||
return bip_range(t);
|
|
||||||
} else if (fun == FUNCTOR_sum1) {
|
|
||||||
return bip_sum(t);
|
|
||||||
}
|
|
||||||
if (fun == FUNCTOR_len1) {
|
|
||||||
term_t targ = PL_new_term_ref();
|
|
||||||
PyObject *ptr;
|
|
||||||
|
|
||||||
AOK(PL_get_arg(1, t, targ), NULL);
|
|
||||||
ptr = term_to_python(targ, true, NULL);
|
|
||||||
return PyLong_FromLong(PyObject_Length(ptr));
|
|
||||||
}
|
|
||||||
if (fun == FUNCTOR_dir1) {
|
|
||||||
term_t targ = PL_new_term_ref();
|
|
||||||
PyObject *ptr;
|
|
||||||
|
|
||||||
AOK(PL_get_arg(1, t, targ), NULL);
|
|
||||||
ptr = term_to_python(targ, true, NULL);
|
|
||||||
return PyObject_Dir(ptr);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (fun == FUNCTOR_plus2) {
|
|
||||||
term_t targ = PL_new_term_ref();
|
|
||||||
PyObject *lhs, *rhs;
|
|
||||||
|
|
||||||
if (!PL_get_arg(1, t, targ))
|
|
||||||
return NULL;
|
|
||||||
lhs = term_to_python(targ, true, NULL);
|
|
||||||
AOK(PL_get_arg(2, t, targ), NULL);
|
|
||||||
rhs = term_to_python(targ, true, NULL);
|
|
||||||
if (PySequence_Check(lhs) && PySequence_Check(rhs)) {
|
|
||||||
return PySequence_Concat(lhs, rhs);
|
|
||||||
}
|
|
||||||
if (!PyNumber_Check(lhs))
|
|
||||||
return NULL;
|
|
||||||
if (!PyNumber_Check(rhs))
|
|
||||||
return NULL;
|
|
||||||
return PyNumber_Add(lhs, rhs);
|
|
||||||
} else if (fun == FUNCTOR_sub2) {
|
|
||||||
term_t targ = PL_new_term_ref();
|
|
||||||
PyObject *lhs, *rhs;
|
|
||||||
|
|
||||||
if (!PL_get_arg(1, t, targ))
|
|
||||||
return NULL;
|
|
||||||
lhs = term_to_python(targ, true, NULL);
|
|
||||||
if (!PyNumber_Check(lhs))
|
|
||||||
return NULL;
|
|
||||||
if (!PL_get_arg(2, t, targ))
|
|
||||||
return NULL;
|
|
||||||
rhs = term_to_python(targ, true, NULL);
|
|
||||||
if (!PyNumber_Check(rhs))
|
|
||||||
return NULL;
|
|
||||||
return PyNumber_Subtract(lhs, rhs);
|
|
||||||
} else if (fun == FUNCTOR_mul2) {
|
|
||||||
term_t targ = PL_new_term_ref();
|
|
||||||
PyObject *lhs, *rhs;
|
|
||||||
|
|
||||||
AOK(PL_get_arg(1, t, targ), NULL);
|
|
||||||
(lhs = term_to_python(targ, true, NULL));
|
|
||||||
CHECKNULL(targ, lhs);
|
|
||||||
AOK(PL_get_arg(2, t, targ), NULL);
|
|
||||||
(rhs = term_to_python(targ, true, NULL));
|
|
||||||
CHECKNULL(targ, rhs);
|
|
||||||
if (PySequence_Check(lhs) && (
|
|
||||||
#if PY_MAJOR_VERSION < 3
|
|
||||||
PyInt_Check(rhs) ||
|
|
||||||
#endif
|
|
||||||
PyLong_Check(rhs))) {
|
|
||||||
return PySequence_Repeat(lhs, get_p_int(rhs, 0));
|
|
||||||
}
|
|
||||||
if (!PyNumber_Check(lhs) + !PyNumber_Check(rhs))
|
|
||||||
return NULL;
|
|
||||||
return PyNumber_Multiply(lhs, rhs);
|
|
||||||
}
|
|
||||||
if (!arity) {
|
|
||||||
char *s = NULL;
|
|
||||||
PyObject *pValue;
|
|
||||||
|
|
||||||
AOK(PL_get_atom_chars(t, &s), NULL);
|
|
||||||
pValue = PyObject_GetAttrString(o, s);
|
|
||||||
if (CHECKNULL(t, pValue) == NULL) {
|
|
||||||
PyErr_Print();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return pValue;
|
|
||||||
} else {
|
|
||||||
char *s = PL_atom_chars(name);
|
|
||||||
o = lookupPySymbol(s, o, NULL);
|
|
||||||
if (CHECKNULL(t, o) == NULL) {
|
|
||||||
PyErr_Print();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
PyObject *pArgs = PyTuple_New(arity);
|
|
||||||
DebugPrintf("Tuple %p\n", pArgs);
|
|
||||||
int i;
|
|
||||||
term_t tleft = PL_new_term_ref();
|
|
||||||
for (i = 0; i < arity; i++) {
|
|
||||||
PyObject *pArg;
|
|
||||||
AOK(PL_get_arg(i + 1, t, tleft), NULL);
|
|
||||||
/* ignore (_) */
|
|
||||||
if (i == 0 && PL_is_variable(tleft)) {
|
|
||||||
pArg = Py_None;
|
|
||||||
} else {
|
|
||||||
pArg = term_to_python(tleft, true, NULL);
|
|
||||||
// PyObject_Print(pArg,fdopen(2,"w"),0);
|
|
||||||
if (pArg == NULL) {
|
|
||||||
pArg = Py_None;
|
|
||||||
}
|
|
||||||
/* pArg reference stolen here: */
|
|
||||||
Py_INCREF(pArg);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyTuple_SetItem(pArgs, i, pArg);
|
|
||||||
}
|
|
||||||
if (!PyCallable_Check(o)) {
|
|
||||||
return term_to_nametuple(s, arity, pArgs);
|
|
||||||
}
|
|
||||||
PyObject *rc;
|
|
||||||
|
|
||||||
// PyObject_Print(pArgs, stderr, 0);
|
|
||||||
// PyObject_Print(o, stderr, 0);
|
|
||||||
CHECK_CALL(rc, t, PyObject_CallObject(o, pArgs));
|
|
||||||
Py_DECREF(pArgs);
|
|
||||||
Py_DECREF(o);
|
|
||||||
DebugPrintf("CallObject %p\n", rc);
|
|
||||||
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -12,7 +12,7 @@ static foreign_t python_len(term_t tobj, term_t tf) {
|
|||||||
Py_ssize_t len;
|
Py_ssize_t len;
|
||||||
PyObject *o;
|
PyObject *o;
|
||||||
|
|
||||||
o = term_to_python(tobj, true, NULL);
|
o = term_to_python(tobj, true, NULL, true);
|
||||||
if (o == NULL) {
|
if (o == NULL) {
|
||||||
pyErrorAndReturn(false, false);
|
pyErrorAndReturn(false, false);
|
||||||
}
|
}
|
||||||
@ -24,7 +24,7 @@ static foreign_t python_dir(term_t tobj, term_t tf) {
|
|||||||
PyObject *dir;
|
PyObject *dir;
|
||||||
PyObject *o;
|
PyObject *o;
|
||||||
|
|
||||||
o = term_to_python(tobj, true, NULL);
|
o = term_to_python(tobj, true, NULL, true);
|
||||||
if (o == NULL) {
|
if (o == NULL) {
|
||||||
pyErrorAndReturn(false, false);
|
pyErrorAndReturn(false, false);
|
||||||
}
|
}
|
||||||
@ -41,14 +41,14 @@ static foreign_t python_index(term_t tobj, term_t tindex, term_t val) {
|
|||||||
PyObject *o;
|
PyObject *o;
|
||||||
PyObject *f;
|
PyObject *f;
|
||||||
|
|
||||||
o = term_to_python(tobj, true, NULL);
|
o = term_to_python(tobj, true, NULL, true);
|
||||||
if (o == NULL) {
|
if (o == NULL) {
|
||||||
pyErrorAndReturn(false, false);
|
pyErrorAndReturn(false, false);
|
||||||
}
|
}
|
||||||
if (!PySequence_Check(o)) {
|
if (!PySequence_Check(o)) {
|
||||||
pyErrorAndReturn(false, false);
|
pyErrorAndReturn(false, false);
|
||||||
}
|
}
|
||||||
i = term_to_python(tindex, true, NULL);
|
i = term_to_python(tindex, true, NULL, true);
|
||||||
if (i == NULL) {
|
if (i == NULL) {
|
||||||
pyErrorAndReturn(false, false);
|
pyErrorAndReturn(false, false);
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ static foreign_t python_is(term_t tobj, term_t tf) {
|
|||||||
|
|
||||||
term_t lim = python_acquire_GIL();
|
term_t lim = python_acquire_GIL();
|
||||||
|
|
||||||
o = term_to_python(tobj, true, NULL);
|
o = term_to_python(tobj, true, NULL, true);
|
||||||
if (!o) {
|
if (!o) {
|
||||||
python_release_GIL(lim);
|
python_release_GIL(lim);
|
||||||
pyErrorAndReturn(false, false);
|
pyErrorAndReturn(false, false);
|
||||||
@ -87,7 +87,7 @@ static foreign_t python_proc(term_t tobj) {
|
|||||||
|
|
||||||
term_t lim = python_acquire_GIL();
|
term_t lim = python_acquire_GIL();
|
||||||
|
|
||||||
o = term_to_python(tobj, true, NULL);
|
o = term_to_python(tobj, true, NULL, true);
|
||||||
python_release_GIL(lim);
|
python_release_GIL(lim);
|
||||||
bool rc = o != NULL;
|
bool rc = o != NULL;
|
||||||
pyErrorAndReturn(rc , false);
|
pyErrorAndReturn(rc , false);
|
||||||
@ -100,10 +100,10 @@ static foreign_t python_slice(term_t parent, term_t indx, term_t tobj) {
|
|||||||
PyObject *p;
|
PyObject *p;
|
||||||
|
|
||||||
// get Scope ...
|
// get Scope ...
|
||||||
pI = term_to_python(indx, true, NULL);
|
pI = term_to_python(indx, true, NULL, true);
|
||||||
// got Scope.Exp
|
// got Scope.Exp
|
||||||
// get Scope ...
|
// get Scope ...
|
||||||
p = term_to_python(parent, true, NULL);
|
p = term_to_python(parent, true, NULL, true);
|
||||||
// Exp
|
// Exp
|
||||||
if (!pI || !p) {
|
if (!pI || !p) {
|
||||||
{ pyErrorAndReturn(false, false); }
|
{ pyErrorAndReturn(false, false); }
|
||||||
@ -131,7 +131,7 @@ static foreign_t python_apply(term_t tin, term_t targs, term_t keywds,
|
|||||||
foreign_t out;
|
foreign_t out;
|
||||||
term_t targ = PL_new_term_ref();
|
term_t targ = PL_new_term_ref();
|
||||||
|
|
||||||
pF = term_to_python(tin, true, NULL);
|
pF = term_to_python(tin, true, NULL, true);
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
if (pF == NULL) {
|
if (pF == NULL) {
|
||||||
{ pyErrorAndReturn(false, false); }
|
{ pyErrorAndReturn(false, false); }
|
||||||
@ -159,7 +159,7 @@ static foreign_t python_apply(term_t tin, term_t targs, term_t keywds,
|
|||||||
if (!PL_get_arg(i + 1, targs, targ)) {
|
if (!PL_get_arg(i + 1, targs, targ)) {
|
||||||
pyErrorAndReturn(false, false);
|
pyErrorAndReturn(false, false);
|
||||||
}
|
}
|
||||||
pArg = term_to_python(targ, true, NULL);
|
pArg = term_to_python(targ, true, NULL, true);
|
||||||
if (pArg == NULL) {
|
if (pArg == NULL) {
|
||||||
pyErrorAndReturn(false, false);
|
pyErrorAndReturn(false, false);
|
||||||
}
|
}
|
||||||
@ -171,7 +171,7 @@ static foreign_t python_apply(term_t tin, term_t targs, term_t keywds,
|
|||||||
if (PL_is_atom(keywds)) {
|
if (PL_is_atom(keywds)) {
|
||||||
pKeywords = NULL;
|
pKeywords = NULL;
|
||||||
} else {
|
} else {
|
||||||
pKeywords = term_to_python(keywds, true, NULL);
|
pKeywords = term_to_python(keywds, true, NULL, true);
|
||||||
}
|
}
|
||||||
if (PyCallable_Check(pF)) {
|
if (PyCallable_Check(pF)) {
|
||||||
pValue = PyEval_CallObjectWithKeywords(pF, pArgs, pKeywords);
|
pValue = PyEval_CallObjectWithKeywords(pF, pArgs, pKeywords);
|
||||||
@ -204,7 +204,7 @@ static foreign_t python_apply(term_t tin, term_t targs, term_t keywds,
|
|||||||
|
|
||||||
static foreign_t assign_python(term_t exp, term_t name) {
|
static foreign_t assign_python(term_t exp, term_t name) {
|
||||||
term_t stackp = python_acquire_GIL();
|
term_t stackp = python_acquire_GIL();
|
||||||
PyObject *e = term_to_python(exp, true, NULL);
|
PyObject *e = term_to_python(exp, true, NULL, true);
|
||||||
|
|
||||||
if (e == NULL) {
|
if (e == NULL) {
|
||||||
python_release_GIL(stackp);
|
python_release_GIL(stackp);
|
||||||
@ -253,7 +253,7 @@ static foreign_t python_builtin_eval(term_t caller, term_t dict, term_t out) {
|
|||||||
if (i == 0 && PL_is_variable(targ)) {
|
if (i == 0 && PL_is_variable(targ)) {
|
||||||
pArg = Py_None;
|
pArg = Py_None;
|
||||||
} else {
|
} else {
|
||||||
pArg = term_to_python(targ, true, NULL);
|
pArg = term_to_python(targ, true, NULL, true);
|
||||||
if (pArg == NULL) {
|
if (pArg == NULL) {
|
||||||
pyErrorAndReturn(false, false);
|
pyErrorAndReturn(false, false);
|
||||||
}
|
}
|
||||||
@ -280,7 +280,7 @@ static foreign_t python_builtin_eval(term_t caller, term_t dict, term_t out) {
|
|||||||
|
|
||||||
static foreign_t python_access(term_t obj, term_t f, term_t out) {
|
static foreign_t python_access(term_t obj, term_t f, term_t out) {
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
PyObject *o = term_to_python(obj, true, NULL), *pValue, *pArgs, *pF;
|
PyObject *o = term_to_python(obj, true, NULL, true), *pValue, *pArgs, *pF;
|
||||||
atom_t name;
|
atom_t name;
|
||||||
char *s = NULL;
|
char *s = NULL;
|
||||||
int i, arity;
|
int i, arity;
|
||||||
@ -323,7 +323,7 @@ static foreign_t python_access(term_t obj, term_t f, term_t out) {
|
|||||||
if (i == 0 && PL_is_variable(targ)) {
|
if (i == 0 && PL_is_variable(targ)) {
|
||||||
pArgs = Py_None;
|
pArgs = Py_None;
|
||||||
}
|
}
|
||||||
pArg = term_to_python(targ, true, NULL);
|
pArg = term_to_python(targ, true, NULL, true);
|
||||||
if (pArg == NULL) {
|
if (pArg == NULL) {
|
||||||
pyErrorAndReturn(false, false);
|
pyErrorAndReturn(false, false);
|
||||||
}
|
}
|
||||||
@ -352,7 +352,7 @@ static foreign_t python_field(term_t parent, term_t att, term_t tobj) {
|
|||||||
|
|
||||||
// got Scope.Exp
|
// got Scope.Exp
|
||||||
// get Scope ...
|
// get Scope ...
|
||||||
p = term_to_python(parent, true, NULL);
|
p = term_to_python(parent, true, NULL, true);
|
||||||
// Exp
|
// Exp
|
||||||
if (!PL_get_name_arity(att, &name, &arity)) {
|
if (!PL_get_name_arity(att, &name, &arity)) {
|
||||||
{ pyErrorAndReturn(false, false); }
|
{ pyErrorAndReturn(false, false); }
|
||||||
@ -392,7 +392,7 @@ static foreign_t python_main_module(term_t mod) {
|
|||||||
|
|
||||||
static foreign_t python_function(term_t tobj) {
|
static foreign_t python_function(term_t tobj) {
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
PyObject *obj = term_to_python(tobj, true, NULL);
|
PyObject *obj = term_to_python(tobj, true, NULL, true);
|
||||||
foreign_t rc = PyFunction_Check(obj);
|
foreign_t rc = PyFunction_Check(obj);
|
||||||
|
|
||||||
pyErrorAndReturn(rc, false);
|
pyErrorAndReturn(rc, false);
|
||||||
@ -595,7 +595,7 @@ if (pName == NULL) {
|
|||||||
static foreign_t python_to_rhs(term_t inp, term_t t) {
|
static foreign_t python_to_rhs(term_t inp, term_t t) {
|
||||||
PyObject *pVal;
|
PyObject *pVal;
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
pVal = term_to_python(inp, true, NULL);
|
pVal = term_to_python(inp, true, NULL, true);
|
||||||
if (pVal == NULL)
|
if (pVal == NULL)
|
||||||
pyErrorAndReturn(false, false);
|
pyErrorAndReturn(false, false);
|
||||||
pyErrorAndReturn(address_to_term(pVal, t), false);
|
pyErrorAndReturn(address_to_term(pVal, t), false);
|
||||||
|
@ -1,19 +1,23 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "py4yap.h"
|
#include "py4yap.h"
|
||||||
#include <VFS.h>
|
#include <VFS.h>
|
||||||
|
|
||||||
|
#include "YapStreams.h"
|
||||||
|
|
||||||
atom_t ATOM_true, ATOM_false, ATOM_colon, ATOM_dot, ATOM_none, ATOM_t,
|
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;
|
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_t FUNCTOR_dollar1, FUNCTOR_abs1, FUNCTOR_all1, FUNCTOR_any1,
|
||||||
FUNCTOR_bin1, FUNCTOR_brackets1, FUNCTOR_comma2, FUNCTOR_dir1,
|
FUNCTOR_bin1, FUNCTOR_brackets1, FUNCTOR_comma2, FUNCTOR_dir1,
|
||||||
FUNCTOR_float1, FUNCTOR_int1, FUNCTOR_iter1, FUNCTOR_iter2, FUNCTOR_long1,
|
FUNCTOR_float1, FUNCTOR_int1, FUNCTOR_iter1, FUNCTOR_iter2, FUNCTOR_long1,
|
||||||
FUNCTOR_len1, FUNCTOR_curly1, FUNCTOR_ord1, FUNCTOR_range1, FUNCTOR_range2,
|
FUNCTOR_len1, FUNCTOR_curly1, FUNCTOR_ord1, FUNCTOR_range1, FUNCTOR_range2,
|
||||||
FUNCTOR_range3, FUNCTOR_sum1, FUNCTOR_pointer1, FUNCTOR_complex2,
|
FUNCTOR_range3, FUNCTOR_sum1, FUNCTOR_pointer1, FUNCTOR_complex2,
|
||||||
FUNCTOR_plus2, FUNCTOR_sub2, FUNCTOR_mul2, FUNCTOR_div2, FUNCTOR_hat2,
|
FUNCTOR_plus2, FUNCTOR_sub2, FUNCTOR_mul2, FUNCTOR_div2, FUNCTOR_hat2,
|
||||||
FUNCTOR_colon2, FUNCTOR_comma2, FUNCTOR_equal2, FUNCTOR_sqbrackets2,
|
FUNCTOR_colon2, FUNCTOR_comma2, FUNCTOR_equal2, FUNCTOR_sqbrackets2,
|
||||||
FUNCTOR_dot2, FUNCTOR_brackets1;
|
FUNCTOR_dot2, FUNCTOR_brackets1;
|
||||||
|
|
||||||
X_API PyObject *py_Builtin;
|
X_API PyObject *py_Builtin;
|
||||||
X_API PyObject *py_Yapex;
|
X_API PyObject *py_Yapex;
|
||||||
@ -23,77 +27,88 @@ PyObject *py_ModDict;
|
|||||||
|
|
||||||
VFS_t pystream;
|
VFS_t pystream;
|
||||||
|
|
||||||
static void *
|
static void *py_open(const char *name, const char *io_mode) {
|
||||||
py_open( const char *name, const char *io_mode) {
|
|
||||||
#if HAVE_STRCASESTR
|
#if HAVE_STRCASESTR
|
||||||
if (strcasestr(name,"//python/")== name)
|
if (strcasestr(name, "//python/") == name)
|
||||||
name += strlen("//python/");
|
name += strlen("//python/");
|
||||||
#else
|
#else
|
||||||
if (strstr(name,"//python/")== name)
|
if (strstr(name, "//python/") == name)
|
||||||
name += strlen("//python/");
|
name += strlen("//python/");
|
||||||
#endif
|
#endif
|
||||||
// we assume object is already open, so there is no need to open it.
|
// we assume object is already open, so there is no need to open it.
|
||||||
PyObject *stream = string_to_python( name, true, NULL);
|
PyObject *stream = string_to_python(name, true, NULL);
|
||||||
if (stream == Py_None)
|
if (stream == Py_None)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
Py_INCREF(stream);
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool py_close(int sno) {
|
||||||
py_close(int sno) {
|
StreamDesc *s = YAP_GetStreamFromId(sno);
|
||||||
PyObject *s = YAP_foreign_stream(sno);
|
PyObject *fclose = PyObject_GetAttrString(s->u.private_data, "close");
|
||||||
PyObject* fclose = PyObject_GetAttrString(s, "close");
|
PyObject *rc = PyObject_CallObject(fclose, NULL);
|
||||||
PyObject* rc= PyObject_CallObject(fclose, NULL);
|
|
||||||
bool v = (rc == Py_True);
|
bool v = (rc == Py_True);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject * pyw; // buffer
|
|
||||||
static int pyw_kind;
|
|
||||||
PyObject * pyw_data;
|
|
||||||
|
|
||||||
static int
|
static int py_put(int sno, int ch) {
|
||||||
py_put(int sno, int ch) {
|
PyObject *pyw; // buffer
|
||||||
PyObject *s = YAP_foreign_stream(sno);
|
//int pyw_kind;
|
||||||
PyUnicode_WRITE( pyw_kind, pyw_data, 0, ch );
|
//PyObject *pyw_data;
|
||||||
PyObject* fput = PyObject_GetAttrString(s, "write");
|
|
||||||
PyObject_CallFunctionObjArgs(fput, pyw, NULL);
|
char s[2];
|
||||||
|
StreamDesc *st = YAP_GetStreamFromId(sno);
|
||||||
|
// PyUnicode_WRITE(pyw_kind, pyw_data, 0, ch);
|
||||||
|
PyObject *fput = PyObject_GetAttrString(st->u.private_data, "write");
|
||||||
|
s[0] = ch;
|
||||||
|
s[1] = '\0';
|
||||||
|
PyObject_CallFunctionObjArgs(fput, PyBytes_FromString(s), NULL);
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int py_get(int sno) {
|
||||||
py_get(int sno) {
|
StreamDesc *s = YAP_GetStreamFromId(sno);
|
||||||
PyObject *s = YAP_foreign_stream(sno);
|
PyObject *fget = PyObject_GetAttrString(s->u.private_data, "read");
|
||||||
PyObject* fget = PyObject_GetAttrString(s, "read");
|
|
||||||
PyObject *pyr = PyObject_CallFunctionObjArgs(fget, PyLong_FromLong(1), NULL);
|
PyObject *pyr = PyObject_CallFunctionObjArgs(fget, PyLong_FromLong(1), NULL);
|
||||||
return PyUnicode_READ_CHAR( pyr, 0) ;
|
return PyUnicode_READ_CHAR(pyr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t py_seek(int sno, int64_t where, int how) {
|
static int64_t py_seek(int sno, int64_t where, int how) {
|
||||||
PyObject *s = YAP_foreign_stream(sno);
|
StreamDesc *s = YAP_GetStreamFromId(sno);
|
||||||
PyObject* fseek = PyObject_GetAttrString(s, "seek");
|
PyObject *fseek = PyObject_GetAttrString(s->u.private_data, "seek");
|
||||||
PyObject *pyr = PyObject_CallFunctionObjArgs(fseek, PyLong_FromLong(where), PyLong_FromLong(how), NULL);
|
PyObject *pyr = PyObject_CallFunctionObjArgs(fseek, PyLong_FromLong(where),
|
||||||
|
PyLong_FromLong(how), NULL);
|
||||||
return PyLong_AsLong(pyr);
|
return PyLong_AsLong(pyr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void py_flush(int sno) {
|
||||||
py_flush(int sno) {
|
StreamDesc *s = YAP_GetStreamFromId(sno);
|
||||||
PyObject *s = YAP_foreign_stream(sno);
|
PyObject *flush = PyObject_GetAttrString(s->u.private_data, "flush");
|
||||||
PyObject* flush = PyObject_GetAttrString(s, "flush");
|
PyObject_CallFunction(flush, NULL);
|
||||||
PyObject_CallFunction( flush, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static void python_output(void) {
|
||||||
|
PyObject *stream = string_to_python("sys.stdout", true, NULL);
|
||||||
|
StreamDesc *st = YAP_GetStreamFromId(1);
|
||||||
|
st->u.private_data = stream;
|
||||||
|
st->vfs = &pystream;
|
||||||
|
stream = string_to_python("sys.stderr", true, NULL);
|
||||||
|
st = YAP_GetStreamFromIds(2);
|
||||||
|
st->u.private_data = stream;
|
||||||
|
st->vfs = &pystream;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool init_python_stream(void) {
|
||||||
|
//pyw = PyUnicode_FromString("x");
|
||||||
|
//pyw_kind = PyUnicode_KIND(pyw);
|
||||||
|
//pyw_data = PyUnicode_DATA(pyw);
|
||||||
|
|
||||||
|
|
||||||
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.name = "python stream";
|
||||||
pystream.vflags = VFS_CAN_WRITE|VFS_CAN_EXEC| VFS_CAN_SEEK|VFS_HAS_PREFIX;
|
pystream.vflags =
|
||||||
|
VFS_CAN_WRITE | VFS_CAN_EXEC | VFS_CAN_SEEK | VFS_HAS_PREFIX;
|
||||||
pystream.prefix = "//python/";
|
pystream.prefix = "//python/";
|
||||||
pystream.suffix = NULL;
|
pystream.suffix = NULL;
|
||||||
pystream.open = py_open;
|
pystream.open = py_open;
|
||||||
@ -108,7 +123,7 @@ init_python_stream(void)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
X_API PyObject *py_F2P;
|
X_API PyObject *Py_f2p;
|
||||||
|
|
||||||
extern X_API bool python_in_python;
|
extern X_API bool python_in_python;
|
||||||
|
|
||||||
@ -125,11 +140,12 @@ static void add_modules(void) {
|
|||||||
py_Yapex = PyImport_AddModule("yap4py.yapi");
|
py_Yapex = PyImport_AddModule("yap4py.yapi");
|
||||||
if (py_Yapex)
|
if (py_Yapex)
|
||||||
Py_INCREF(py_Yapex);
|
Py_INCREF(py_Yapex);
|
||||||
py_F2P = PyDict_New();
|
Py_f2p = PythonLookup("f2p", NULL);
|
||||||
|
if (Py_f2p)
|
||||||
|
Py_INCREF(Py_f2p);
|
||||||
init_python_stream();
|
init_python_stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void install_py_constants(void) {
|
static void install_py_constants(void) {
|
||||||
FUNCTOR_dot2 = PL_new_functor(PL_new_atom("."), 2);
|
FUNCTOR_dot2 = PL_new_functor(PL_new_atom("."), 2);
|
||||||
// FUNCTOR_equal2 = PL_new_functor(PL_new_atom("="), 2);
|
// FUNCTOR_equal2 = PL_new_functor(PL_new_atom("="), 2);
|
||||||
@ -176,7 +192,7 @@ static void install_py_constants(void) {
|
|||||||
FUNCTOR_comma2 = 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_equal2 = PL_new_functor(PL_new_atom("="), 2);
|
||||||
FUNCTOR_sqbrackets2 = PL_new_functor(PL_new_atom("[]"), 2);
|
FUNCTOR_sqbrackets2 = PL_new_functor(PL_new_atom("[]"), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreign_t end_python(void) {
|
foreign_t end_python(void) {
|
||||||
if (!python_in_python)
|
if (!python_in_python)
|
||||||
@ -189,11 +205,11 @@ static bool libpython_initialized = 0;
|
|||||||
|
|
||||||
X_API bool do_init_python(void) {
|
X_API bool do_init_python(void) {
|
||||||
// char **argv;
|
// char **argv;
|
||||||
if (libpython_initialized)
|
if (libpython_initialized)
|
||||||
return true;
|
return true;
|
||||||
libpython_initialized = true;
|
libpython_initialized = true;
|
||||||
|
|
||||||
// PyGILState_STATE gstate = PyGILState_Ensure();
|
// PyGILState_STATE gstate = PyGILState_Ensure();
|
||||||
term_t t = PL_new_term_ref();
|
term_t t = PL_new_term_ref();
|
||||||
if (!python_in_python)
|
if (!python_in_python)
|
||||||
Py_Initialize();
|
Py_Initialize();
|
||||||
@ -201,7 +217,7 @@ X_API bool do_init_python(void) {
|
|||||||
PL_reset_term_refs(t);
|
PL_reset_term_refs(t);
|
||||||
install_pl2pl();
|
install_pl2pl();
|
||||||
// PyGILState_Release(gstate);
|
// PyGILState_Release(gstate);
|
||||||
add_modules();
|
add_modules();
|
||||||
|
// python_output();
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
1
packages/python/swig/yap4py/__main__.py
Normal file
1
packages/python/swig/yap4py/__main__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
import yap4py.yapi
|
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
%% @file yapi.yap
|
|
||||||
%% @brief support yap shell
|
|
||||||
%%
|
|
||||||
:- module(yapi, [bindvars/2]).
|
|
||||||
|
|
||||||
:- use_module( library(maplist) ).
|
|
||||||
:- use_module( library(rbtrees) ).
|
|
||||||
|
|
||||||
bindvars( [], [] ) :- !.
|
|
||||||
bindvars( L, NL ) :-
|
|
||||||
rb_new(T),
|
|
||||||
% trace,
|
|
||||||
foldl2( bind, L, NL, T, _ , 0, _),
|
|
||||||
term_variables(NL, Vs),
|
|
||||||
foldl( bind_new, Vs, 0, _).
|
|
||||||
|
|
||||||
|
|
||||||
bind(t(_,t(X,Y)), Z, T0, T, N1, N2) :-
|
|
||||||
!,
|
|
||||||
bind(X=Y, Z, T0, T, N1, N2).
|
|
||||||
bind(tuple(_,tuple(X,Y)), Z, T0, T, N1, N2) :-
|
|
||||||
!,
|
|
||||||
bind(X=Y, Z, T0, T, N1, N2).
|
|
||||||
bind(X=Y, X=X, T0, T, N, N) :-
|
|
||||||
var(Y),
|
|
||||||
!,
|
|
||||||
rb_update(T0, Y, X, T).
|
|
||||||
bind(X = G, X = G, T, T, N0, N0) :-
|
|
||||||
ground(G),
|
|
||||||
!.
|
|
||||||
bind(X = C, X = NC, T, NT, N0, NF) :-
|
|
||||||
C =.. [N|L],
|
|
||||||
foldl2(newb, L, NL, T, NT, N0, NF),
|
|
||||||
NC =.. [N|NL].
|
|
||||||
|
|
||||||
newb(Y, X, T, T, N, N) :-
|
|
||||||
var(Y),
|
|
||||||
rb_lookup(Y, X, T),
|
|
||||||
!.
|
|
||||||
newb(Y, X, T, TN, N, NF) :-
|
|
||||||
var(Y),
|
|
||||||
!,
|
|
||||||
rb_insert(Y, T, X, TN),
|
|
||||||
NF is N+1,
|
|
||||||
atomic_concat('_',N,X).
|
|
||||||
newb(Y, Y, T, T, N, N) :-
|
|
||||||
ground(Y),
|
|
||||||
!.
|
|
||||||
newb(Y, X, T, NT, N0, NF) :-
|
|
||||||
Y =.. [N|L],
|
|
||||||
foldl2(newb, L, NL, T, NT, N0, NF),
|
|
||||||
X =.. [N|NL].
|
|
||||||
*/
|
|
@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
import os.path
|
import os.path
|
||||||
import sys
|
import sys
|
||||||
|
import keyword
|
||||||
# debugging support.
|
# debugging support.
|
||||||
# import pdb
|
# import pdb
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
@ -20,6 +21,8 @@ class Engine( YAPEngine ):
|
|||||||
YAPEngine.__init__(self,args)
|
YAPEngine.__init__(self,args)
|
||||||
self.goal( set_prolog_flag('verbose', 'silent' ) )
|
self.goal( set_prolog_flag('verbose', 'silent' ) )
|
||||||
self.goal( use_module(library('yapi') ) )
|
self.goal( use_module(library('yapi') ) )
|
||||||
|
self.goal( set_prolog_flag('verbose', 'normal' ) )
|
||||||
|
|
||||||
|
|
||||||
def run(self, g, m=None):
|
def run(self, g, m=None):
|
||||||
if m:
|
if m:
|
||||||
@ -81,7 +84,16 @@ class PrologTableIter:
|
|||||||
self.q = None
|
self.q = None
|
||||||
raise StopIteration()
|
raise StopIteration()
|
||||||
|
|
||||||
|
f2p = []
|
||||||
|
for i in range(16):
|
||||||
|
f2p += [{}]
|
||||||
|
|
||||||
|
def named( name, arity):
|
||||||
|
if arity > 0 and name.isidentifier() and not keyword.iskeyword(name):
|
||||||
|
s = []
|
||||||
|
for i in range(arity):
|
||||||
|
s += ["A" + str(i)]
|
||||||
|
f2p[arity][name] = namedtuple(name, s)
|
||||||
|
|
||||||
class PrologPredicate( YAPPrologPredicate ):
|
class PrologPredicate( YAPPrologPredicate ):
|
||||||
""" Interface to Prolog Predicate"""
|
""" Interface to Prolog Predicate"""
|
||||||
@ -103,8 +115,12 @@ yapi_query = namedtuple( 'yapi_query', 'vars dict')
|
|||||||
show_answer = namedtuple( 'show_answer', 'vars dict')
|
show_answer = namedtuple( 'show_answer', 'vars dict')
|
||||||
set_prolog_flag = namedtuple('set_prolog_flag', 'flag new_value')
|
set_prolog_flag = namedtuple('set_prolog_flag', 'flag new_value')
|
||||||
|
|
||||||
def v():
|
class v(YAPVarTerm):
|
||||||
return yap.YAPVarTerm()
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def binding(self):
|
||||||
|
return self.term()
|
||||||
|
|
||||||
def numbervars( q ):
|
def numbervars( q ):
|
||||||
Dict = {}
|
Dict = {}
|
||||||
@ -113,105 +129,110 @@ def numbervars( q ):
|
|||||||
return Dict
|
return Dict
|
||||||
rc = q.namedVarsVector()
|
rc = q.namedVarsVector()
|
||||||
q.r = q.goal().numbervars()
|
q.r = q.goal().numbervars()
|
||||||
print( rc )
|
|
||||||
o = []
|
o = []
|
||||||
for i in rc:
|
for i in rc:
|
||||||
if len(i) == 2:
|
if len(i) == 2:
|
||||||
do = str(i[0]) + " = " + str( i[1] ) + "\n"
|
do = str(i[0]) + " = " + str( i[1] ) + "\n"
|
||||||
o += do
|
o += do
|
||||||
print(do)
|
|
||||||
else:
|
else:
|
||||||
do = str(i[0]) + " = " + str( i[1] ) + "\n"
|
do = str(i[0]) + " = " + str( i[1] ) + "\n"
|
||||||
o += do
|
o += do
|
||||||
print(do)
|
|
||||||
return o
|
return o
|
||||||
|
|
||||||
def answer(q):
|
class YAPShell:
|
||||||
try:
|
|
||||||
v = q.next()
|
|
||||||
if v:
|
|
||||||
print( bindings )
|
|
||||||
return v
|
|
||||||
except Exception as e:
|
|
||||||
print(e.args[1])
|
|
||||||
return False
|
|
||||||
|
|
||||||
def query_prolog(engine, s):
|
|
||||||
# import pdb; pdb.set_trace()
|
|
||||||
#
|
|
||||||
# construct a query from a one-line string
|
|
||||||
# q is opaque to Python
|
|
||||||
bindings = {}
|
|
||||||
q = engine.query(python_query(s, bindings))
|
|
||||||
# vs is the list of variables
|
|
||||||
# you can print it out, the left-side is the variable name,
|
|
||||||
# the right side wraps a handle to a variable
|
|
||||||
# pdb.set_trace()
|
|
||||||
# #pdb.set_trace()
|
|
||||||
# atom match either symbols, or if no symbol exists, sttrings, In this case
|
|
||||||
# variable names should match strings
|
|
||||||
#for eq in vs:
|
|
||||||
# if not isinstance(eq[0],str):
|
|
||||||
# print( "Error: Variable Name matches a Python Symbol")
|
|
||||||
# return
|
|
||||||
ask = True
|
|
||||||
# launch the query
|
|
||||||
while answer(q):
|
|
||||||
# deterministic = one solution
|
|
||||||
if q.deterministic():
|
|
||||||
# done
|
|
||||||
q.close()
|
|
||||||
return True, True
|
|
||||||
if ask:
|
|
||||||
s = input("more(;), all(*), no(\\n), python(#) ?").lstrip()
|
|
||||||
if s.startswith(';') or s.startswith('y'):
|
|
||||||
continue
|
|
||||||
elif s.startswith('#'):
|
|
||||||
try:
|
|
||||||
exec(s.lstrip('#'))
|
|
||||||
except:
|
|
||||||
raise
|
|
||||||
elif s.startswith('*') or s.startswith('a'):
|
|
||||||
ask = False
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
print("No (more) answers")
|
|
||||||
q.close()
|
|
||||||
return
|
|
||||||
|
|
||||||
def live(**kwargs):
|
def answer(self, q):
|
||||||
loop = True
|
|
||||||
while loop:
|
|
||||||
try:
|
try:
|
||||||
s = input("?- ")
|
self.bindings = {}
|
||||||
if not s:
|
v = q.next()
|
||||||
loop = False
|
if v:
|
||||||
else:
|
print( self.bindings )
|
||||||
query_prolog(engine, s)
|
return v
|
||||||
except SyntaxError as err:
|
except Exception as e:
|
||||||
print("Syntax Error error: {0}".format(err))
|
print(e.args[1])
|
||||||
except EOFError:
|
return False
|
||||||
return
|
|
||||||
except RuntimeError as err:
|
|
||||||
print("YAP Execution Error: {0}".format(err))
|
|
||||||
except ValueError:
|
|
||||||
print("Could not convert data to an integer.")
|
|
||||||
except:
|
|
||||||
print("Unexpected error:", sys.exc_info()[0])
|
|
||||||
raise
|
|
||||||
engine.close()
|
|
||||||
#
|
|
||||||
# initialize engine
|
|
||||||
# engine = yap.YAPEngine();
|
|
||||||
# engine = yap.YAPEngine(yap.YAPParams());
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
||||||
def boot_yap(**kwargs):
|
def query_prolog(self, engine, s):
|
||||||
return Engine(**kwargs)
|
# import pdb; pdb.set_trace()
|
||||||
|
#
|
||||||
|
# construct a query from a one-line string
|
||||||
|
# q is opaque to Python
|
||||||
|
#
|
||||||
|
q = engine.query(python_query(self, s))
|
||||||
|
#
|
||||||
|
# # vs is the list of variables
|
||||||
|
# you can print it out, the left-side is the variable name,
|
||||||
|
# the right side wraps a handle to a variable
|
||||||
|
# pdb.set_trace()
|
||||||
|
# #pdb.set_trace()
|
||||||
|
# atom match either symbols, or if no symbol exists, sttrings, In this case
|
||||||
|
# variable names should match strings
|
||||||
|
#for eq in vs:
|
||||||
|
# if not isinstance(eq[0],str):
|
||||||
|
# print( "Error: Variable Name matches a Python Symbol")
|
||||||
|
# return
|
||||||
|
do_ask = True
|
||||||
|
self.port = "call"
|
||||||
|
# launch the query
|
||||||
|
while self.answer(q):
|
||||||
|
if self.port == "exit":
|
||||||
|
# done
|
||||||
|
q.close()
|
||||||
|
return True, True
|
||||||
|
if do_ask:
|
||||||
|
s = input("more(;), all(*), no(\\n), python(#) ?").lstrip()
|
||||||
|
if s.startswith(';') or s.startswith('y'):
|
||||||
|
continue
|
||||||
|
elif s.startswith('#'):
|
||||||
|
try:
|
||||||
|
exec(s.lstrip('#'))
|
||||||
|
except:
|
||||||
|
raise
|
||||||
|
elif s.startswith('*') or s.startswith('a'):
|
||||||
|
do_ask = False
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
print("No (more) answers")
|
||||||
|
q.close()
|
||||||
|
return
|
||||||
|
|
||||||
|
def live(self, engine, **kwargs):
|
||||||
|
loop = True
|
||||||
|
while loop:
|
||||||
|
try:
|
||||||
|
s = input("?- ")
|
||||||
|
if not s:
|
||||||
|
loop = False
|
||||||
|
else:
|
||||||
|
self.query_prolog(engine, s)
|
||||||
|
except SyntaxError as err:
|
||||||
|
print("Syntax Error error: {0}".format(err))
|
||||||
|
except EOFError:
|
||||||
|
return
|
||||||
|
except RuntimeError as err:
|
||||||
|
print("YAP Execution Error: {0}".format(err))
|
||||||
|
except ValueError:
|
||||||
|
print("Could not convert data to an integer.")
|
||||||
|
except:
|
||||||
|
print("Unexpected error:", sys.exc_info()[0])
|
||||||
|
raise
|
||||||
|
engine.close()
|
||||||
|
#
|
||||||
|
# initialize engine
|
||||||
|
# engine = yap.YAPEngine();
|
||||||
|
# engine = yap.YAPEngine(yap.YAPParams());
|
||||||
|
#
|
||||||
|
def __init__(self, engine, **kwargs):
|
||||||
|
self.live(engine)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
engine = Engine()
|
||||||
|
handler = numbervars
|
||||||
|
YAPShell(engine)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
engine = boot_yap()
|
main()
|
||||||
handler = numbervars
|
|
||||||
live()
|
|
||||||
|
@ -1,12 +1,19 @@
|
|||||||
drye%% @file yapi.yap
|
%% @file yapi.yap
|
||||||
%% @brief support yap shell
|
%% @brief support yap shell
|
||||||
%%
|
%%
|
||||||
:- module(yapi, [python_query/2,
|
|
||||||
|
% :- yap_flag(verbose, verbose).
|
||||||
|
|
||||||
|
:- use_module( library(python) ).
|
||||||
|
|
||||||
|
:- module(yapi, [
|
||||||
python_ouput/0,
|
python_ouput/0,
|
||||||
show_answer/2,
|
show_answer/2,
|
||||||
show_answer/3,
|
show_answer/3,
|
||||||
yap_query/4,
|
yap_query/4,
|
||||||
yapi_query/2]).
|
python_query/2,
|
||||||
|
yapi_query/2
|
||||||
|
]).
|
||||||
|
|
||||||
:- use_module( library(lists) ).
|
:- use_module( library(lists) ).
|
||||||
:- use_module( library(maplist) ).
|
:- use_module( library(maplist) ).
|
||||||
@ -14,102 +21,49 @@ drye%% @file yapi.yap
|
|||||||
:- use_module( library(terms) ).
|
:- use_module( library(terms) ).
|
||||||
:- use_module( library(python) ).
|
:- use_module( library(python) ).
|
||||||
|
|
||||||
|
:- python_import(yap4py.yapi).
|
||||||
%% @pred yap_query(sGoal, + VarList, +OutStream, - Dictionary)
|
|
||||||
%% @pred yap_query(0:Goal, + VarList, - Dictionary)
|
|
||||||
%%
|
|
||||||
%% dictionary, Examples
|
|
||||||
%%
|
|
||||||
%%
|
|
||||||
python_query( String, D ) :-
|
|
||||||
atomic_to_term( String, Goal, VarNames ),
|
|
||||||
yap_query( Goal, VarNames, user_error, Dict),
|
|
||||||
D := Dict,
|
|
||||||
yap4py.yapi.bindings := Dict.
|
|
||||||
|
|
||||||
%% @pred yapi_query( + VarList, - Dictionary)
|
%% @pred yapi_query( + VarList, - Dictionary)
|
||||||
%%
|
%%
|
||||||
%% dictionary, Examples
|
%% dictionary, Examples
|
||||||
%%
|
%%
|
||||||
%%
|
%%
|
||||||
yapi_query( VarNames, Dict ) :-
|
yapi_query( VarNames, Self ) :-
|
||||||
show_answer(VarNames, Dict).
|
show_answer(VarNames, Dict),
|
||||||
|
Self.bindings := Dict.
|
||||||
|
|
||||||
|
:- initialization set_preds.
|
||||||
|
|
||||||
|
set_preds :-
|
||||||
%% @pred yap_query(0:Goal, + VarList, +OutStream, - Dictionary)
|
current_predicate(P, Q),
|
||||||
%% @pred yap_query(0:Goal, + VarList, - Dictionary)
|
functor(Q,P,A),
|
||||||
%%
|
atom_string(P,S),
|
||||||
%% dictionary, Examples
|
:= yap4py.yapi.named( S, A),
|
||||||
%%
|
|
||||||
%%
|
|
||||||
yap_query( Goal, VarNames, Stream, Dictionary) :-
|
|
||||||
(
|
|
||||||
call(Goal)
|
|
||||||
*->
|
|
||||||
!,
|
|
||||||
show_answer(VarNames, Stream, Dictionary)
|
|
||||||
).
|
|
||||||
|
|
||||||
yap_query( VarNames, Dictionary) :-
|
|
||||||
yap_query( VarNames, user_output, Dictionary).
|
|
||||||
|
|
||||||
show_answer(QVs0, Dict) :-
|
|
||||||
show_answer(QVs0, user_error, Dict).
|
|
||||||
|
|
||||||
show_answer(QVs0, Stream, Dict) :-
|
|
||||||
copy_term(QVs0, QVs),
|
|
||||||
copy_term(QVs0, QVs1),
|
|
||||||
rb_new(RB),
|
|
||||||
foldl2(bind_qv, QVs, QVs1, [], LP, {}-RB, Dict-_),
|
|
||||||
!,
|
|
||||||
term_variables(QVs, IVs),
|
|
||||||
term_variables(QVs1, IVs1),
|
|
||||||
foldl( enumerate, IVs, IVs1, 1, _ ),
|
|
||||||
out(LP, Stream ).
|
|
||||||
show_answer(_, _, {}) :-
|
|
||||||
format(' yes.~n', [] ).
|
|
||||||
|
|
||||||
bind_qv(V=V0, V1 = V01, Vs, Vs, Vs1-RB, Vs1-RB) :-
|
|
||||||
var(V0),
|
|
||||||
!,
|
|
||||||
'$VAR'(V) = V0,
|
|
||||||
V1 = V01.
|
|
||||||
% atom_string(V1, V01).
|
|
||||||
bind_qv(V='$VAR'(Vi), V1=S1, Vs, [V='$VAR'(Vi)|Vs], D0-RB, D-RB) :- !,
|
|
||||||
add2dict(D0, V1:S1, D).
|
|
||||||
bind_qv(V=S, V1=S1, Vs, [V=S|Vs], D0-RB0, D-RB0) :-
|
|
||||||
% fix_tree( S, SS, S1, SS1, RB0, RBT),
|
|
||||||
add2dict(D0, V1:S1, D).
|
|
||||||
|
|
||||||
|
|
||||||
add2dict({}, B, {B}).
|
|
||||||
add2dict({C}, B, {B,C}).
|
|
||||||
|
|
||||||
enumerate('$VAR'(A), A, I, I1) :-
|
|
||||||
enum(I, Chars),
|
|
||||||
atom_codes(A,[0'_|Chars]),
|
|
||||||
I1 is I + 1.
|
|
||||||
|
|
||||||
enum(I, [C]) :-
|
|
||||||
I < 26,
|
|
||||||
!,
|
|
||||||
C is "A" + I.
|
|
||||||
enum(I, [C|Cs]) :-
|
|
||||||
J is I//26,
|
|
||||||
K is I mod 26,
|
|
||||||
C is "A" +K,
|
|
||||||
enum(J, Cs).
|
|
||||||
|
|
||||||
out(Bs, S) :-
|
|
||||||
output(Bs, S),
|
|
||||||
!.
|
|
||||||
out([_|Bs], S) :-
|
|
||||||
out(Bs, S).
|
|
||||||
|
|
||||||
output([V=B], S) :-
|
|
||||||
!,
|
|
||||||
format(S, '~a = ~q~n', [V, B]).
|
|
||||||
output([V=B|_Ns], S) :-
|
|
||||||
format( S, '~a = ~q.~n', [V, B]),
|
|
||||||
fail.
|
fail.
|
||||||
|
set_preds :-
|
||||||
|
system_predicate(P/A),
|
||||||
|
atom_string(P,S),
|
||||||
|
:= yap4py.yapi.named( S, A),
|
||||||
|
fail.
|
||||||
|
set_preds.
|
||||||
|
|
||||||
|
argi(N,I,I1) :-
|
||||||
|
atomic_concat(`A`,I,N),
|
||||||
|
I1 is I+1.
|
||||||
|
|
||||||
|
python_query( Self, String ) :-
|
||||||
|
yap_flag(typein_module, Mod),
|
||||||
|
atomic_to_term( String, Goal, VarNames ),
|
||||||
|
query_to_answer( Mod:Goal, VarNames, Status, Bindings),
|
||||||
|
maplist(in_dict(Self.bindings), Bindings),
|
||||||
|
write_query_answer( Bindings ),
|
||||||
|
nl( user_error ),
|
||||||
|
Self.port := Status.
|
||||||
|
|
||||||
|
in_dict(Dict, var([V0,V|Vs])) :- !,
|
||||||
|
Dict[V] := V0,
|
||||||
|
in_dict( Dict, var([V0|Vs])).
|
||||||
|
in_dict(Dict, nonvar([V0|Vs],G)) :- !,
|
||||||
|
Dict[V0] := G,
|
||||||
|
in_dict( Dict, var([V0|Vs])).
|
||||||
|
in_dict(_, _).
|
||||||
|
@ -49,9 +49,13 @@
|
|||||||
|
|
||||||
configure_file(setup.py.in ${CMAKE_CURRENT_BINARY_DIR}/setup.py)
|
configure_file(setup.py.in ${CMAKE_CURRENT_BINARY_DIR}/setup.py)
|
||||||
|
|
||||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources)
|
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources )
|
||||||
file( GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/logo-32x32.png INPUT ${CMAKE_SOURCE_DIR}/docs/icons/yap_32x32x32.png )
|
file( COPY ${CMAKE_SOURCE_DIR}/docs/icons/yap_32x32x32.png
|
||||||
file( GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/logo-64x64.png INPUT ${CMAKE_SOURCE_DIR}/docs/icons/yap_64x64x32.png )
|
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/ )
|
||||||
|
file( RENAME ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/yap_32x32x32.png ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/logo-32x32.png )
|
||||||
|
file( COPY ${CMAKE_SOURCE_DIR}/docs/icons/yap_64x64x32.png DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources )
|
||||||
|
file( RENAME ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/yap_64x64x32.png ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/logo-64x64.png )
|
||||||
|
file( COPY ${CMAKE_CURRENT_SOURCE_DIR}/kernel.js DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/ )
|
||||||
file( COPY ${CMAKE_SOURCE_DIR}/misc/editors/prolog.js DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/)
|
file( COPY ${CMAKE_SOURCE_DIR}/misc/editors/prolog.js DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/yap_kernel/resources/)
|
||||||
|
|
||||||
set(SETUP_PY ${CMAKE_CURRENT_BINARY_DIR}/setup.py)
|
set(SETUP_PY ${CMAKE_CURRENT_BINARY_DIR}/setup.py)
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
#include COPYING.md
|
#include COPYING.md
|
||||||
#include CONTRIBUTING.md
|
#include CONTRIBUTING.md
|
||||||
include README.md
|
include README.md
|
||||||
|
include yap_kernel/resources/logo-32x32.png
|
||||||
|
include yap_kernel/resources/logo-64x64.png
|
||||||
|
include yap_kernel/resources/kernel.js
|
||||||
|
include yap_kernel/resources/kernel.json
|
||||||
|
|
||||||
|
|
||||||
# Documentation
|
# Documentation
|
||||||
|
0
packages/python/yap_kernel/__init__.py
Normal file
0
packages/python/yap_kernel/__init__.py
Normal file
@ -14,6 +14,7 @@ name = 'yap_kernel'
|
|||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
import sysconfig
|
||||||
import setuptools
|
import setuptools
|
||||||
|
|
||||||
v = sys.version_info
|
v = sys.version_info
|
||||||
@ -43,8 +44,10 @@ packages = setuptools.find_packages('${CMAKE_CURRENT_SOURCE_DIR}')
|
|||||||
# if os.path.exists(pjoin(d, '__init__.py')):
|
# if os.path.exists(pjoin(d, '__init__.py')):
|
||||||
# packages.append(d[len(here)+1:].replace(os.path.sep, '.'))
|
# packages.append(d[len(here)+1:].replace(os.path.sep, '.'))
|
||||||
|
|
||||||
|
sys.path.insert(0, "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
package_data = {
|
package_data = {
|
||||||
'yap_kernel': ['resources/*.*','prolog/*.*'],
|
'yap_ipython': ['prolog/*.*'],
|
||||||
|
'yap_kernel': ['resources/*.*']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -62,9 +65,9 @@ setup_args = dict(
|
|||||||
packages = packages,
|
packages = packages,
|
||||||
py_modules = ['yap_kernel_launcher'],
|
py_modules = ['yap_kernel_launcher'],
|
||||||
package_data = package_data,
|
package_data = package_data,
|
||||||
package_dir = {'':"${CMAKE_CURRENT_SOURCE_DIR}" },
|
package_dir = {'':"${CMAKE_CURRENT_SOURCE_DIR}"},
|
||||||
description = "YAP Kernel for Jupyter",
|
description = "YAP Kernel for Jupyter",
|
||||||
author = 'YP Development Team',
|
author = 'YAP Development Team',
|
||||||
author_email = 'YAP-dev@scipy.org',
|
author_email = 'YAP-dev@scipy.org',
|
||||||
url = 'http://ipython.org',
|
url = 'http://ipython.org',
|
||||||
license = 'BSD',
|
license = 'BSD',
|
||||||
@ -91,15 +94,26 @@ install_requires = setuptools_args['install_requires'] = [
|
|||||||
if any(a.startswith(('bdist', 'build', 'install')) for a in sys.argv):
|
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
|
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='python')
|
||||||
dest = os.path.join(here, 'data_kernelspec')
|
dest = os.path.join(here, 'resources')
|
||||||
if os.path.exists(dest):
|
if os.path.exists(dest):
|
||||||
shutil.rmtree(dest)
|
shutil.rmtree(dest)
|
||||||
write_kernel_spec(dest, overrides={'argv': argv})
|
write_kernel_spec(dest, overrides={'argv': argv})
|
||||||
|
shutil.copy('${CMAKE_CURRENT_SOURCE_DIR}/kernel.js',dest)
|
||||||
|
shutil.copy('${CMAKE_SOURCE_DIR}/misc/editors/prolog.js',dest)
|
||||||
|
shutil.copy('${CMAKE_SOURCE_DIR}/docs/icons/yap_32x32x32.png',os.path.join(dest,'logo-32x32.png'))
|
||||||
|
shutil.copy('${CMAKE_SOURCE_DIR}/docs/icons/yap_64x64x32.png',os.path.join(dest,'logo-64x64.png'))
|
||||||
setup_args['data_files'] = [
|
setup_args['data_files'] = [
|
||||||
(pjoin('share', 'jupyter', 'kernels', KERNEL_NAME), glob(pjoin(dest, '*'))),
|
(pjoin('share', 'jupyter', 'kernels', KERNEL_NAME), glob(pjoin(dest, '*'))),
|
||||||
]
|
]
|
||||||
|
mode_loc = pjoin( sysconfig.get_path('platlib'), 'notebook', 'static', 'components', 'codemirror', 'mode', 'prolog')
|
||||||
|
try:
|
||||||
|
os.mkdir(mode_loc)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
shutil.copy( "${CMAKE_SOURCE_DIR}/misc/editors/prolog.js" , mode_loc)
|
||||||
|
|
||||||
|
|
||||||
extras_require = setuptools_args['extras_require'] = {
|
extras_require = setuptools_args['extras_require'] = {
|
||||||
'test:python_version=="2.7"': ['mock'],
|
'test:python_version=="2.7"': ['mock'],
|
||||||
|
@ -0,0 +1,151 @@
|
|||||||
|
# encoding: utf-8
|
||||||
|
"""
|
||||||
|
IPython: tools for interactive and parallel computing in Python.
|
||||||
|
|
||||||
|
http://ipython.org
|
||||||
|
"""
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Copyright (c) 2008-2011, IPython Development Team.
|
||||||
|
# Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
|
||||||
|
# Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
|
||||||
|
# Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
|
||||||
|
#
|
||||||
|
# Distributed under the terms of the Modified BSD License.
|
||||||
|
#
|
||||||
|
# The full license is in the file COPYING.txt, distributed with this software.
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Imports
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Setup everything
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Don't forget to also update setup.py when this changes!
|
||||||
|
if sys.version_info < (3,3):
|
||||||
|
raise ImportError(
|
||||||
|
"""
|
||||||
|
IPython 6.0+ does not support Python 2.6, 2.7, 3.0, 3.1, or 3.2.
|
||||||
|
When using Python 2.7, please install IPython 5.x LTS Long Term Support version.
|
||||||
|
Beginning with IPython 6.0, Python 3.3 and above is required.
|
||||||
|
|
||||||
|
See IPython `README.rst` file for more information:
|
||||||
|
|
||||||
|
https://github.com/ipython/ipython/blob/master/README.rst
|
||||||
|
|
||||||
|
""")
|
||||||
|
|
||||||
|
# Make it easy to import extensions - they are always directly on pythonpath.
|
||||||
|
# Therefore, non-IPython modules can be added to extensions directory.
|
||||||
|
# This should probably be in ipapp.py.
|
||||||
|
sys.path.append(os.path.join(os.path.dirname(__file__), "extensions"))
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Setup the top level names
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
from .core.getipython import get_ipython
|
||||||
|
from .core import release
|
||||||
|
from IPython.core.application import Application
|
||||||
|
from IPython.terminal.embed import embed
|
||||||
|
|
||||||
|
from .core.interactiveshell import YAPInteractive as InteractiveShell
|
||||||
|
from IPython.testing import test
|
||||||
|
from IPython.utils.sysinfo import sys_info
|
||||||
|
from IPython.utils.frame import extract_module_locals
|
||||||
|
|
||||||
|
# Release data
|
||||||
|
__author__ = '%s <%s>' % (release.author, release.author_email)
|
||||||
|
__license__ = release.license
|
||||||
|
__version__ = release.version
|
||||||
|
version_info = release.version_info
|
||||||
|
|
||||||
|
def embed_kernel(module=None, local_ns=None, **kwargs):
|
||||||
|
"""Embed and start an IPython kernel in a given scope.
|
||||||
|
|
||||||
|
If you don't want the kernel to initialize the namespace
|
||||||
|
from the scope of the surrounding function,
|
||||||
|
and/or you want to load full IPython configuration,
|
||||||
|
you probably want `IPython.start_kernel()` instead.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
module : ModuleType, optional
|
||||||
|
The module to load into IPython globals (default: caller)
|
||||||
|
local_ns : dict, optional
|
||||||
|
The namespace to load into IPython user namespace (default: caller)
|
||||||
|
|
||||||
|
kwargs : various, optional
|
||||||
|
Further keyword args are relayed to the IPKernelApp constructor,
|
||||||
|
allowing configuration of the Kernel. Will only have an effect
|
||||||
|
on the first embed_kernel call for a given process.
|
||||||
|
"""
|
||||||
|
|
||||||
|
(caller_module, caller_locals) = extract_module_locals(1)
|
||||||
|
if module is None:
|
||||||
|
module = caller_module
|
||||||
|
if local_ns is None:
|
||||||
|
local_ns = caller_locals
|
||||||
|
|
||||||
|
# Only import .zmq when we really need it
|
||||||
|
from ipykernel.embed import embed_kernel as real_embed_kernel
|
||||||
|
real_embed_kernel(module=module, local_ns=local_ns, **kwargs)
|
||||||
|
|
||||||
|
def start_ipython(argv=None, **kwargs):
|
||||||
|
"""Launch a normal IPython instance (as opposed to embedded)
|
||||||
|
|
||||||
|
`IPython.embed()` puts a shell in a particular calling scope,
|
||||||
|
such as a function or method for debugging purposes,
|
||||||
|
which is often not desirable.
|
||||||
|
|
||||||
|
`start_ipython()` does full, regular IPython initialization,
|
||||||
|
including loading startup files, configuration, etc.
|
||||||
|
much of which is skipped by `embed()`.
|
||||||
|
|
||||||
|
This is a public API method, and will survive implementation changes.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
|
||||||
|
argv : list or None, optional
|
||||||
|
If unspecified or None, IPython will parse command-line options from sys.argv.
|
||||||
|
To prevent any command-line parsing, pass an empty list: `argv=[]`.
|
||||||
|
user_ns : dict, optional
|
||||||
|
specify this dictionary to initialize the IPython user namespace with particular values.
|
||||||
|
kwargs : various, optional
|
||||||
|
Any other kwargs will be passed to the Application constructor,
|
||||||
|
such as `config`.
|
||||||
|
"""
|
||||||
|
from IPython.terminal.ipapp import launch_new_instance
|
||||||
|
return launch_new_instance(argv=argv, **kwargs)
|
||||||
|
|
||||||
|
def start_kernel(argv=None, **kwargs):
|
||||||
|
"""Launch a normal IPython kernel instance (as opposed to embedded)
|
||||||
|
|
||||||
|
`IPython.embed_kernel()` puts a shell in a particular calling scope,
|
||||||
|
such as a function or method for debugging purposes,
|
||||||
|
which is often not desirable.
|
||||||
|
|
||||||
|
`start_kernel()` does full, regular IPython initialization,
|
||||||
|
including loading startup files, configuration, etc.
|
||||||
|
much of which is skipped by `embed()`.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
|
||||||
|
argv : list or None, optional
|
||||||
|
If unspecified or None, IPython will parse command-line options from sys.argv.
|
||||||
|
To prevent any command-line parsing, pass an empty list: `argv=[]`.
|
||||||
|
user_ns : dict, optional
|
||||||
|
specify this dictionary to initialize the IPython user namespace with particular values.
|
||||||
|
kwargs : various, optional
|
||||||
|
Any other kwargs will be passed to the Application constructor,
|
||||||
|
such as `config`.
|
||||||
|
"""
|
||||||
|
from IPython.kernel.zmq.kernelapp import launch_new_instance
|
||||||
|
return launch_new_instance(argv=argv, **kwargs)
|
@ -0,0 +1,20 @@
|
|||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Copyright (C) 2013 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.
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Classes and functions
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
def get_ipython():
|
||||||
|
"""Get the global InteractiveShell instance.
|
||||||
|
|
||||||
|
Returns None if no InteractiveShell instance is registered.
|
||||||
|
"""
|
||||||
|
from yap_ipython.core.interactiveshell import YAPInteractive
|
||||||
|
if YAPInteractive.initialized():
|
||||||
|
return YAPInteractive.instance()
|
397
packages/python/yap_kernel/yap_ipython/core/interactiveshell.py
Normal file
397
packages/python/yap_kernel/yap_ipython/core/interactiveshell.py
Normal file
@ -0,0 +1,397 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import abc
|
||||||
|
|
||||||
|
import yap4py.yapi
|
||||||
|
from IPython.core import interactiveshell
|
||||||
|
from IPython.core.completer import IPCompleter
|
||||||
|
from IPython.core.interactiveshell import ExecutionResult, InteractiveShell
|
||||||
|
from IPython.utils.strdispatch import StrDispatch
|
||||||
|
# import yap_ipython.core
|
||||||
|
from traitlets import Instance
|
||||||
|
|
||||||
|
from pygments import highlight
|
||||||
|
from pygments.lexers.prolog import PrologLexer
|
||||||
|
from pygments.formatters import HtmlFormatter
|
||||||
|
|
||||||
|
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
|
use_module = namedtuple('use_module', 'file')
|
||||||
|
bindvars = namedtuple('bindvars', 'list')
|
||||||
|
library = namedtuple('library', 'list')
|
||||||
|
v = namedtuple('_', 'slot')
|
||||||
|
load_files = namedtuple('load_files', 'file ofile args')
|
||||||
|
python_query= namedtuple('python_query', 'query_mgr string')
|
||||||
|
jupyter_query = namedtuple('jupyter_query', 'self string')
|
||||||
|
enter_cell = namedtuple('enter_cell', 'self' )
|
||||||
|
exit_cell = namedtuple('exit_cell', 'self' )
|
||||||
|
completions = namedtuple('completions', 'txt self' )
|
||||||
|
|
||||||
|
class YAPCompleter:
|
||||||
|
|
||||||
|
def __init__(self, engine):
|
||||||
|
self.yapeng = engine
|
||||||
|
self.completions = None
|
||||||
|
|
||||||
|
def complete(self, text, line=None, cursor_pos=None):
|
||||||
|
"""Return the completed text and a list of completions.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
|
||||||
|
text : string
|
||||||
|
A string of text to be completed on. It can be given as empty and
|
||||||
|
instead a line/position pair are given. In this case, the
|
||||||
|
completer itself will split the line like readline does.
|
||||||
|
|
||||||
|
line : string, optional
|
||||||
|
The complete line that text is part of.
|
||||||
|
|
||||||
|
cursor_pos : int, optional
|
||||||
|
The position of the cursor on the input line.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
text : string
|
||||||
|
The actual text that was completed.
|
||||||
|
|
||||||
|
matches : list
|
||||||
|
A sorted list with all possible completions.
|
||||||
|
|
||||||
|
The optional arguments allow the completion to take more context into
|
||||||
|
account, and are part of the low-level completion API.
|
||||||
|
|
||||||
|
This is a wrapper around the completion mechanism, similar to what
|
||||||
|
readline does at the command line when the TAB key is hit. By
|
||||||
|
exposing it as a method, it can be used by other non-readline
|
||||||
|
environments (such as GUIs) for text completion.
|
||||||
|
|
||||||
|
Simple usage example:
|
||||||
|
|
||||||
|
In [1]: x = 'hello'
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# def _init__(self, **kwargs) -> None:
|
||||||
|
# PyCompleter.__init__(**kwargs__)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class YAPInteractive(InteractiveShell):
|
||||||
|
"""An enhanced, interactive shell for YAP."""
|
||||||
|
|
||||||
|
def init_yap_completer(self):
|
||||||
|
"""Initialize the completion machinery.
|
||||||
|
|
||||||
|
This creates completion machinery that can be used by client code,
|
||||||
|
either interactively in-process (typically triggered by the readline
|
||||||
|
library), programmatically (such as in test suites) or out-of-process
|
||||||
|
(typically over the network by remote frontends).
|
||||||
|
"""
|
||||||
|
print(self)
|
||||||
|
|
||||||
|
# Add custom completers to the basic ones built into IPCompleter
|
||||||
|
self.Completer = YAPCompleter(self.yapeng)
|
||||||
|
self.configurables.append(self.Completer)
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(YAPInteractive, self).__init__(**kwargs)
|
||||||
|
# type: (object, object) -> object
|
||||||
|
pjoin = os.path.join
|
||||||
|
here = os.path.dirname(__file__)
|
||||||
|
self.yapeng = yap4py.yapi.Engine()
|
||||||
|
self.yapeng.goal(use_module(pjoin(here, '../prolog/jupyter.yap')))
|
||||||
|
self.q = None
|
||||||
|
self.run = False
|
||||||
|
self.os = ""
|
||||||
|
self.port = None
|
||||||
|
self.init_yap_completer()
|
||||||
|
|
||||||
|
def init_syntax_highlighting(self, changes=None):
|
||||||
|
# Python source parser/formatter for syntax highlighting
|
||||||
|
# pyformat = PyColorize.Parser(style=self.colors, parent=self).format
|
||||||
|
# self.pycolorize = lambda src: pyformat(src,'str')
|
||||||
|
self.pycolorize = lambda code : highlight(code, PrologLexer(), HtmlFormatter())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def complete(self, text, line=None, cursor_pos=None):
|
||||||
|
"""Return the completed text and a list of completions.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
|
||||||
|
text : string
|
||||||
|
A string of text to be completed on. It can be given as empty and
|
||||||
|
instead a line/position pair are given. In this case, the
|
||||||
|
completer itself will split the line like readline does.
|
||||||
|
|
||||||
|
line : string, optional
|
||||||
|
The complete line that text is part of.
|
||||||
|
|
||||||
|
cursor_pos : int, optional
|
||||||
|
The position of the cursor on the input line.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
text : string
|
||||||
|
The actual text that was completed.
|
||||||
|
|
||||||
|
matches : list
|
||||||
|
A sorted list with all possible completions.
|
||||||
|
|
||||||
|
The optional arguments allow the completion to take more context into
|
||||||
|
account, and are part of the low-level completion API.
|
||||||
|
|
||||||
|
This is a wrapper around the completion mechanism, similar to what
|
||||||
|
readline does at the command line when the TAB key is hit. By
|
||||||
|
exposing it as a method, it can be used by other non-readline
|
||||||
|
environments (such as GUIs) for text completion.
|
||||||
|
|
||||||
|
Simple usage example:
|
||||||
|
|
||||||
|
In [1]: x = 'hello'
|
||||||
|
|
||||||
|
In [2]: _ip.complete('x.l')
|
||||||
|
Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Inject names into __builtin__ so we can complete on the added names.
|
||||||
|
return self.Completer.complete(text, line, cursor_pos)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def run_cell(self, raw_cell, store_history=True, silent=False,
|
||||||
|
shell_futures=True):
|
||||||
|
"""Run a complete IPython cell.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
raw_cell : str
|
||||||
|
The code (including IPython code such as
|
||||||
|
%magic functions) to run.
|
||||||
|
store_history : bool
|
||||||
|
If True, the raw and translated cell will be stored in IPython's
|
||||||
|
history. For user code calling back into
|
||||||
|
IPython's machinery, this
|
||||||
|
should be set to False.
|
||||||
|
silent : bool
|
||||||
|
If True, avoid side-effects, such as implicit displayhooks and
|
||||||
|
and logging. silent=True forces store_history=False.
|
||||||
|
shell_futures : bool
|
||||||
|
If True, the code will share future statements with the interactive
|
||||||
|
shell. It will both be affected by previous
|
||||||
|
__future__ imports, and any __future__ imports in the code
|
||||||
|
will affect the shell. If False,
|
||||||
|
__future__ imports are not shared in either direction.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
|
||||||
|
-------
|
||||||
|
|
||||||
|
`result : :class:`ExecutionResult`
|
||||||
|
"""
|
||||||
|
|
||||||
|
# construct a query from a one-line string
|
||||||
|
# q is opaque to Python
|
||||||
|
# vs is the list of variables
|
||||||
|
# you can print it out, the left-side is the variable name,
|
||||||
|
# the right side wraps a handle to a variable
|
||||||
|
# pdb.set_trace()
|
||||||
|
# #pdb.set_trace()
|
||||||
|
# atom match either symbols, or if no symbol exists, strings, In this case
|
||||||
|
# variable names should match strings
|
||||||
|
# ask = True
|
||||||
|
# launch the query
|
||||||
|
result = ExecutionResult()
|
||||||
|
|
||||||
|
if (not raw_cell) or raw_cell.isspace():
|
||||||
|
self.last_execution_succeeded = True
|
||||||
|
return result
|
||||||
|
|
||||||
|
if silent:
|
||||||
|
store_history = False
|
||||||
|
|
||||||
|
if store_history:
|
||||||
|
result.execution_count = self.execution_count
|
||||||
|
|
||||||
|
def error_before_exec(value):
|
||||||
|
result.error_before_exec = value
|
||||||
|
self.last_execution_succeeded = False
|
||||||
|
return result
|
||||||
|
|
||||||
|
self.events.trigger('pre_execute')
|
||||||
|
if not silent:
|
||||||
|
self.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 = raw_cell #self.input_transformer_manager.transform_cell(raw_cell)
|
||||||
|
# except SyntaxError:
|
||||||
|
# preprocessing_exc_tuple = 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:
|
||||||
|
# try:
|
||||||
|
# # use prefilter_lines to handle trailing newlines
|
||||||
|
# # restore trailing newline for ast.parse
|
||||||
|
# cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
|
||||||
|
# except Exception:
|
||||||
|
# # don't allow prefilter errors to crash IPython
|
||||||
|
# preprocessing_exc_tuple = sys.exc_info()
|
||||||
|
|
||||||
|
|
||||||
|
# Store raw and processed history
|
||||||
|
if store_history:
|
||||||
|
self.history_manager.store_inputs(self.execution_count,
|
||||||
|
cell, raw_cell)
|
||||||
|
if not silent:
|
||||||
|
self.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
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
if cell[0] == '%':
|
||||||
|
if cell[1] == '%':
|
||||||
|
linec = False
|
||||||
|
mcell = cell.lstrip('%%')
|
||||||
|
else:
|
||||||
|
linec = True
|
||||||
|
mcell = cell.lstrip('%')
|
||||||
|
txt0 = mcell.split(maxsplit = 2, sep = '\n')
|
||||||
|
txt = txt0[0].split(maxsplit = 2)
|
||||||
|
magic = txt[0]
|
||||||
|
if len(txt) == 2:
|
||||||
|
line = txt[1]
|
||||||
|
else:
|
||||||
|
line = ""
|
||||||
|
if linec:
|
||||||
|
self.run_line_magic(magic, line)
|
||||||
|
if len(txt0) == 2:
|
||||||
|
cell = txt0[1]
|
||||||
|
else:
|
||||||
|
cellArea = ""
|
||||||
|
else:
|
||||||
|
self.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
|
||||||
|
has_raised = False
|
||||||
|
try:
|
||||||
|
self.bindings = dict = {}
|
||||||
|
state = self.jupyter_query(cell)
|
||||||
|
if state:
|
||||||
|
self.last_execution_succeeded = True
|
||||||
|
result.result = (True, dict)
|
||||||
|
else:
|
||||||
|
self.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
|
||||||
|
|
||||||
|
# Reset this so later displayed values do not modify the
|
||||||
|
# ExecutionResult
|
||||||
|
self.displayhook.exec_result = None
|
||||||
|
print(self.complete)
|
||||||
|
self.events.trigger('post_execute')
|
||||||
|
if not silent:
|
||||||
|
self.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)
|
||||||
|
# Each cell is a *single* input, regardless of how many lines it has
|
||||||
|
self.execution_count += 1
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
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 = {}
|
||||||
|
self.port = "call"
|
||||||
|
if self.q and s != self.os:
|
||||||
|
self.q.close()
|
||||||
|
self.q = None
|
||||||
|
if not self.q:
|
||||||
|
self.q = self.yapeng.query(jupyter_query(self, s))
|
||||||
|
self.os = s
|
||||||
|
# vs is the list of variables
|
||||||
|
# you can print it out, the left-side is the variable name,
|
||||||
|
# the right side wraps a handle to a variable
|
||||||
|
# pdb.set_trace()
|
||||||
|
# #pdb.set_trace()
|
||||||
|
# atom match either symbols, or if no symbol exists, sttrings, In this case
|
||||||
|
# variable names should match strings
|
||||||
|
#for eq in vs:
|
||||||
|
# if not isinstance(eq[0],str):
|
||||||
|
# print( "Error: Variable Name matches a Python Symbol")
|
||||||
|
# return
|
||||||
|
# ask = True
|
||||||
|
# launch the query
|
||||||
|
# run the new command using the given tracer
|
||||||
|
rc = self.answer(self.q)
|
||||||
|
if rc:
|
||||||
|
# deterministic = one solution
|
||||||
|
if self.port == "exit":
|
||||||
|
# done
|
||||||
|
self.q.close()
|
||||||
|
self.q = None
|
||||||
|
self.os = ""
|
||||||
|
print("yes")
|
||||||
|
return True, self.bindings
|
||||||
|
print("No (more) answers")
|
||||||
|
self.q.close()
|
||||||
|
self.q = None
|
||||||
|
return True, None
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
class YAPInteractiveABC(metaclass=abc.ABCMeta):
|
||||||
|
"""An abstract base class for YAPInteractive."""
|
||||||
|
|
||||||
|
YAPInteractiveABC.register(YAPInteractive)
|
13
packages/python/yap_kernel/yap_ipython/core/modulefind.py
Normal file
13
packages/python/yap_kernel/yap_ipython/core/modulefind.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
from modulefinder import ModuleFinder
|
||||||
|
|
||||||
|
finder = ModuleFinder()
|
||||||
|
finder.run_script('__main__.py')
|
||||||
|
|
||||||
|
print('Loaded modules:')
|
||||||
|
for name, mod in finder.modules.items():
|
||||||
|
print('%s: ' % name, end='')
|
||||||
|
print(','.join(list(mod.globalnames.keys())[:3]))
|
||||||
|
|
||||||
|
print('-'*50)
|
||||||
|
print('Modules not imported:')
|
||||||
|
print('\n'.join(finder.badmodules.keys()))
|
118
packages/python/yap_kernel/yap_ipython/core/release.py
Normal file
118
packages/python/yap_kernel/yap_ipython/core/release.py
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""Release data for the IPython project."""
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Copyright (c) 2008, IPython Development Team.
|
||||||
|
# Copyright (c) 2001, Fernando Perez <fernando.perez@colorado.edu>
|
||||||
|
# Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
|
||||||
|
# Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
|
||||||
|
#
|
||||||
|
# Distributed under the terms of the Modified BSD License.
|
||||||
|
#
|
||||||
|
# The full license is in the file COPYING.txt, distributed with this software.
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Name of the package for release purposes. This is the name which labels
|
||||||
|
# the tarballs and RPMs made by distutils, so it's best to lowercase it.
|
||||||
|
name = 'ipython'
|
||||||
|
|
||||||
|
# IPython version information. An empty _version_extra corresponds to a full
|
||||||
|
# release. 'dev' as a _version_extra string means this is a development
|
||||||
|
# version
|
||||||
|
_version_major = 0
|
||||||
|
_version_minor = 1
|
||||||
|
_version_patch = 0
|
||||||
|
_version_extra = '.dev'
|
||||||
|
# _version_extra = 'rc2'
|
||||||
|
_version_extra = '' # Uncomment this for full releases
|
||||||
|
|
||||||
|
# Construct full version string from these.
|
||||||
|
_ver = [_version_major, _version_minor, _version_patch]
|
||||||
|
|
||||||
|
__version__ = '.'.join(map(str, _ver))
|
||||||
|
if _version_extra:
|
||||||
|
__version__ = __version__ + _version_extra
|
||||||
|
|
||||||
|
version = __version__ # backwards compatibility name
|
||||||
|
version_info = (_version_major, _version_minor, _version_patch, _version_extra)
|
||||||
|
|
||||||
|
# Change this when incrementing the kernel protocol version
|
||||||
|
kernel_protocol_version_info = (5, 0)
|
||||||
|
kernel_protocol_version = "%i.%i" % kernel_protocol_version_info
|
||||||
|
|
||||||
|
description = "IPython: Productive Interactive Computing"
|
||||||
|
|
||||||
|
long_description = \
|
||||||
|
"""
|
||||||
|
IPython provides a rich toolkit to help you make the most out of using Python
|
||||||
|
interactively. Its main components are:
|
||||||
|
|
||||||
|
* A powerful interactive Python shell
|
||||||
|
* A `Jupyter <http://jupyter.org/>`_ kernel to work with Python code in Jupyter
|
||||||
|
notebooks and other interactive frontends.
|
||||||
|
|
||||||
|
The enhanced interactive Python shells have the following main features:
|
||||||
|
|
||||||
|
* Comprehensive object introspection.
|
||||||
|
|
||||||
|
* Input history, persistent across sessions.
|
||||||
|
|
||||||
|
* Caching of output results during a session with automatically generated
|
||||||
|
references.
|
||||||
|
|
||||||
|
* Extensible tab completion, with support by default for completion of python
|
||||||
|
variables and keywords, filenames and function keywords.
|
||||||
|
|
||||||
|
* Extensible system of 'magic' commands for controlling the environment and
|
||||||
|
performing many tasks related either to IPython or the operating system.
|
||||||
|
|
||||||
|
* A rich configuration system with easy switching between different setups
|
||||||
|
(simpler than changing $PYTHONSTARTUP environment variables every time).
|
||||||
|
|
||||||
|
* Session logging and reloading.
|
||||||
|
|
||||||
|
* Extensible syntax processing for special purpose situations.
|
||||||
|
|
||||||
|
* Access to the system shell with user-extensible alias system.
|
||||||
|
|
||||||
|
* Easily embeddable in other Python programs and GUIs.
|
||||||
|
|
||||||
|
* Integrated access to the pdb debugger and the Python profiler.
|
||||||
|
|
||||||
|
The latest development version is always available from IPython's `GitHub
|
||||||
|
site <http://github.com/ipython>`_.
|
||||||
|
"""
|
||||||
|
|
||||||
|
license = 'BSD'
|
||||||
|
|
||||||
|
authors = {'Fernando' : ('Fernando Perez','fperez.net@gmail.com'),
|
||||||
|
'Janko' : ('Janko Hauser','jhauser@zscout.de'),
|
||||||
|
'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'),
|
||||||
|
'Ville' : ('Ville Vainio','vivainio@gmail.com'),
|
||||||
|
'Brian' : ('Brian E Granger', 'ellisonbg@gmail.com'),
|
||||||
|
'Min' : ('Min Ragan-Kelley', 'benjaminrk@gmail.com'),
|
||||||
|
'Thomas' : ('Thomas A. Kluyver', 'takowl@gmail.com'),
|
||||||
|
'Jorgen' : ('Jorgen Stenarson', 'jorgen.stenarson@bostream.nu'),
|
||||||
|
'Matthias' : ('Matthias Bussonnier', 'bussonniermatthias@gmail.com'),
|
||||||
|
}
|
||||||
|
|
||||||
|
author = 'The IPython Development Team'
|
||||||
|
|
||||||
|
author_email = 'ipython-dev@python.org'
|
||||||
|
|
||||||
|
url = 'https://ipython.org'
|
||||||
|
|
||||||
|
|
||||||
|
platforms = ['Linux','Mac OSX','Windows']
|
||||||
|
|
||||||
|
keywords = ['Interactive','Interpreter','Shell', 'Embedding']
|
||||||
|
|
||||||
|
classifiers = [
|
||||||
|
'Framework :: IPython',
|
||||||
|
'Intended Audience :: Developers',
|
||||||
|
'Intended Audience :: Science/Research',
|
||||||
|
'License :: OSI Approved :: BSD License',
|
||||||
|
'Programming Language :: Python',
|
||||||
|
'Programming Language :: Python :: 3',
|
||||||
|
'Topic :: System :: Shells'
|
||||||
|
]
|
414
packages/python/yap_kernel/yap_ipython/core/shellapp.py
Normal file
414
packages/python/yap_kernel/yap_ipython/core/shellapp.py
Normal file
@ -0,0 +1,414 @@
|
|||||||
|
# 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
|
||||||
|
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
|
||||||
|
|
||||||
|
ENV_CONFIG_DIRS = []
|
||||||
|
_env_config_dir = os.path.join(sys.prefix, 'etc', 'ipython')
|
||||||
|
if _env_config_dir not in SYSTEM_CONFIG_DIRS:
|
||||||
|
# only add ENV_CONFIG if sys.prefix is not already included
|
||||||
|
ENV_CONFIG_DIRS.append(_env_config_dir)
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# 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
|
83
packages/python/yap_kernel/yap_ipython/prolog/jupyter.yap
Normal file
83
packages/python/yap_kernel/yap_ipython/prolog/jupyter.yap
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
|
||||||
|
:- use_module(library(yapi)).
|
||||||
|
|
||||||
|
:- use_module(library(python)).
|
||||||
|
|
||||||
|
:- python_import(sys).
|
||||||
|
|
||||||
|
jupyter_query(Self, Cell) :-
|
||||||
|
setup_call_cleanup(
|
||||||
|
enter_cell(Self),
|
||||||
|
python_query(Self, Cell),
|
||||||
|
exit_cell(Self)
|
||||||
|
).
|
||||||
|
|
||||||
|
enter_cell(_Self) :-
|
||||||
|
open('//python/sys.stdout', append, _Output, [alias(jupo)]),
|
||||||
|
open('//python/sys.stdout', append, _, [alias(jupe)]),
|
||||||
|
set_prolog_flag(user_output, jupo),
|
||||||
|
set_prolog_flag(user_error, jupe).
|
||||||
|
|
||||||
|
exit_cell(_Self) :-
|
||||||
|
close( jupo),
|
||||||
|
close( jupe).
|
||||||
|
|
||||||
|
|
||||||
|
completions(S, Self) :-
|
||||||
|
open(atom(S), read, St),
|
||||||
|
scan_to_list(St, Tokens),
|
||||||
|
reverse(Tokens, RTokens),
|
||||||
|
setof( Completion, complete(RTokens, Completion), Cs),
|
||||||
|
Self.completions := Cs.
|
||||||
|
|
||||||
|
complete( [atom(F)|LibRest], C) :-
|
||||||
|
LibRest = [l, atom(Where)|Consult],
|
||||||
|
isconsult(Consult, Rest),
|
||||||
|
\+ arg( Rest ),
|
||||||
|
check_library( F, Where, C).
|
||||||
|
complete( [atom(F)|Consult], C) :-
|
||||||
|
isconsult(Consult, Rest),
|
||||||
|
\+ arg( Rest ),
|
||||||
|
check_file( F, C).
|
||||||
|
complete( [atom(F)|Rest], C) :-
|
||||||
|
\+ arg( Rest ),
|
||||||
|
predicate( F, Pred, Arity ),
|
||||||
|
cont( Arity, Pred, C).
|
||||||
|
|
||||||
|
isconsult( [l, use_module| _Rest]).
|
||||||
|
isconsult( [l, ensure_loaded| _Rest]).
|
||||||
|
isconsult( [l, compile| _Rest]).
|
||||||
|
isconsult( [l, consult| _Rest]).
|
||||||
|
isconsult( [l, reconsult| _Rest]).
|
||||||
|
isconsult( [l, load_files| _Rest]).
|
||||||
|
isconsult( ['-', ']'| _Rest]).
|
||||||
|
isconsult( [']'| _Rest]).
|
||||||
|
|
||||||
|
arg(([']'|_]).
|
||||||
|
arg(([l|_]).
|
||||||
|
|
||||||
|
check_file(F,C) :-
|
||||||
|
atom_concat( F, '*' , Pat),
|
||||||
|
absolute_file_name( Pat, C0, [glob(true)] ),
|
||||||
|
atom_concat(['\'',C0,'\''], C).
|
||||||
|
|
||||||
|
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, P, P).
|
||||||
|
cont( _, P, PB ):-
|
||||||
|
atom_concat( P, '(', PB ).
|
@ -1,5 +1,16 @@
|
|||||||
|
import sys
|
||||||
|
import trace
|
||||||
|
|
||||||
|
# create a Trace object, telling it what to ignore, and whether to
|
||||||
|
# do tracing or line-counting or both.
|
||||||
|
tracer = trace.Trace(
|
||||||
|
# ignoredirs=[sys.prefix, sys.exec_prefix],
|
||||||
|
trace=1,
|
||||||
|
count=0)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
from yap_kernel import kernelapp as app
|
from yap_kernel import kernelapp as app
|
||||||
|
# tracer.run('app.launch_new_instance()')
|
||||||
app.launch_new_instance()
|
app.launch_new_instance()
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
from IPython.utils.py3compat import str_to_bytes
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
from subprocess import Popen, PIPE
|
from subprocess import Popen, PIPE
|
||||||
@ -13,7 +15,6 @@ import warnings
|
|||||||
from IPython.core.profiledir import ProfileDir
|
from IPython.core.profiledir import ProfileDir
|
||||||
from IPython.paths import get_ipython_dir
|
from IPython.paths import get_ipython_dir
|
||||||
from ipython_genutils.path import filefind
|
from ipython_genutils.path import filefind
|
||||||
from ipython_genutils.py3compat import str_to_bytes
|
|
||||||
|
|
||||||
import jupyter_client
|
import jupyter_client
|
||||||
from jupyter_client import write_connection_file
|
from jupyter_client import write_connection_file
|
||||||
@ -39,7 +40,7 @@ def get_connection_file(app=None):
|
|||||||
|
|
||||||
def find_connection_file(filename='kernel-*.json', profile=None):
|
def find_connection_file(filename='kernel-*.json', profile=None):
|
||||||
"""DEPRECATED: find a connection file, and return its absolute path.
|
"""DEPRECATED: find a connection file, and return its absolute path.
|
||||||
|
|
||||||
THIS FUNCION IS DEPRECATED. Use juptyer_client.find_connection_file instead.
|
THIS FUNCION IS DEPRECATED. Use juptyer_client.find_connection_file instead.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
@ -54,7 +55,7 @@ def find_connection_file(filename='kernel-*.json', profile=None):
|
|||||||
-------
|
-------
|
||||||
str : The absolute path of the connection file.
|
str : The absolute path of the connection file.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import warnings
|
import warnings
|
||||||
warnings.warn("""yap_kernel.find_connection_file is deprecated, use jupyter_client.find_connection_file""",
|
warnings.warn("""yap_kernel.find_connection_file is deprecated, use jupyter_client.find_connection_file""",
|
||||||
DeprecationWarning, stacklevel=2)
|
DeprecationWarning, stacklevel=2)
|
||||||
@ -77,13 +78,13 @@ def find_connection_file(filename='kernel-*.json', profile=None):
|
|||||||
# find profiledir by profile name:
|
# find profiledir by profile name:
|
||||||
profile_dir = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
|
profile_dir = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
|
||||||
security_dir = profile_dir.security_dir
|
security_dir = profile_dir.security_dir
|
||||||
|
|
||||||
return jupyter_client.find_connection_file(filename, path=['.', security_dir])
|
return jupyter_client.find_connection_file(filename, path=['.', security_dir])
|
||||||
|
|
||||||
|
|
||||||
def _find_connection_file(connection_file, profile=None):
|
def _find_connection_file(connection_file, profile=None):
|
||||||
"""Return the absolute path for a connection file
|
"""Return the absolute path for a connection file
|
||||||
|
|
||||||
- If nothing specified, return current Kernel's connection file
|
- If nothing specified, return current Kernel's connection file
|
||||||
- If profile specified, show deprecation warning about finding connection files in profiles
|
- If profile specified, show deprecation warning about finding connection files in profiles
|
||||||
- Otherwise, call jupyter_client.find_connection_file
|
- Otherwise, call jupyter_client.find_connection_file
|
||||||
|
941
packages/python/yap_kernel/yap_kernel/formatters.py
Normal file
941
packages/python/yap_kernel/yap_kernel/formatters.py
Normal file
@ -0,0 +1,941 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""Display formatters.
|
||||||
|
|
||||||
|
Inheritance diagram:
|
||||||
|
|
||||||
|
.. inheritance-diagram:: IPython.core.formatters
|
||||||
|
:parts: 3
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Copyright (c) IPython Development Team.
|
||||||
|
# Distributed under the terms of the Modified BSD License.
|
||||||
|
|
||||||
|
import abc
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
|
import warnings
|
||||||
|
from io import StringIO
|
||||||
|
|
||||||
|
from IPython.lib import pretty
|
||||||
|
from IPython.utils.dir2 import get_real_method
|
||||||
|
from IPython.utils.sentinel import Sentinel
|
||||||
|
from decorator import decorator
|
||||||
|
from traitlets import (
|
||||||
|
Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
|
||||||
|
ForwardDeclaredInstance,
|
||||||
|
default, observe,
|
||||||
|
)
|
||||||
|
from traitlets.config.configurable import Configurable
|
||||||
|
|
||||||
|
from packages.python.yap_kernel.core.yap_kernel.getipython import get_ipython
|
||||||
|
|
||||||
|
|
||||||
|
class DisplayFormatter(Configurable):
|
||||||
|
|
||||||
|
active_types = List(Unicode(),
|
||||||
|
help="""List of currently active mime-types to display.
|
||||||
|
You can use this to set a white-list for formats to display.
|
||||||
|
|
||||||
|
Most users will not need to change this value.
|
||||||
|
""").tag(config=True)
|
||||||
|
|
||||||
|
@default('active_types')
|
||||||
|
def _active_types_default(self):
|
||||||
|
return self.format_types
|
||||||
|
|
||||||
|
@observe('active_types')
|
||||||
|
def _active_types_changed(self, change):
|
||||||
|
for key, formatter in self.formatters.items():
|
||||||
|
if key in change['new']:
|
||||||
|
formatter.enabled = True
|
||||||
|
else:
|
||||||
|
formatter.enabled = False
|
||||||
|
|
||||||
|
ipython_display_formatter = ForwardDeclaredInstance('FormatterABC')
|
||||||
|
@default('ipython_display_formatter')
|
||||||
|
def _default_formatter(self):
|
||||||
|
return IPythonDisplayFormatter(parent=self)
|
||||||
|
|
||||||
|
# A dict of formatter whose keys are format types (MIME types) and whose
|
||||||
|
# values are subclasses of BaseFormatter.
|
||||||
|
formatters = Dict()
|
||||||
|
@default('formatters')
|
||||||
|
def _formatters_default(self):
|
||||||
|
"""Activate the default formatters."""
|
||||||
|
formatter_classes = [
|
||||||
|
PlainTextFormatter,
|
||||||
|
HTMLFormatter,
|
||||||
|
MarkdownFormatter,
|
||||||
|
SVGFormatter,
|
||||||
|
PNGFormatter,
|
||||||
|
PDFFormatter,
|
||||||
|
JPEGFormatter,
|
||||||
|
LatexFormatter,
|
||||||
|
JSONFormatter,
|
||||||
|
JavascriptFormatter
|
||||||
|
]
|
||||||
|
d = {}
|
||||||
|
for cls in formatter_classes:
|
||||||
|
f = cls(parent=self)
|
||||||
|
d[f.format_type] = f
|
||||||
|
return d
|
||||||
|
|
||||||
|
def format(self, obj, include=None, exclude=None):
|
||||||
|
"""Return a format data dict for an object.
|
||||||
|
|
||||||
|
By default all format types will be computed.
|
||||||
|
|
||||||
|
The following MIME types are currently implemented:
|
||||||
|
|
||||||
|
* text/plain
|
||||||
|
* text/html
|
||||||
|
* text/markdown
|
||||||
|
* text/latex
|
||||||
|
* application/json
|
||||||
|
* application/javascript
|
||||||
|
* application/pdf
|
||||||
|
* image/png
|
||||||
|
* image/jpeg
|
||||||
|
* image/svg+xml
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
obj : object
|
||||||
|
The Python object whose format data will be computed.
|
||||||
|
include : list or tuple, optional
|
||||||
|
A list of format type strings (MIME types) to include in the
|
||||||
|
format data dict. If this is set *only* the format types included
|
||||||
|
in this list will be computed.
|
||||||
|
exclude : list or tuple, optional
|
||||||
|
A list of format type string (MIME types) to exclude in the format
|
||||||
|
data dict. If this is set all format types will be computed,
|
||||||
|
except for those included in this argument.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
(format_dict, metadata_dict) : tuple of two dicts
|
||||||
|
|
||||||
|
format_dict is a dictionary of key/value pairs, one of each format that was
|
||||||
|
generated for the object. The keys are the format types, which
|
||||||
|
will usually be MIME type strings and the values and JSON'able
|
||||||
|
data structure containing the raw data for the representation in
|
||||||
|
that format.
|
||||||
|
|
||||||
|
metadata_dict is a dictionary of metadata about each mime-type output.
|
||||||
|
Its keys will be a strict subset of the keys in format_dict.
|
||||||
|
"""
|
||||||
|
format_dict = {}
|
||||||
|
md_dict = {}
|
||||||
|
|
||||||
|
if self.ipython_display_formatter(obj):
|
||||||
|
# object handled itself, don't proceed
|
||||||
|
return {}, {}
|
||||||
|
|
||||||
|
for format_type, formatter in self.formatters.items():
|
||||||
|
if include and format_type not in include:
|
||||||
|
continue
|
||||||
|
if exclude and format_type in exclude:
|
||||||
|
continue
|
||||||
|
|
||||||
|
md = None
|
||||||
|
try:
|
||||||
|
data = formatter(obj)
|
||||||
|
except:
|
||||||
|
# FIXME: log the exception
|
||||||
|
raise
|
||||||
|
|
||||||
|
# formatters can return raw data or (data, metadata)
|
||||||
|
if isinstance(data, tuple) and len(data) == 2:
|
||||||
|
data, md = data
|
||||||
|
|
||||||
|
if data is not None:
|
||||||
|
format_dict[format_type] = data
|
||||||
|
if md is not None:
|
||||||
|
md_dict[format_type] = md
|
||||||
|
|
||||||
|
return format_dict, md_dict
|
||||||
|
|
||||||
|
@property
|
||||||
|
def format_types(self):
|
||||||
|
"""Return the format types (MIME types) of the active formatters."""
|
||||||
|
return list(self.formatters.keys())
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Formatters for specific format types (text, html, svg, etc.)
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
def _safe_repr(obj):
|
||||||
|
"""Try to return a repr of an object
|
||||||
|
|
||||||
|
always returns a string, at least.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return repr(obj)
|
||||||
|
except Exception as e:
|
||||||
|
return "un-repr-able object (%r)" % e
|
||||||
|
|
||||||
|
|
||||||
|
class FormatterWarning(UserWarning):
|
||||||
|
"""Warning class for errors in formatters"""
|
||||||
|
|
||||||
|
@decorator
|
||||||
|
def catch_format_error(method, self, *args, **kwargs):
|
||||||
|
"""show traceback on failed format call"""
|
||||||
|
try:
|
||||||
|
r = method(self, *args, **kwargs)
|
||||||
|
except NotImplementedError:
|
||||||
|
# don't warn on NotImplementedErrors
|
||||||
|
return None
|
||||||
|
except Exception:
|
||||||
|
exc_info = sys.exc_info()
|
||||||
|
ip = get_ipython()
|
||||||
|
if ip is not None:
|
||||||
|
ip.showtraceback(exc_info)
|
||||||
|
else:
|
||||||
|
traceback.print_exception(*exc_info)
|
||||||
|
return None
|
||||||
|
return self._check_return(r, args[0])
|
||||||
|
|
||||||
|
|
||||||
|
class FormatterABC(metaclass=abc.ABCMeta):
|
||||||
|
""" Abstract base class for Formatters.
|
||||||
|
|
||||||
|
A formatter is a callable class that is responsible for computing the
|
||||||
|
raw format data for a particular format type (MIME type). For example,
|
||||||
|
an HTML formatter would have a format type of `text/html` and would return
|
||||||
|
the HTML representation of the object when called.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# The format type of the data returned, usually a MIME type.
|
||||||
|
format_type = 'text/plain'
|
||||||
|
|
||||||
|
# Is the formatter enabled...
|
||||||
|
enabled = True
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def __call__(self, obj):
|
||||||
|
"""Return a JSON'able representation of the object.
|
||||||
|
|
||||||
|
If the object cannot be formatted by this formatter,
|
||||||
|
warn and return None.
|
||||||
|
"""
|
||||||
|
return repr(obj)
|
||||||
|
|
||||||
|
|
||||||
|
def _mod_name_key(typ):
|
||||||
|
"""Return a (__module__, __name__) tuple for a type.
|
||||||
|
|
||||||
|
Used as key in Formatter.deferred_printers.
|
||||||
|
"""
|
||||||
|
module = getattr(typ, '__module__', None)
|
||||||
|
name = getattr(typ, '__name__', None)
|
||||||
|
return (module, name)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_type(obj):
|
||||||
|
"""Return the type of an instance (old and new-style)"""
|
||||||
|
return getattr(obj, '__class__', None) or type(obj)
|
||||||
|
|
||||||
|
|
||||||
|
_raise_key_error = Sentinel('_raise_key_error', __name__,
|
||||||
|
"""
|
||||||
|
Special value to raise a KeyError
|
||||||
|
|
||||||
|
Raise KeyError in `BaseFormatter.pop` if passed as the default value to `pop`
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
class BaseFormatter(Configurable):
|
||||||
|
"""A base formatter class that is configurable.
|
||||||
|
|
||||||
|
This formatter should usually be used as the base class of all formatters.
|
||||||
|
It is a traited :class:`Configurable` class and includes an extensible
|
||||||
|
API for users to determine how their objects are formatted. The following
|
||||||
|
logic is used to find a function to format an given object.
|
||||||
|
|
||||||
|
1. The object is introspected to see if it has a method with the name
|
||||||
|
:attr:`print_method`. If is does, that object is passed to that method
|
||||||
|
for formatting.
|
||||||
|
2. If no print method is found, three internal dictionaries are consulted
|
||||||
|
to find print method: :attr:`singleton_printers`, :attr:`type_printers`
|
||||||
|
and :attr:`deferred_printers`.
|
||||||
|
|
||||||
|
Users should use these dictionaries to register functions that will be
|
||||||
|
used to compute the format data for their objects (if those objects don't
|
||||||
|
have the special print methods). The easiest way of using these
|
||||||
|
dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
|
||||||
|
methods.
|
||||||
|
|
||||||
|
If no function/callable is found to compute the format data, ``None`` is
|
||||||
|
returned and this format type is not used.
|
||||||
|
"""
|
||||||
|
|
||||||
|
format_type = Unicode('text/plain')
|
||||||
|
_return_type = str
|
||||||
|
|
||||||
|
enabled = Bool(True).tag(config=True)
|
||||||
|
|
||||||
|
print_method = ObjectName('__repr__')
|
||||||
|
|
||||||
|
# The singleton printers.
|
||||||
|
# Maps the IDs of the builtin singleton objects to the format functions.
|
||||||
|
singleton_printers = Dict().tag(config=True)
|
||||||
|
|
||||||
|
# The type-specific printers.
|
||||||
|
# Map type objects to the format functions.
|
||||||
|
type_printers = Dict().tag(config=True)
|
||||||
|
|
||||||
|
# The deferred-import type-specific printers.
|
||||||
|
# Map (modulename, classname) pairs to the format functions.
|
||||||
|
deferred_printers = Dict().tag(config=True)
|
||||||
|
|
||||||
|
@catch_format_error
|
||||||
|
def __call__(self, obj):
|
||||||
|
"""Compute the format for an object."""
|
||||||
|
if self.enabled:
|
||||||
|
# lookup registered printer
|
||||||
|
try:
|
||||||
|
printer = self.lookup(obj)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
return printer(obj)
|
||||||
|
# Finally look for special method names
|
||||||
|
method = get_real_method(obj, self.print_method)
|
||||||
|
if method is not None:
|
||||||
|
return method()
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __contains__(self, typ):
|
||||||
|
"""map in to lookup_by_type"""
|
||||||
|
try:
|
||||||
|
self.lookup_by_type(typ)
|
||||||
|
except KeyError:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _check_return(self, r, obj):
|
||||||
|
"""Check that a return value is appropriate
|
||||||
|
|
||||||
|
Return the value if so, None otherwise, warning if invalid.
|
||||||
|
"""
|
||||||
|
if r is None or isinstance(r, self._return_type) or \
|
||||||
|
(isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
|
||||||
|
return r
|
||||||
|
else:
|
||||||
|
warnings.warn(
|
||||||
|
"%s formatter returned invalid type %s (expected %s) for object: %s" % \
|
||||||
|
(self.format_type, type(r), self._return_type, _safe_repr(obj)),
|
||||||
|
FormatterWarning
|
||||||
|
)
|
||||||
|
|
||||||
|
def lookup(self, obj):
|
||||||
|
"""Look up the formatter for a given instance.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
obj : object instance
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
f : callable
|
||||||
|
The registered formatting callable for the type.
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
KeyError if the type has not been registered.
|
||||||
|
"""
|
||||||
|
# look for singleton first
|
||||||
|
obj_id = id(obj)
|
||||||
|
if obj_id in self.singleton_printers:
|
||||||
|
return self.singleton_printers[obj_id]
|
||||||
|
# then lookup by type
|
||||||
|
return self.lookup_by_type(_get_type(obj))
|
||||||
|
|
||||||
|
def lookup_by_type(self, typ):
|
||||||
|
"""Look up the registered formatter for a type.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
typ : type or '__module__.__name__' string for a type
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
f : callable
|
||||||
|
The registered formatting callable for the type.
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
KeyError if the type has not been registered.
|
||||||
|
"""
|
||||||
|
if isinstance(typ, str):
|
||||||
|
typ_key = tuple(typ.rsplit('.',1))
|
||||||
|
if typ_key not in self.deferred_printers:
|
||||||
|
# We may have it cached in the type map. We will have to
|
||||||
|
# iterate over all of the types to check.
|
||||||
|
for cls in self.type_printers:
|
||||||
|
if _mod_name_key(cls) == typ_key:
|
||||||
|
return self.type_printers[cls]
|
||||||
|
else:
|
||||||
|
return self.deferred_printers[typ_key]
|
||||||
|
else:
|
||||||
|
for cls in pretty._get_mro(typ):
|
||||||
|
if cls in self.type_printers or self._in_deferred_types(cls):
|
||||||
|
return self.type_printers[cls]
|
||||||
|
|
||||||
|
# If we have reached here, the lookup failed.
|
||||||
|
raise KeyError("No registered printer for {0!r}".format(typ))
|
||||||
|
|
||||||
|
def for_type(self, typ, func=None):
|
||||||
|
"""Add a format function for a given type.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
-----------
|
||||||
|
typ : type or '__module__.__name__' string for a type
|
||||||
|
The class of the object that will be formatted using `func`.
|
||||||
|
func : callable
|
||||||
|
A callable for computing the format data.
|
||||||
|
`func` will be called with the object to be formatted,
|
||||||
|
and will return the raw data in this formatter's format.
|
||||||
|
Subclasses may use a different call signature for the
|
||||||
|
`func` argument.
|
||||||
|
|
||||||
|
If `func` is None or not specified, there will be no change,
|
||||||
|
only returning the current value.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
oldfunc : callable
|
||||||
|
The currently registered callable.
|
||||||
|
If you are registering a new formatter,
|
||||||
|
this will be the previous value (to enable restoring later).
|
||||||
|
"""
|
||||||
|
# if string given, interpret as 'pkg.module.class_name'
|
||||||
|
if isinstance(typ, str):
|
||||||
|
type_module, type_name = typ.rsplit('.', 1)
|
||||||
|
return self.for_type_by_name(type_module, type_name, func)
|
||||||
|
|
||||||
|
try:
|
||||||
|
oldfunc = self.lookup_by_type(typ)
|
||||||
|
except KeyError:
|
||||||
|
oldfunc = None
|
||||||
|
|
||||||
|
if func is not None:
|
||||||
|
self.type_printers[typ] = func
|
||||||
|
|
||||||
|
return oldfunc
|
||||||
|
|
||||||
|
def for_type_by_name(self, type_module, type_name, func=None):
|
||||||
|
"""Add a format function for a type specified by the full dotted
|
||||||
|
module and name of the type, rather than the type of the object.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
type_module : str
|
||||||
|
The full dotted name of the module the type is defined in, like
|
||||||
|
``numpy``.
|
||||||
|
type_name : str
|
||||||
|
The name of the type (the class name), like ``dtype``
|
||||||
|
func : callable
|
||||||
|
A callable for computing the format data.
|
||||||
|
`func` will be called with the object to be formatted,
|
||||||
|
and will return the raw data in this formatter's format.
|
||||||
|
Subclasses may use a different call signature for the
|
||||||
|
`func` argument.
|
||||||
|
|
||||||
|
If `func` is None or unspecified, there will be no change,
|
||||||
|
only returning the current value.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
oldfunc : callable
|
||||||
|
The currently registered callable.
|
||||||
|
If you are registering a new formatter,
|
||||||
|
this will be the previous value (to enable restoring later).
|
||||||
|
"""
|
||||||
|
key = (type_module, type_name)
|
||||||
|
|
||||||
|
try:
|
||||||
|
oldfunc = self.lookup_by_type("%s.%s" % key)
|
||||||
|
except KeyError:
|
||||||
|
oldfunc = None
|
||||||
|
|
||||||
|
if func is not None:
|
||||||
|
self.deferred_printers[key] = func
|
||||||
|
return oldfunc
|
||||||
|
|
||||||
|
def pop(self, typ, default=_raise_key_error):
|
||||||
|
"""Pop a formatter for the given type.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
typ : type or '__module__.__name__' string for a type
|
||||||
|
default : object
|
||||||
|
value to be returned if no formatter is registered for typ.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
obj : object
|
||||||
|
The last registered object for the type.
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
KeyError if the type is not registered and default is not specified.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if isinstance(typ, str):
|
||||||
|
typ_key = tuple(typ.rsplit('.',1))
|
||||||
|
if typ_key not in self.deferred_printers:
|
||||||
|
# We may have it cached in the type map. We will have to
|
||||||
|
# iterate over all of the types to check.
|
||||||
|
for cls in self.type_printers:
|
||||||
|
if _mod_name_key(cls) == typ_key:
|
||||||
|
old = self.type_printers.pop(cls)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
old = default
|
||||||
|
else:
|
||||||
|
old = self.deferred_printers.pop(typ_key)
|
||||||
|
else:
|
||||||
|
if typ in self.type_printers:
|
||||||
|
old = self.type_printers.pop(typ)
|
||||||
|
else:
|
||||||
|
old = self.deferred_printers.pop(_mod_name_key(typ), default)
|
||||||
|
if old is _raise_key_error:
|
||||||
|
raise KeyError("No registered value for {0!r}".format(typ))
|
||||||
|
return old
|
||||||
|
|
||||||
|
def _in_deferred_types(self, cls):
|
||||||
|
"""
|
||||||
|
Check if the given class is specified in the deferred type registry.
|
||||||
|
|
||||||
|
Successful matches will be moved to the regular type registry for future use.
|
||||||
|
"""
|
||||||
|
mod = getattr(cls, '__module__', None)
|
||||||
|
name = getattr(cls, '__name__', None)
|
||||||
|
key = (mod, name)
|
||||||
|
if key in self.deferred_printers:
|
||||||
|
# Move the printer over to the regular registry.
|
||||||
|
printer = self.deferred_printers.pop(key)
|
||||||
|
self.type_printers[cls] = printer
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class PlainTextFormatter(BaseFormatter):
|
||||||
|
"""The default pretty-printer.
|
||||||
|
|
||||||
|
This uses :mod:`IPython.lib.pretty` to compute the format data of
|
||||||
|
the object. If the object cannot be pretty printed, :func:`repr` is used.
|
||||||
|
See the documentation of :mod:`IPython.lib.pretty` for details on
|
||||||
|
how to write pretty printers. Here is a simple example::
|
||||||
|
|
||||||
|
def dtype_pprinter(obj, p, cycle):
|
||||||
|
if cycle:
|
||||||
|
return p.text('dtype(...)')
|
||||||
|
if hasattr(obj, 'fields'):
|
||||||
|
if obj.fields is None:
|
||||||
|
p.text(repr(obj))
|
||||||
|
else:
|
||||||
|
p.begin_group(7, 'dtype([')
|
||||||
|
for i, field in enumerate(obj.descr):
|
||||||
|
if i > 0:
|
||||||
|
p.text(',')
|
||||||
|
p.breakable()
|
||||||
|
p.pretty(field)
|
||||||
|
p.end_group(7, '])')
|
||||||
|
"""
|
||||||
|
|
||||||
|
# The format type of data returned.
|
||||||
|
format_type = Unicode('text/plain')
|
||||||
|
|
||||||
|
# This subclass ignores this attribute as it always need to return
|
||||||
|
# something.
|
||||||
|
enabled = Bool(True).tag(config=False)
|
||||||
|
|
||||||
|
max_seq_length = Integer(pretty.MAX_SEQ_LENGTH,
|
||||||
|
help="""Truncate large collections (lists, dicts, tuples, sets) to this size.
|
||||||
|
|
||||||
|
Set to 0 to disable truncation.
|
||||||
|
"""
|
||||||
|
).tag(config=True)
|
||||||
|
|
||||||
|
# Look for a _repr_pretty_ methods to use for pretty printing.
|
||||||
|
print_method = ObjectName('_repr_pretty_')
|
||||||
|
|
||||||
|
# Whether to pretty-print or not.
|
||||||
|
pprint = Bool(True).tag(config=True)
|
||||||
|
|
||||||
|
# Whether to be verbose or not.
|
||||||
|
verbose = Bool(False).tag(config=True)
|
||||||
|
|
||||||
|
# The maximum width.
|
||||||
|
max_width = Integer(79).tag(config=True)
|
||||||
|
|
||||||
|
# The newline character.
|
||||||
|
newline = Unicode('\n').tag(config=True)
|
||||||
|
|
||||||
|
# format-string for pprinting floats
|
||||||
|
float_format = Unicode('%r')
|
||||||
|
# setter for float precision, either int or direct format-string
|
||||||
|
float_precision = CUnicode('').tag(config=True)
|
||||||
|
|
||||||
|
@observe('float_precision')
|
||||||
|
def _float_precision_changed(self, change):
|
||||||
|
"""float_precision changed, set float_format accordingly.
|
||||||
|
|
||||||
|
float_precision can be set by int or str.
|
||||||
|
This will set float_format, after interpreting input.
|
||||||
|
If numpy has been imported, numpy print precision will also be set.
|
||||||
|
|
||||||
|
integer `n` sets format to '%.nf', otherwise, format set directly.
|
||||||
|
|
||||||
|
An empty string returns to defaults (repr for float, 8 for numpy).
|
||||||
|
|
||||||
|
This parameter can be set via the '%precision' magic.
|
||||||
|
"""
|
||||||
|
|
||||||
|
new = change['new']
|
||||||
|
if '%' in new:
|
||||||
|
# got explicit format string
|
||||||
|
fmt = new
|
||||||
|
try:
|
||||||
|
fmt%3.14159
|
||||||
|
except Exception:
|
||||||
|
raise ValueError("Precision must be int or format string, not %r"%new)
|
||||||
|
elif new:
|
||||||
|
# otherwise, should be an int
|
||||||
|
try:
|
||||||
|
i = int(new)
|
||||||
|
assert i >= 0
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError("Precision must be int or format string, not %r"%new)
|
||||||
|
except AssertionError:
|
||||||
|
raise ValueError("int precision must be non-negative, not %r"%i)
|
||||||
|
|
||||||
|
fmt = '%%.%if'%i
|
||||||
|
if 'numpy' in sys.modules:
|
||||||
|
# set numpy precision if it has been imported
|
||||||
|
import numpy
|
||||||
|
numpy.set_printoptions(precision=i)
|
||||||
|
else:
|
||||||
|
# default back to repr
|
||||||
|
fmt = '%r'
|
||||||
|
if 'numpy' in sys.modules:
|
||||||
|
import numpy
|
||||||
|
# numpy default is 8
|
||||||
|
numpy.set_printoptions(precision=8)
|
||||||
|
self.float_format = fmt
|
||||||
|
|
||||||
|
# Use the default pretty printers from IPython.lib.pretty.
|
||||||
|
@default('singleton_printers')
|
||||||
|
def _singleton_printers_default(self):
|
||||||
|
return pretty._singleton_pprinters.copy()
|
||||||
|
|
||||||
|
@default('type_printers')
|
||||||
|
def _type_printers_default(self):
|
||||||
|
d = pretty._type_pprinters.copy()
|
||||||
|
d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
|
||||||
|
return d
|
||||||
|
|
||||||
|
@default('deferred_printers')
|
||||||
|
def _deferred_printers_default(self):
|
||||||
|
return pretty._deferred_type_pprinters.copy()
|
||||||
|
|
||||||
|
#### FormatterABC interface ####
|
||||||
|
|
||||||
|
@catch_format_error
|
||||||
|
def __call__(self, obj):
|
||||||
|
"""Compute the pretty representation of the object."""
|
||||||
|
if not self.pprint:
|
||||||
|
return repr(obj)
|
||||||
|
else:
|
||||||
|
stream = StringIO()
|
||||||
|
printer = pretty.RepresentationPrinter(stream, self.verbose,
|
||||||
|
self.max_width, self.newline,
|
||||||
|
max_seq_length=self.max_seq_length,
|
||||||
|
singleton_pprinters=self.singleton_printers,
|
||||||
|
type_pprinters=self.type_printers,
|
||||||
|
deferred_pprinters=self.deferred_printers)
|
||||||
|
printer.pretty(obj)
|
||||||
|
printer.flush()
|
||||||
|
return stream.getvalue()
|
||||||
|
|
||||||
|
|
||||||
|
class HTMLFormatter(BaseFormatter):
|
||||||
|
"""An HTML formatter.
|
||||||
|
|
||||||
|
To define the callables that compute the HTML representation of your
|
||||||
|
objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
|
||||||
|
or :meth:`for_type_by_name` methods to register functions that handle
|
||||||
|
this.
|
||||||
|
|
||||||
|
The return value of this formatter should be a valid HTML snippet that
|
||||||
|
could be injected into an existing DOM. It should *not* include the
|
||||||
|
```<html>`` or ```<body>`` tags.
|
||||||
|
"""
|
||||||
|
format_type = Unicode('text/html')
|
||||||
|
|
||||||
|
print_method = ObjectName('_repr_html_')
|
||||||
|
|
||||||
|
|
||||||
|
class MarkdownFormatter(BaseFormatter):
|
||||||
|
"""A Markdown formatter.
|
||||||
|
|
||||||
|
To define the callables that compute the Markdown representation of your
|
||||||
|
objects, define a :meth:`_repr_markdown_` method or use the :meth:`for_type`
|
||||||
|
or :meth:`for_type_by_name` methods to register functions that handle
|
||||||
|
this.
|
||||||
|
|
||||||
|
The return value of this formatter should be a valid Markdown.
|
||||||
|
"""
|
||||||
|
format_type = Unicode('text/markdown')
|
||||||
|
|
||||||
|
print_method = ObjectName('_repr_markdown_')
|
||||||
|
|
||||||
|
class SVGFormatter(BaseFormatter):
|
||||||
|
"""An SVG formatter.
|
||||||
|
|
||||||
|
To define the callables that compute the SVG representation of your
|
||||||
|
objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
|
||||||
|
or :meth:`for_type_by_name` methods to register functions that handle
|
||||||
|
this.
|
||||||
|
|
||||||
|
The return value of this formatter should be valid SVG enclosed in
|
||||||
|
```<svg>``` tags, that could be injected into an existing DOM. It should
|
||||||
|
*not* include the ```<html>`` or ```<body>`` tags.
|
||||||
|
"""
|
||||||
|
format_type = Unicode('image/svg+xml')
|
||||||
|
|
||||||
|
print_method = ObjectName('_repr_svg_')
|
||||||
|
|
||||||
|
|
||||||
|
class PNGFormatter(BaseFormatter):
|
||||||
|
"""A PNG formatter.
|
||||||
|
|
||||||
|
To define the callables that compute the PNG representation of your
|
||||||
|
objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
|
||||||
|
or :meth:`for_type_by_name` methods to register functions that handle
|
||||||
|
this.
|
||||||
|
|
||||||
|
The return value of this formatter should be raw PNG data, *not*
|
||||||
|
base64 encoded.
|
||||||
|
"""
|
||||||
|
format_type = Unicode('image/png')
|
||||||
|
|
||||||
|
print_method = ObjectName('_repr_png_')
|
||||||
|
|
||||||
|
_return_type = (bytes, str)
|
||||||
|
|
||||||
|
|
||||||
|
class JPEGFormatter(BaseFormatter):
|
||||||
|
"""A JPEG formatter.
|
||||||
|
|
||||||
|
To define the callables that compute the JPEG representation of your
|
||||||
|
objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
|
||||||
|
or :meth:`for_type_by_name` methods to register functions that handle
|
||||||
|
this.
|
||||||
|
|
||||||
|
The return value of this formatter should be raw JPEG data, *not*
|
||||||
|
base64 encoded.
|
||||||
|
"""
|
||||||
|
format_type = Unicode('image/jpeg')
|
||||||
|
|
||||||
|
print_method = ObjectName('_repr_jpeg_')
|
||||||
|
|
||||||
|
_return_type = (bytes, str)
|
||||||
|
|
||||||
|
|
||||||
|
class LatexFormatter(BaseFormatter):
|
||||||
|
"""A LaTeX formatter.
|
||||||
|
|
||||||
|
To define the callables that compute the LaTeX representation of your
|
||||||
|
objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
|
||||||
|
or :meth:`for_type_by_name` methods to register functions that handle
|
||||||
|
this.
|
||||||
|
|
||||||
|
The return value of this formatter should be a valid LaTeX equation,
|
||||||
|
enclosed in either ```$```, ```$$``` or another LaTeX equation
|
||||||
|
environment.
|
||||||
|
"""
|
||||||
|
format_type = Unicode('text/latex')
|
||||||
|
|
||||||
|
print_method = ObjectName('_repr_latex_')
|
||||||
|
|
||||||
|
|
||||||
|
class JSONFormatter(BaseFormatter):
|
||||||
|
"""A JSON string formatter.
|
||||||
|
|
||||||
|
To define the callables that compute the JSONable representation of
|
||||||
|
your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
|
||||||
|
or :meth:`for_type_by_name` methods to register functions that handle
|
||||||
|
this.
|
||||||
|
|
||||||
|
The return value of this formatter should be a JSONable list or dict.
|
||||||
|
JSON scalars (None, number, string) are not allowed, only dict or list containers.
|
||||||
|
"""
|
||||||
|
format_type = Unicode('application/json')
|
||||||
|
_return_type = (list, dict)
|
||||||
|
|
||||||
|
print_method = ObjectName('_repr_json_')
|
||||||
|
|
||||||
|
def _check_return(self, r, obj):
|
||||||
|
"""Check that a return value is appropriate
|
||||||
|
|
||||||
|
Return the value if so, None otherwise, warning if invalid.
|
||||||
|
"""
|
||||||
|
if r is None:
|
||||||
|
return
|
||||||
|
md = None
|
||||||
|
if isinstance(r, tuple):
|
||||||
|
# unpack data, metadata tuple for type checking on first element
|
||||||
|
r, md = r
|
||||||
|
|
||||||
|
# handle deprecated JSON-as-string form from IPython < 3
|
||||||
|
if isinstance(r, str):
|
||||||
|
warnings.warn("JSON expects JSONable list/dict containers, not JSON strings",
|
||||||
|
FormatterWarning)
|
||||||
|
r = json.loads(r)
|
||||||
|
|
||||||
|
if md is not None:
|
||||||
|
# put the tuple back together
|
||||||
|
r = (r, md)
|
||||||
|
return super(JSONFormatter, self)._check_return(r, obj)
|
||||||
|
|
||||||
|
|
||||||
|
class JavascriptFormatter(BaseFormatter):
|
||||||
|
"""A Javascript formatter.
|
||||||
|
|
||||||
|
To define the callables that compute the Javascript representation of
|
||||||
|
your objects, define a :meth:`_repr_javascript_` method or use the
|
||||||
|
:meth:`for_type` or :meth:`for_type_by_name` methods to register functions
|
||||||
|
that handle this.
|
||||||
|
|
||||||
|
The return value of this formatter should be valid Javascript code and
|
||||||
|
should *not* be enclosed in ```<script>``` tags.
|
||||||
|
"""
|
||||||
|
format_type = Unicode('application/javascript')
|
||||||
|
|
||||||
|
print_method = ObjectName('_repr_javascript_')
|
||||||
|
|
||||||
|
|
||||||
|
class PDFFormatter(BaseFormatter):
|
||||||
|
"""A PDF formatter.
|
||||||
|
|
||||||
|
To define the callables that compute the PDF representation of your
|
||||||
|
objects, define a :meth:`_repr_pdf_` method or use the :meth:`for_type`
|
||||||
|
or :meth:`for_type_by_name` methods to register functions that handle
|
||||||
|
this.
|
||||||
|
|
||||||
|
The return value of this formatter should be raw PDF data, *not*
|
||||||
|
base64 encoded.
|
||||||
|
"""
|
||||||
|
format_type = Unicode('application/pdf')
|
||||||
|
|
||||||
|
print_method = ObjectName('_repr_pdf_')
|
||||||
|
|
||||||
|
_return_type = (bytes, str)
|
||||||
|
|
||||||
|
class IPythonDisplayFormatter(BaseFormatter):
|
||||||
|
"""A Formatter for objects that know how to display themselves.
|
||||||
|
|
||||||
|
To define the callables that compute the representation of your
|
||||||
|
objects, define a :meth:`_ipython_display_` method or use the :meth:`for_type`
|
||||||
|
or :meth:`for_type_by_name` methods to register functions that handle
|
||||||
|
this. Unlike mime-type displays, this method should not return anything,
|
||||||
|
instead calling any appropriate display methods itself.
|
||||||
|
|
||||||
|
This display formatter has highest priority.
|
||||||
|
If it fires, no other display formatter will be called.
|
||||||
|
"""
|
||||||
|
print_method = ObjectName('_ipython_display_')
|
||||||
|
_return_type = (type(None), bool)
|
||||||
|
|
||||||
|
|
||||||
|
@catch_format_error
|
||||||
|
def __call__(self, obj):
|
||||||
|
"""Compute the format for an object."""
|
||||||
|
if self.enabled:
|
||||||
|
# lookup registered printer
|
||||||
|
try:
|
||||||
|
printer = self.lookup(obj)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
printer(obj)
|
||||||
|
return True
|
||||||
|
# Finally look for special method names
|
||||||
|
method = get_real_method(obj, self.print_method)
|
||||||
|
if method is not None:
|
||||||
|
method()
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
FormatterABC.register(BaseFormatter)
|
||||||
|
FormatterABC.register(PlainTextFormatter)
|
||||||
|
FormatterABC.register(HTMLFormatter)
|
||||||
|
FormatterABC.register(MarkdownFormatter)
|
||||||
|
FormatterABC.register(SVGFormatter)
|
||||||
|
FormatterABC.register(PNGFormatter)
|
||||||
|
FormatterABC.register(PDFFormatter)
|
||||||
|
FormatterABC.register(JPEGFormatter)
|
||||||
|
FormatterABC.register(LatexFormatter)
|
||||||
|
FormatterABC.register(JSONFormatter)
|
||||||
|
FormatterABC.register(JavascriptFormatter)
|
||||||
|
FormatterABC.register(IPythonDisplayFormatter)
|
||||||
|
|
||||||
|
|
||||||
|
def format_display_data(obj, include=None, exclude=None):
|
||||||
|
"""Return a format data dict for an object.
|
||||||
|
|
||||||
|
By default all format types will be computed.
|
||||||
|
|
||||||
|
The following MIME types are currently implemented:
|
||||||
|
|
||||||
|
* text/plain
|
||||||
|
* text/html
|
||||||
|
* text/markdown
|
||||||
|
* text/latex
|
||||||
|
* application/json
|
||||||
|
* application/javascript
|
||||||
|
* application/pdf
|
||||||
|
* image/png
|
||||||
|
* image/jpeg
|
||||||
|
* image/svg+xml
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
obj : object
|
||||||
|
The Python object whose format data will be computed.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
format_dict : dict
|
||||||
|
A dictionary of key/value pairs, one or each format that was
|
||||||
|
generated for the object. The keys are the format types, which
|
||||||
|
will usually be MIME type strings and the values and JSON'able
|
||||||
|
data structure containing the raw data for the representation in
|
||||||
|
that format.
|
||||||
|
include : list or tuple, optional
|
||||||
|
A list of format type strings (MIME types) to include in the
|
||||||
|
format data dict. If this is set *only* the format types included
|
||||||
|
in this list will be computed.
|
||||||
|
exclude : list or tuple, optional
|
||||||
|
A list of format type string (MIME types) to exclue in the format
|
||||||
|
data dict. If this is set all format types will be computed,
|
||||||
|
except for those included in this argument.
|
||||||
|
"""
|
||||||
|
from yap_ipython.core.interactiveshell import InteractiveShell
|
||||||
|
|
||||||
|
return InteractiveShell.instance().display_formatter.format(
|
||||||
|
obj,
|
||||||
|
include,
|
||||||
|
exclude
|
||||||
|
)
|
||||||
|
|
525
packages/python/yap_kernel/yap_kernel/inputtransformer.py
Normal file
525
packages/python/yap_kernel/yap_kernel/inputtransformer.py
Normal file
@ -0,0 +1,525 @@
|
|||||||
|
"""Input transformer classes to support IPython special syntax.
|
||||||
|
|
||||||
|
This includes the machinery to recognise and transform ``%magic`` commands,
|
||||||
|
``!system`` commands, ``help?`` querying, prompt stripping, and so forth.
|
||||||
|
"""
|
||||||
|
import abc
|
||||||
|
import functools
|
||||||
|
import re
|
||||||
|
from io import StringIO
|
||||||
|
|
||||||
|
from IPython.core.splitinput import LineInfo
|
||||||
|
from IPython.utils import tokenize2
|
||||||
|
from IPython.utils.tokenize2 import generate_tokens, untokenize, TokenError
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Globals
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# The escape sequences that define the syntax transformations IPython will
|
||||||
|
# apply to user input. These can NOT be just changed here: many regular
|
||||||
|
# expressions and other parts of the code may use their hardcoded values, and
|
||||||
|
# for all intents and purposes they constitute the 'IPython syntax', so they
|
||||||
|
# should be considered fixed.
|
||||||
|
|
||||||
|
ESC_SHELL = '!' # Send line to underlying system shell
|
||||||
|
ESC_SH_CAP = '!!' # Send line to system shell and capture output
|
||||||
|
ESC_HELP = '?' # Find information about object
|
||||||
|
ESC_HELP2 = '??' # Find extra-detailed information about object
|
||||||
|
ESC_MAGIC = '%' # Call magic function
|
||||||
|
ESC_MAGIC2 = '%%' # Call cell-magic function
|
||||||
|
ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
|
||||||
|
ESC_QUOTE2 = ';' # Quote all args as a single string, call
|
||||||
|
ESC_PAREN = '/' # Call first argument with rest of line as arguments
|
||||||
|
|
||||||
|
ESC_SEQUENCES = [ESC_SHELL, ESC_SH_CAP, ESC_HELP ,\
|
||||||
|
ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,\
|
||||||
|
ESC_QUOTE, ESC_QUOTE2, ESC_PAREN ]
|
||||||
|
|
||||||
|
|
||||||
|
class InputTransformer(metaclass=abc.ABCMeta):
|
||||||
|
"""Abstract base class for line-based input transformers."""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def push(self, line):
|
||||||
|
"""Send a line of input to the transformer, returning the transformed
|
||||||
|
input or None if the transformer is waiting for more input.
|
||||||
|
|
||||||
|
Must be overridden by subclasses.
|
||||||
|
|
||||||
|
Implementations may raise ``SyntaxError`` if the input is invalid. No
|
||||||
|
other exceptions may be raised.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def reset(self):
|
||||||
|
"""Return, transformed any lines that the transformer has accumulated,
|
||||||
|
and reset its internal state.
|
||||||
|
|
||||||
|
Must be overridden by subclasses.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def wrap(cls, func):
|
||||||
|
"""Can be used by subclasses as a decorator, to return a factory that
|
||||||
|
will allow instantiation with the decorated object.
|
||||||
|
"""
|
||||||
|
@functools.wraps(func)
|
||||||
|
def transformer_factory(**kwargs):
|
||||||
|
return cls(func, **kwargs)
|
||||||
|
|
||||||
|
return transformer_factory
|
||||||
|
|
||||||
|
class StatelessInputTransformer(InputTransformer):
|
||||||
|
"""Wrapper for a stateless input transformer implemented as a function."""
|
||||||
|
def __init__(self, func):
|
||||||
|
self.func = func
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "StatelessInputTransformer(func={0!r})".format(self.func)
|
||||||
|
|
||||||
|
def push(self, line):
|
||||||
|
"""Send a line of input to the transformer, returning the
|
||||||
|
transformed input."""
|
||||||
|
return self.func(line)
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""No-op - exists for compatibility."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
class CoroutineInputTransformer(InputTransformer):
|
||||||
|
"""Wrapper for an input transformer implemented as a coroutine."""
|
||||||
|
def __init__(self, coro, **kwargs):
|
||||||
|
# Prime it
|
||||||
|
self.coro = coro(**kwargs)
|
||||||
|
next(self.coro)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "CoroutineInputTransformer(coro={0!r})".format(self.coro)
|
||||||
|
|
||||||
|
def push(self, line):
|
||||||
|
"""Send a line of input to the transformer, returning the
|
||||||
|
transformed input or None if the transformer is waiting for more
|
||||||
|
input.
|
||||||
|
"""
|
||||||
|
return self.coro.send(line)
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""Return, transformed any lines that the transformer has
|
||||||
|
accumulated, and reset its internal state.
|
||||||
|
"""
|
||||||
|
return self.coro.send(None)
|
||||||
|
|
||||||
|
class TokenInputTransformer(InputTransformer):
|
||||||
|
"""Wrapper for a token-based input transformer.
|
||||||
|
|
||||||
|
func should accept a list of tokens (5-tuples, see tokenize docs), and
|
||||||
|
return an iterable which can be passed to tokenize.untokenize().
|
||||||
|
"""
|
||||||
|
def __init__(self, func):
|
||||||
|
self.func = func
|
||||||
|
self.buf = []
|
||||||
|
self.reset_tokenizer()
|
||||||
|
|
||||||
|
def reset_tokenizer(self):
|
||||||
|
it = iter(self.buf)
|
||||||
|
self.tokenizer = generate_tokens(it.__next__)
|
||||||
|
|
||||||
|
def push(self, line):
|
||||||
|
self.buf.append(line + '\n')
|
||||||
|
if all(l.isspace() for l in self.buf):
|
||||||
|
return self.reset()
|
||||||
|
|
||||||
|
tokens = []
|
||||||
|
stop_at_NL = False
|
||||||
|
try:
|
||||||
|
for intok in self.tokenizer:
|
||||||
|
tokens.append(intok)
|
||||||
|
t = intok[0]
|
||||||
|
if t == tokenize2.NEWLINE or (stop_at_NL and t == tokenize2.NL):
|
||||||
|
# Stop before we try to pull a line we don't have yet
|
||||||
|
break
|
||||||
|
elif t == tokenize2.ERRORTOKEN:
|
||||||
|
stop_at_NL = True
|
||||||
|
except TokenError:
|
||||||
|
# Multi-line statement - stop and try again with the next line
|
||||||
|
self.reset_tokenizer()
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self.output(tokens)
|
||||||
|
|
||||||
|
def output(self, tokens):
|
||||||
|
self.buf.clear()
|
||||||
|
self.reset_tokenizer()
|
||||||
|
return untokenize(self.func(tokens)).rstrip('\n')
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
l = ''.join(self.buf)
|
||||||
|
self.buf.clear()
|
||||||
|
self.reset_tokenizer()
|
||||||
|
if l:
|
||||||
|
return l.rstrip('\n')
|
||||||
|
|
||||||
|
class assemble_python_lines(TokenInputTransformer):
|
||||||
|
def __init__(self):
|
||||||
|
super(assemble_python_lines, self).__init__(None)
|
||||||
|
|
||||||
|
def output(self, tokens):
|
||||||
|
return self.reset()
|
||||||
|
|
||||||
|
@CoroutineInputTransformer.wrap
|
||||||
|
def assemble_logical_lines():
|
||||||
|
"""Join lines following explicit line continuations (\)"""
|
||||||
|
line = ''
|
||||||
|
while True:
|
||||||
|
line = (yield line)
|
||||||
|
if not line or line.isspace():
|
||||||
|
continue
|
||||||
|
|
||||||
|
parts = []
|
||||||
|
while line is not None:
|
||||||
|
if line.endswith('\\') and (not has_comment(line)):
|
||||||
|
parts.append(line[:-1])
|
||||||
|
line = (yield None) # Get another line
|
||||||
|
else:
|
||||||
|
parts.append(line)
|
||||||
|
break
|
||||||
|
|
||||||
|
# Output
|
||||||
|
line = ''.join(parts)
|
||||||
|
|
||||||
|
# Utilities
|
||||||
|
def _make_help_call(target, esc, lspace, next_input=None):
|
||||||
|
"""Prepares a pinfo(2)/psearch call from a target name and the escape
|
||||||
|
(i.e. ? or ??)"""
|
||||||
|
method = 'pinfo2' if esc == '??' \
|
||||||
|
else 'psearch' if '*' in target \
|
||||||
|
else 'pinfo'
|
||||||
|
arg = " ".join([method, target])
|
||||||
|
if next_input is None:
|
||||||
|
return '%sget_ipython().magic(%r)' % (lspace, arg)
|
||||||
|
else:
|
||||||
|
return '%sget_ipython().set_next_input(%r);get_ipython().magic(%r)' % \
|
||||||
|
(lspace, next_input, arg)
|
||||||
|
|
||||||
|
# These define the transformations for the different escape characters.
|
||||||
|
def _tr_system(line_info):
|
||||||
|
"Translate lines escaped with: !"
|
||||||
|
cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
|
||||||
|
return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
|
||||||
|
|
||||||
|
def _tr_system2(line_info):
|
||||||
|
"Translate lines escaped with: !!"
|
||||||
|
cmd = line_info.line.lstrip()[2:]
|
||||||
|
return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
|
||||||
|
|
||||||
|
def _tr_help(line_info):
|
||||||
|
"Translate lines escaped with: ?/??"
|
||||||
|
# A naked help line should just fire the intro help screen
|
||||||
|
if not line_info.line[1:]:
|
||||||
|
return 'get_ipython().show_usage()'
|
||||||
|
|
||||||
|
return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
|
||||||
|
|
||||||
|
def _tr_magic(line_info):
|
||||||
|
"Translate lines escaped with: %"
|
||||||
|
tpl = '%sget_ipython().magic(%r)'
|
||||||
|
if line_info.line.startswith(ESC_MAGIC2):
|
||||||
|
return line_info.line
|
||||||
|
cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip()
|
||||||
|
return tpl % (line_info.pre, cmd)
|
||||||
|
|
||||||
|
def _tr_quote(line_info):
|
||||||
|
"Translate lines escaped with: ,"
|
||||||
|
return '%s%s("%s")' % (line_info.pre, line_info.ifun,
|
||||||
|
'", "'.join(line_info.the_rest.split()) )
|
||||||
|
|
||||||
|
def _tr_quote2(line_info):
|
||||||
|
"Translate lines escaped with: ;"
|
||||||
|
return '%s%s("%s")' % (line_info.pre, line_info.ifun,
|
||||||
|
line_info.the_rest)
|
||||||
|
|
||||||
|
def _tr_paren(line_info):
|
||||||
|
"Translate lines escaped with: /"
|
||||||
|
return '%s%s(%s)' % (line_info.pre, line_info.ifun,
|
||||||
|
", ".join(line_info.the_rest.split()))
|
||||||
|
|
||||||
|
tr = { ESC_SHELL : _tr_system,
|
||||||
|
ESC_SH_CAP : _tr_system2,
|
||||||
|
ESC_HELP : _tr_help,
|
||||||
|
ESC_HELP2 : _tr_help,
|
||||||
|
ESC_MAGIC : _tr_magic,
|
||||||
|
ESC_QUOTE : _tr_quote,
|
||||||
|
ESC_QUOTE2 : _tr_quote2,
|
||||||
|
ESC_PAREN : _tr_paren }
|
||||||
|
|
||||||
|
@StatelessInputTransformer.wrap
|
||||||
|
def escaped_commands(line):
|
||||||
|
"""Transform escaped commands - %magic, !system, ?help + various autocalls.
|
||||||
|
"""
|
||||||
|
if not line or line.isspace():
|
||||||
|
return line
|
||||||
|
lineinf = LineInfo(line)
|
||||||
|
if lineinf.esc not in tr:
|
||||||
|
return line
|
||||||
|
|
||||||
|
return tr[lineinf.esc](lineinf)
|
||||||
|
|
||||||
|
_initial_space_re = re.compile(r'\s*')
|
||||||
|
|
||||||
|
_help_end_re = re.compile(r"""(%{0,2}
|
||||||
|
[a-zA-Z_*][\w*]* # Variable name
|
||||||
|
(\.[a-zA-Z_*][\w*]*)* # .etc.etc
|
||||||
|
)
|
||||||
|
(\?\??)$ # ? or ??
|
||||||
|
""",
|
||||||
|
re.VERBOSE)
|
||||||
|
|
||||||
|
# Extra pseudotokens for multiline strings and data structures
|
||||||
|
_MULTILINE_STRING = object()
|
||||||
|
_MULTILINE_STRUCTURE = object()
|
||||||
|
|
||||||
|
def _line_tokens(line):
|
||||||
|
"""Helper for has_comment and ends_in_comment_or_string."""
|
||||||
|
readline = StringIO(line).readline
|
||||||
|
toktypes = set()
|
||||||
|
try:
|
||||||
|
for t in generate_tokens(readline):
|
||||||
|
toktypes.add(t[0])
|
||||||
|
except TokenError as e:
|
||||||
|
# There are only two cases where a TokenError is raised.
|
||||||
|
if 'multi-line string' in e.args[0]:
|
||||||
|
toktypes.add(_MULTILINE_STRING)
|
||||||
|
else:
|
||||||
|
toktypes.add(_MULTILINE_STRUCTURE)
|
||||||
|
return toktypes
|
||||||
|
|
||||||
|
def has_comment(src):
|
||||||
|
"""Indicate whether an input line has (i.e. ends in, or is) a comment.
|
||||||
|
|
||||||
|
This uses tokenize, so it can distinguish comments from # inside strings.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
src : string
|
||||||
|
A single line input string.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
comment : bool
|
||||||
|
True if source has a comment.
|
||||||
|
"""
|
||||||
|
return (tokenize2.COMMENT in _line_tokens(src))
|
||||||
|
|
||||||
|
def ends_in_comment_or_string(src):
|
||||||
|
"""Indicates whether or not an input line ends in a comment or within
|
||||||
|
a multiline string.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
src : string
|
||||||
|
A single line input string.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
comment : bool
|
||||||
|
True if source ends in a comment or multiline string.
|
||||||
|
"""
|
||||||
|
toktypes = _line_tokens(src)
|
||||||
|
return (tokenize2.COMMENT in toktypes) or (_MULTILINE_STRING in toktypes)
|
||||||
|
|
||||||
|
|
||||||
|
@StatelessInputTransformer.wrap
|
||||||
|
def help_end(line):
|
||||||
|
"""Translate lines with ?/?? at the end"""
|
||||||
|
m = _help_end_re.search(line)
|
||||||
|
if m is None or ends_in_comment_or_string(line):
|
||||||
|
return line
|
||||||
|
target = m.group(1)
|
||||||
|
esc = m.group(3)
|
||||||
|
lspace = _initial_space_re.match(line).group(0)
|
||||||
|
|
||||||
|
# If we're mid-command, put it back on the next prompt for the user.
|
||||||
|
next_input = line.rstrip('?') if line.strip() != m.group(0) else None
|
||||||
|
|
||||||
|
return _make_help_call(target, esc, lspace, next_input)
|
||||||
|
|
||||||
|
|
||||||
|
@CoroutineInputTransformer.wrap
|
||||||
|
def cellmagic(end_on_blank_line=False):
|
||||||
|
"""Captures & transforms cell magics.
|
||||||
|
|
||||||
|
After a cell magic is started, this stores up any lines it gets until it is
|
||||||
|
reset (sent None).
|
||||||
|
"""
|
||||||
|
tpl = 'get_ipython().run_cell_magic(%r, %r, %r)'
|
||||||
|
cellmagic_help_re = re.compile('%%\w+\?')
|
||||||
|
line = ''
|
||||||
|
while True:
|
||||||
|
line = (yield line)
|
||||||
|
# consume leading empty lines
|
||||||
|
while not line:
|
||||||
|
line = (yield line)
|
||||||
|
|
||||||
|
if not line.startswith(ESC_MAGIC2):
|
||||||
|
# This isn't a cell magic, idle waiting for reset then start over
|
||||||
|
while line is not None:
|
||||||
|
line = (yield line)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if cellmagic_help_re.match(line):
|
||||||
|
# This case will be handled by help_end
|
||||||
|
continue
|
||||||
|
|
||||||
|
first = line
|
||||||
|
body = []
|
||||||
|
line = (yield None)
|
||||||
|
while (line is not None) and \
|
||||||
|
((line.strip() != '') or not end_on_blank_line):
|
||||||
|
body.append(line)
|
||||||
|
line = (yield None)
|
||||||
|
|
||||||
|
# Output
|
||||||
|
magic_name, _, first = first.partition(' ')
|
||||||
|
magic_name = magic_name.lstrip(ESC_MAGIC2)
|
||||||
|
line = tpl % (magic_name, first, u'\n'.join(body))
|
||||||
|
|
||||||
|
|
||||||
|
def _strip_prompts(prompt_re, initial_re=None, turnoff_re=None):
|
||||||
|
"""Remove matching input prompts from a block of input.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
prompt_re : regular expression
|
||||||
|
A regular expression matching any input prompt (including continuation)
|
||||||
|
initial_re : regular expression, optional
|
||||||
|
A regular expression matching only the initial prompt, but not continuation.
|
||||||
|
If no initial expression is given, prompt_re will be used everywhere.
|
||||||
|
Used mainly for plain Python prompts, where the continuation prompt
|
||||||
|
``...`` is a valid Python expression in Python 3, so shouldn't be stripped.
|
||||||
|
|
||||||
|
If initial_re and prompt_re differ,
|
||||||
|
only initial_re will be tested against the first line.
|
||||||
|
If any prompt is found on the first two lines,
|
||||||
|
prompts will be stripped from the rest of the block.
|
||||||
|
"""
|
||||||
|
if initial_re is None:
|
||||||
|
initial_re = prompt_re
|
||||||
|
line = ''
|
||||||
|
while True:
|
||||||
|
line = (yield line)
|
||||||
|
|
||||||
|
# First line of cell
|
||||||
|
if line is None:
|
||||||
|
continue
|
||||||
|
out, n1 = initial_re.subn('', line, count=1)
|
||||||
|
if turnoff_re and not n1:
|
||||||
|
if turnoff_re.match(line):
|
||||||
|
# We're in e.g. a cell magic; disable this transformer for
|
||||||
|
# the rest of the cell.
|
||||||
|
while line is not None:
|
||||||
|
line = (yield line)
|
||||||
|
continue
|
||||||
|
|
||||||
|
line = (yield out)
|
||||||
|
|
||||||
|
if line is None:
|
||||||
|
continue
|
||||||
|
# check for any prompt on the second line of the cell,
|
||||||
|
# because people often copy from just after the first prompt,
|
||||||
|
# so we might not see it in the first line.
|
||||||
|
out, n2 = prompt_re.subn('', line, count=1)
|
||||||
|
line = (yield out)
|
||||||
|
|
||||||
|
if n1 or n2:
|
||||||
|
# Found a prompt in the first two lines - check for it in
|
||||||
|
# the rest of the cell as well.
|
||||||
|
while line is not None:
|
||||||
|
line = (yield prompt_re.sub('', line, count=1))
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Prompts not in input - wait for reset
|
||||||
|
while line is not None:
|
||||||
|
line = (yield line)
|
||||||
|
|
||||||
|
@CoroutineInputTransformer.wrap
|
||||||
|
def classic_prompt():
|
||||||
|
"""Strip the >>>/... prompts of the Python interactive shell."""
|
||||||
|
# FIXME: non-capturing version (?:...) usable?
|
||||||
|
prompt_re = re.compile(r'^(>>>|\.\.\.)( |$)')
|
||||||
|
initial_re = re.compile(r'^>>>( |$)')
|
||||||
|
# Any %magic/!system is IPython syntax, so we needn't look for >>> prompts
|
||||||
|
turnoff_re = re.compile(r'^[%!]')
|
||||||
|
return _strip_prompts(prompt_re, initial_re, turnoff_re)
|
||||||
|
|
||||||
|
@CoroutineInputTransformer.wrap
|
||||||
|
def ipy_prompt():
|
||||||
|
"""Strip IPython's In [1]:/...: prompts."""
|
||||||
|
# FIXME: non-capturing version (?:...) usable?
|
||||||
|
prompt_re = re.compile(r'^(In \[\d+\]: |\s*\.{3,}: ?)')
|
||||||
|
# Disable prompt stripping inside cell magics
|
||||||
|
turnoff_re = re.compile(r'^%%')
|
||||||
|
return _strip_prompts(prompt_re, turnoff_re=turnoff_re)
|
||||||
|
|
||||||
|
|
||||||
|
@CoroutineInputTransformer.wrap
|
||||||
|
def leading_indent():
|
||||||
|
"""Remove leading indentation.
|
||||||
|
|
||||||
|
If the first line starts with a spaces or tabs, the same whitespace will be
|
||||||
|
removed from each following line until it is reset.
|
||||||
|
"""
|
||||||
|
space_re = re.compile(r'^[ \t]+')
|
||||||
|
line = ''
|
||||||
|
while True:
|
||||||
|
line = (yield line)
|
||||||
|
|
||||||
|
if line is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
m = space_re.match(line)
|
||||||
|
if m:
|
||||||
|
space = m.group(0)
|
||||||
|
while line is not None:
|
||||||
|
if line.startswith(space):
|
||||||
|
line = line[len(space):]
|
||||||
|
line = (yield line)
|
||||||
|
else:
|
||||||
|
# No leading spaces - wait for reset
|
||||||
|
while line is not None:
|
||||||
|
line = (yield line)
|
||||||
|
|
||||||
|
|
||||||
|
_assign_pat = \
|
||||||
|
r'''(?P<lhs>(\s*)
|
||||||
|
([\w\.]+) # Initial identifier
|
||||||
|
(\s*,\s*
|
||||||
|
\*?[\w\.]+)* # Further identifiers for unpacking
|
||||||
|
\s*?,? # Trailing comma
|
||||||
|
)
|
||||||
|
\s*=\s*
|
||||||
|
'''
|
||||||
|
|
||||||
|
assign_system_re = re.compile(r'{}!\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
|
||||||
|
assign_system_template = '%s = get_ipython().getoutput(%r)'
|
||||||
|
@StatelessInputTransformer.wrap
|
||||||
|
def assign_from_system(line):
|
||||||
|
"""Transform assignment from system commands (e.g. files = !ls)"""
|
||||||
|
m = assign_system_re.match(line)
|
||||||
|
if m is None:
|
||||||
|
return line
|
||||||
|
|
||||||
|
return assign_system_template % m.group('lhs', 'cmd')
|
||||||
|
|
||||||
|
assign_magic_re = re.compile(r'{}%\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
|
||||||
|
assign_magic_template = '%s = get_ipython().magic(%r)'
|
||||||
|
@StatelessInputTransformer.wrap
|
||||||
|
def assign_from_magic(line):
|
||||||
|
"""Transform assignment from magic commands (e.g. a = %who_ls)"""
|
||||||
|
m = assign_magic_re.match(line)
|
||||||
|
if m is None:
|
||||||
|
return line
|
||||||
|
|
||||||
|
return assign_magic_template % m.group('lhs', 'cmd')
|
@ -21,8 +21,8 @@ from IPython.core.application import (
|
|||||||
BaseIPythonApplication, base_flags, base_aliases, catch_config_error
|
BaseIPythonApplication, base_flags, base_aliases, catch_config_error
|
||||||
)
|
)
|
||||||
from IPython.core.profiledir import ProfileDir
|
from IPython.core.profiledir import ProfileDir
|
||||||
from IPython.core.shellapp import (
|
from yap_ipython.core.shellapp import (
|
||||||
InteractiveShellApp, shell_flags, shell_aliases
|
YAPInteractiveApp, shell_flags, shell_aliases
|
||||||
)
|
)
|
||||||
from IPython.utils import io
|
from IPython.utils import io
|
||||||
from ipython_genutils.path import filefind, ensure_dir_exists
|
from ipython_genutils.path import filefind, ensure_dir_exists
|
||||||
@ -96,7 +96,7 @@ To read more about this, see https://github.com/ipython/ipython/issues/2049
|
|||||||
# Application class for starting an IPython Kernel
|
# Application class for starting an IPython Kernel
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
class YAPKernelApp(BaseIPythonApplication, InteractiveShellApp,
|
class YAPKernelApp(BaseIPythonApplication, YAPInteractiveApp,
|
||||||
ConnectionFileMixin):
|
ConnectionFileMixin):
|
||||||
name='YAP Kernel'
|
name='YAP Kernel'
|
||||||
aliases = Dict(kernel_aliases)
|
aliases = Dict(kernel_aliases)
|
||||||
@ -385,7 +385,7 @@ class YAPKernelApp(BaseIPythonApplication, InteractiveShellApp,
|
|||||||
if not os.environ.get('MPLBACKEND'):
|
if not os.environ.get('MPLBACKEND'):
|
||||||
os.environ['MPLBACKEND'] = 'module://yap_kernel.pylab.backend_inline'
|
os.environ['MPLBACKEND'] = 'module://yap_kernel.pylab.backend_inline'
|
||||||
|
|
||||||
# Provide a wrapper for :meth:`InteractiveShellApp.init_gui_pylab`
|
# Provide a wrapper for :meth:`YAPInteractiveApp.init_gui_pylab`
|
||||||
# to ensure that any exception is printed straight to stderr.
|
# to ensure that any exception is printed straight to stderr.
|
||||||
# Normally _showtraceback associates the reply with an execution,
|
# Normally _showtraceback associates the reply with an execution,
|
||||||
# which means frontends will never draw it, as this exception
|
# which means frontends will never draw it, as this exception
|
||||||
@ -400,7 +400,7 @@ class YAPKernelApp(BaseIPythonApplication, InteractiveShellApp,
|
|||||||
file=sys.stderr)
|
file=sys.stderr)
|
||||||
print (shell.InteractiveTB.stb2text(stb), file=sys.stderr)
|
print (shell.InteractiveTB.stb2text(stb), file=sys.stderr)
|
||||||
shell._showtraceback = print_tb
|
shell._showtraceback = print_tb
|
||||||
InteractiveShellApp.init_gui_pylab(self)
|
YAPInteractiveApp.init_gui_pylab(self)
|
||||||
finally:
|
finally:
|
||||||
shell._showtraceback = _showtraceback
|
shell._showtraceback = _showtraceback
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ from jupyter_client.kernelspec import KernelSpecManager
|
|||||||
|
|
||||||
pjoin = os.path.join
|
pjoin = os.path.join
|
||||||
|
|
||||||
KERNEL_NAME = 'YAPKernel'
|
KERNEL_NAME = 'yap_kernel'
|
||||||
|
|
||||||
# path to kernelspec resources
|
# path to kernelspec resources
|
||||||
RESOURCES = pjoin(os.path.dirname(__file__), 'resources')
|
RESOURCES = pjoin(os.path.dirname(__file__), 'resources')
|
||||||
@ -59,7 +59,7 @@ def get_kernel_dict(extra_arguments=None):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def write_kernel_spec(path=None, overrides=None, extra_arguments=None):
|
def write_kernel_spec(path=os.path.join(tempfile.mkdtemp(suffix='_kernels'), KERNEL_NAME), overrides=None, extra_arguments=None):
|
||||||
"""Write a kernel spec directory to `path`
|
"""Write a kernel spec directory to `path`
|
||||||
|
|
||||||
If `path` is not specified, a temporary directory is created.
|
If `path` is not specified, a temporary directory is created.
|
||||||
@ -69,7 +69,7 @@ def write_kernel_spec(path=None, overrides=None, extra_arguments=None):
|
|||||||
"""
|
"""
|
||||||
if path is None:
|
if path is None:
|
||||||
path = os.path.join(tempfile.mkdtemp(suffix='_kernels'), KERNEL_NAME)
|
path = os.path.join(tempfile.mkdtemp(suffix='_kernels'), KERNEL_NAME)
|
||||||
|
print( path )
|
||||||
# stage resources
|
# stage resources
|
||||||
shutil.copytree(RESOURCES, path)
|
shutil.copytree(RESOURCES, path)
|
||||||
# write kernel.json
|
# write kernel.json
|
||||||
@ -142,7 +142,7 @@ from traitlets.config import Application
|
|||||||
|
|
||||||
class InstallYAPKernelSpecApp(Application):
|
class InstallYAPKernelSpecApp(Application):
|
||||||
"""Dummy app wrapping argparse"""
|
"""Dummy app wrapping argparse"""
|
||||||
name = 'ipython-kernel-install'
|
name = 'yap-kernel-install'
|
||||||
|
|
||||||
def initialize(self, argv=None):
|
def initialize(self, argv=None):
|
||||||
if argv is None:
|
if argv is None:
|
||||||
@ -152,12 +152,12 @@ class InstallYAPKernelSpecApp(Application):
|
|||||||
def start(self):
|
def start(self):
|
||||||
import argparse
|
import argparse
|
||||||
parser = argparse.ArgumentParser(prog=self.name,
|
parser = argparse.ArgumentParser(prog=self.name,
|
||||||
description="Install the IPython kernel spec.")
|
description="Install the YAP kernel spec.")
|
||||||
parser.add_argument('--user', action='store_true',
|
parser.add_argument('--user', action='store_true',
|
||||||
help="Install for the current user instead of system-wide")
|
help="Install for the current user instead of system-wide")
|
||||||
parser.add_argument('--name', type=str, default=KERNEL_NAME,
|
parser.add_argument('--name', type=str, default=KERNEL_NAME,
|
||||||
help="Specify a name for the kernelspec."
|
help="Specify a name for the kernelspec."
|
||||||
" This is needed to have multiple IPython kernels at the same time.")
|
" This is needed to have multiple YAP kernels at the same time.")
|
||||||
parser.add_argument('--display-name', type=str,
|
parser.add_argument('--display-name', type=str,
|
||||||
help="Specify the display name for the kernelspec."
|
help="Specify the display name for the kernelspec."
|
||||||
" This is helpful when you have multiple IPython kernels.")
|
" This is helpful when you have multiple IPython kernels.")
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
:- use_module(library(python)).
|
|
||||||
|
|
||||||
:- initialization
|
|
||||||
ensure_loaded(library(yapi) ),
|
|
||||||
python_import(sys).
|
|
||||||
|
|
||||||
%% @pred yap_query(0:Goalc, - Dictionary)
|
|
||||||
%%
|
|
||||||
%% dictionary, Examples
|
|
||||||
%%
|
|
||||||
%%
|
|
||||||
jupyter_query( Self, String ) :-
|
|
||||||
set_python_output( Self, Output , Error),
|
|
||||||
python_query( Self, String ),
|
|
||||||
close( Output ),
|
|
||||||
cloe( Error ).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
set_python_output(_Self,Output,Error) :-
|
|
||||||
open('//python/sys.stdout', append, Output, [alias(output)]),
|
|
||||||
open('//python/sys.stderr', append, Error, [alias(error)]),
|
|
||||||
yap_flag(user_output, output),
|
|
||||||
yap_flag(user_error, error).
|
|
||||||
|
|
||||||
|
|
@ -2,20 +2,19 @@
|
|||||||
|
|
||||||
import getpass
|
import getpass
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
|
||||||
|
|
||||||
from IPython.core import release
|
|
||||||
from ipython_genutils.py3compat import builtin_mod, PY3, unicode_type, safe_unicode
|
|
||||||
from IPython.utils.tokenutil import token_at_cursor, line_at_cursor
|
from IPython.utils.tokenutil import token_at_cursor, line_at_cursor
|
||||||
|
from ipython_genutils.py3compat import builtin_mod, PY3, unicode_type, safe_unicode
|
||||||
from traitlets import Instance, Type, Any, List
|
from traitlets import Instance, Type, Any, List
|
||||||
|
|
||||||
|
from yap_ipython.core.interactiveshell import YAPInteractive
|
||||||
from .comm import CommManager
|
from .comm import CommManager
|
||||||
from .kernelbase import Kernel as KernelBase
|
from .kernelbase import Kernel as KernelBase
|
||||||
from .zmqshell import ZMQInteractiveShell
|
from .zmqshell import ZMQInteractiveShell
|
||||||
from .interactiveshell import YAPInteraction
|
|
||||||
|
|
||||||
class YAPKernel(KernelBase):
|
class YAPKernel(KernelBase):
|
||||||
shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
|
shell = Instance('yap_ipython.core.interactiveshell.YAPInteractiveABC',
|
||||||
allow_none=True)
|
allow_none=True)
|
||||||
shell_class = Type(ZMQInteractiveShell)
|
shell_class = Type(ZMQInteractiveShell)
|
||||||
user_module = Any()
|
user_module = Any()
|
||||||
@ -57,7 +56,7 @@ class YAPKernel(KernelBase):
|
|||||||
for msg_type in comm_msg_types:
|
for msg_type in comm_msg_types:
|
||||||
self.shell_handlers[msg_type] = getattr(self.comm_manager, msg_type)
|
self.shell_handlers[msg_type] = getattr(self.comm_manager, msg_type)
|
||||||
|
|
||||||
self.engine = YAPInteraction(self)
|
self.engine = YAPInteractive()
|
||||||
self.shell._last_traceback = None
|
self.shell._last_traceback = None
|
||||||
self.shell.run_cell = self.engine.run_cell
|
self.shell.run_cell = self.engine.run_cell
|
||||||
|
|
||||||
@ -100,8 +99,8 @@ class YAPKernel(KernelBase):
|
|||||||
'version': '6.3',
|
'version': '6.3',
|
||||||
'mimetype': 'text/x-prolog',
|
'mimetype': 'text/x-prolog',
|
||||||
'codemirror_mode': {
|
'codemirror_mode': {
|
||||||
'name': 'prolog',
|
'name': 'prolog' #,
|
||||||
'version': sys.version_info[0]
|
#'version': '3'
|
||||||
},
|
},
|
||||||
'pygments_lexer': 'prolog',
|
'pygments_lexer': 'prolog',
|
||||||
'nbconvert_exporter': 'prolog',
|
'nbconvert_exporter': 'prolog',
|
||||||
|
@ -25,8 +25,8 @@ from threading import local
|
|||||||
|
|
||||||
from tornado import ioloop
|
from tornado import ioloop
|
||||||
|
|
||||||
from IPython.core.interactiveshell import (
|
from yap_ipython.core.interactiveshell import (
|
||||||
InteractiveShell, InteractiveShellABC
|
YAPInteractive, YAPInteractiveABC
|
||||||
)
|
)
|
||||||
from IPython.core import page
|
from IPython.core import page
|
||||||
from IPython.core.autocall import ZMQExitAutocall
|
from IPython.core.autocall import ZMQExitAutocall
|
||||||
@ -437,7 +437,7 @@ class KernelMagics(Magics):
|
|||||||
print("Autosave disabled")
|
print("Autosave disabled")
|
||||||
|
|
||||||
|
|
||||||
class ZMQInteractiveShell(InteractiveShell):
|
class ZMQInteractiveShell(YAPInteractive):
|
||||||
"""A subclass of InteractiveShell for ZMQ."""
|
"""A subclass of InteractiveShell for ZMQ."""
|
||||||
|
|
||||||
displayhook_class = Type(ZMQShellDisplayHook)
|
displayhook_class = Type(ZMQShellDisplayHook)
|
||||||
@ -598,4 +598,4 @@ class ZMQInteractiveShell(InteractiveShell):
|
|||||||
# https://ipython.readthedocs.io/en/latest/install/kernel_install.html
|
# https://ipython.readthedocs.io/en/latest/install/kernel_install.html
|
||||||
pass
|
pass
|
||||||
|
|
||||||
InteractiveShellABC.register(ZMQInteractiveShell)
|
YAPInteractiveABC.register(ZMQInteractiveShell)
|
||||||
|
@ -12,5 +12,5 @@ if __name__ == '__main__':
|
|||||||
if sys.path[0] == '':
|
if sys.path[0] == '':
|
||||||
del sys.path[0]
|
del sys.path[0]
|
||||||
|
|
||||||
from inprocess.ipkernel import kernelapp as app
|
from yap_kernel import kernelapp as app
|
||||||
app.launch_new_instance()
|
app.launch_new_instance()
|
||||||
|
Reference in New Issue
Block a user