Skip to content

Commit 7ccb462

Browse files
cmccarthy1Conor McCarthy
andauthored
Optional error message conforming to Python return. KXI-1467 (#100)
* Update to p.q logic for handling sys.argv * reintroduction of old logic * addition of initial sys argv and embedpy version check * Addition of functionality to return Python traceback rather than q shorthand * Memory leak fix and removal of environment variable check C side * reformat of prr to use modifiable global rather than env variable * Initial pass at rectifying potential buffer overflow * update to py.c to initialize traceback import on init * closer fit to code base style Co-authored-by: Conor McCarthy <conormccarthy@brainpool1.mynet>
1 parent 3a5fe7e commit 7ccb462

File tree

4 files changed

+23
-6
lines changed

4 files changed

+23
-6
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@
44

55
*.bak
66
q
7+
8+
k.h
9+
*.so
10+
m64/

makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Q = $(QHOME)/$(QARCH)
2626

2727
p.so: $(QARCH)/p.so
2828
cp $(QARCH)/p.so .
29+
2930
$(QARCH)/p.so: py.c py.h k.h
3031
mkdir -p $(QARCH)
3132
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
@@ -42,7 +43,8 @@ k.h:
4243
q.lib:
4344
curl -O -J -L https://github.com/KxSystems/kdb/raw/master/w64/q.lib
4445

45-
install:
46+
install: p.so
47+
cp p.q p.k $(QHOME)
4648
install $(TGT) $(Q)
4749
clean:
4850
rm -f p.so

py.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@
22
ZS zs(K x){S s=memcpy(malloc(xn+1),xG,xn);R s[xn]=0,s;}Z K1(cs){K r,y;P(xt||!xn,r1(x))DO(xn,P(10!=kK(x)[i]->t,r1(x)))r=ktn(KS,xn);DO(xn,y=kK(x)[i];kS(r)[i]=sn(y->G0,y->n))R r;}
33
ZK at(K x,J i){R!xt?r1(kK(x)[i]):k(0,"@",r1(x),kj(i),0);}ZJ cn(K x){J n;x=k(0,"#:",r1(x),0);n=xt==-KJ?xj:nj;R r0(x),n;}ZK val(K x){R k(0,".:",r1(x),0);}
44
ZI g1(){R PyGILState_Ensure();}ZV g0(I g){PyGILState_Release(g);}ZK ktrr(){R krr("type");}ZP ptrr(){R PyErr_BadArgument();}
5-
ZV*t1(){R PyEval_SaveThread();}ZV t0(V*t){PyEval_RestoreThread(t);}ZP M;ZV**N;ZP pe(K x){R PyErr_SetString(PyExc_RuntimeError,xs);}
5+
ZV*t1(){R PyEval_SaveThread();}ZV t0(V*t){PyEval_RestoreThread(t);}ZP M,errfmt;ZV**N;ZP pe(K x){R PyErr_SetString(PyExc_RuntimeError,xs);}
66
ZP p1(P p){Py_IncRef(p);R p;}ZV p0(P p){Py_DecRef(p);}ZI pt(P p,P t){P u=PyObject_Type(p);I f;f=(u==t||PyType_IsSubtype(u,t));p0(u);R f;}
77
ZP pg(K x){R(P)(kK(x)[1]);}ZV pd(K x){I g=g1();p0(pg(x));g0(g);}ZK kfp(P p){K x=knk(2,pd,p);R xt=112,x;}ZI pq(K x){R xt==112&&xn==2&&*kK(x)==(K)pd;}
88
ZK kfg(P p){R PyCapsule_GetPointer(p,"k");}ZV kfd(P p){r0(kfg(p));}ZP pfk(K x){R PyCapsule_New(r1(x),"k",kfd);}
9-
ZK prr(S s){Z __thread C b[4096];J n=sizeof(b)-1;P t,v,d,a;*b=0;strncat(b,s,n);PyErr_Fetch(&t,&v,&d);if(t){PyErr_NormalizeException(&t,&v,&d);
10-
strncat(strncat(b,": ",n),PyUnicode_AsUTF8AndSize(a=PyObject_Str(v),0),n);p0(a);p0(t);p0(v);p0(d);}R krr(b);}ZK prg(S s,I g){K r=prr(s);g0(g);R r;}
9+
ZJ pyerr=0;ZS updbuff(S d,S s,J*n){J k=strnlen(s,*n);memcpy(d,s,k);*n=*n>k?*n-k:0;R d+k;}
10+
ZK prr(S s){Z __thread C b[BUFFSIZE];S p=b;J n=sizeof(b)-1;P t,v,d,a;p=updbuff(p,s,&n);PyErr_Fetch(&t,&v,&d);
11+
if(t&&n){p=updbuff(p,": ",&n);PyErr_NormalizeException(&t,&v,&d);
12+
if(pyerr)a=PyObject_CallFunctionObjArgs(errfmt,t,v,d,NULL),p0(v),v=a;p=updbuff(p,PyUnicode_AsUTF8AndSize(a=PyObject_Str(v),0),&n);p0(t);p0(v);p0(d);p0(a);}
13+
if(!n){n=2;updbuff(p-2,"..",&n);}R *p=0,krr(b);}
14+
ZK prg(S s,I g){K r=prr(s);g0(g);R r;}
1115

1216
ZK ko(P);ZK cf;//k from python
1317
ZK kstr(I t,P p){K r;L n;S s=t==KG?PyBytes_AsStringAndSize(p,&s,&n)<0?0:s:PyUnicode_AsUTF8AndSize(p,&n);P(!s,prr("kstr"))r=kpn(s,n);R r->t=t,r;}
@@ -43,15 +47,18 @@ Z K2(getattr){P p;I g;P(y->t!=-KS||!pq(x),ktrr())g=g1();p=PyObject_GetAttrString
4347
Z K3(call){P a,k,p;I g;P(!pq(x)||!pq(z)&&z->t!=XD,ktrr())g=g1();a=pq(y)?p1(pg(y)):pseq(1,y);P(!a,prg("call a",g))k=pq(z)?p1(pg(z)):pdict(z);P(!k,(p0(a),prg("call k",g)))
4448
p=PyObject_Call(pg(x),a,k);P(!p,(p0(a),p0(k),prg("call",g)))p0(a);p0(k);g0(g);R kfp(p);}
4549
Z K1(setconv){P(xt<100||xt>111,ktrr())r0(cf);cf=r1(x);R 0;}Z K1(getconv){R r1(cf);}Z K1(isp){R kb(pq(x));}
50+
Z K1(setpyerr){P(xt!=-KJ,ktrr())P(!errfmt,krr("traceback.format_exception"))pyerr=xj;R 0;}Z K1(getpyerr){R kj(pyerr);}
51+
4652

4753
ZV*t;EXP K2(init){
4854
ZI i=0;I f,g;S l,h;K n,v;P a,b;P(i,0)l=zs(x),h=zs(y);f=pyl(l);free(l);
4955
P(!f,krr("libpython"))Py_SetPythonHome(Py_DecodeLocale(h,0));free(h);
5056
Py_InitializeEx(0);if(PyEval_ThreadsInitialized()&&!PyGILState_Check())t0(PyGILState_GetThisThreadState());PyEval_InitThreads();
5157
M=PyModule_GetDict(PyImport_AddModule("__main__"));cf=k(0,"::",0);n=ktn(KS,0);v=ktn(0,0);
5258
if(a=PyImport_ImportModule("numpy.core.multiarray")){N=PyCapsule_GetPointer(b=PyObject_GetAttrString(a,"_ARRAY_API"),0);if(!N||!pyn(N))N=0;p0(b);p0(a);}PyErr_Clear();
59+
if(a=PyImport_ImportModule("traceback")){errfmt=PyObject_GetAttrString(a,"format_exception");p0(a);}PyErr_Clear();
5360
#define F(f,i) js(&n,ss(#f));jk(&v,dl(f,i));
54-
F(eval,1)F(e,1)F(py2q,1)F(q2py,1)F(get,1)F(set,2)F(import,1)F(getattr,2)F(call,3)F(isp,1)F(setconv,1)F(getconv,1)js(&n,ss("numpy"));jk(&v,kb(!!N));
55-
t=t1();i=1;R xD(n,v);}
61+
F(setpyerr,1)F(getpyerr,1)F(eval,1)F(e,1)F(py2q,1)F(q2py,1)F(get,1)F(set,2)F(import,1)F(getattr,2)F(call,3)F(isp,1)F(setconv,1)F(getconv,1)js(&n,ss("numpy"));
62+
jk(&v,kb(!!N));t=t1();i=1;R xD(n,v);}
5663
// a kludge for python modules which try to resolve main e.g. scipy.optimize
5764
int main(){}

py.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ typedef struct _p _p,*P;struct _p{L r;P t;L n;union{P*p;P v[1];};};typedef struc
8484
X(P,PyDict_SetItem,(P,P,P))\
8585
X(P,PyDict_Keys,(P))\
8686
X(P,PyDict_Values,(P))\
87+
X(P,PyObject_CallFunctionObjArgs,(P,...))\
88+
X(P,PyImport_Import,(P))\
8789

8890
//https://docs.scipy.org/doc/numpy/reference/c-api.html https://github.com/numpy/numpy/blob/master/numpy/core/code_generators/numpy_api.py
8991
#undef PyCFunction_New
@@ -115,6 +117,8 @@ ZI pyl(S l){
115117
#undef X
116118
R 1;}
117119

120+
#define BUFFSIZE 4096
121+
118122
ZI pyn(V**v){
119123
#define X(r,n,a,i) U(n=(T##n(*)a)v[i])
120124
NF

0 commit comments

Comments
 (0)