move hooks into python

This commit is contained in:
Michael Davidsaver
2013-04-14 12:01:56 -04:00
parent 4d2c3c4fd3
commit 1e34cf9b76
2 changed files with 42 additions and 57 deletions

View File

@ -23,9 +23,6 @@
#include "pydevsup.h" #include "pydevsup.h"
/* dictionary of initHook names */
static PyObject *hooktable;
typedef struct { typedef struct {
const initHookState state; const initHookState state;
const char * const name; const char * const name;
@ -98,46 +95,30 @@ void evalFilePy(const char* file)
static void pyhook(initHookState state) static void pyhook(initHookState state)
{ {
static int madenoise = 0;
PyGILState_STATE gilstate; PyGILState_STATE gilstate;
PyObject *mod, *ret;
/* ignore deprecated init hooks */
if(state==initHookAfterInterruptAccept || state==initHookAtEnd)
return;
gilstate = PyGILState_Ensure(); gilstate = PyGILState_Ensure();
if(hooktable && PyDict_Check(hooktable)) { mod = PyImport_ImportModule("devsup.hooks");
PyObject *next; if(!mod) {
PyObject *key = PyInt_FromLong((long)state); if(!madenoise)
PyObject *list = PyDict_GetItem(hooktable, key); fprintf(stderr, "Couldn't import devsup.hooks\n");
Py_DECREF(key); madenoise=1;
return;
if(list) { }
ret = PyObject_CallMethod(mod, "_runhook", "l", (long)state);
list = PyObject_GetIter(list); Py_DECREF(mod);
if(!list) { if(PyErr_Occurred()) {
fprintf(stderr, "hook sequence not iterable!");
} else {
while((next=PyIter_Next(list))!=NULL) {
PyObject *obj;
if(!PyCallable_Check(next))
continue;
obj = PyObject_CallFunction(next, "");
Py_DECREF(next);
if(obj)
Py_DECREF(obj);
else {
PyErr_Print(); PyErr_Print();
PyErr_Clear(); PyErr_Clear();
} }
} Py_XDECREF(ret);
if(!PyErr_Occurred()) {
PyErr_Print();
PyErr_Clear();
}
Py_DECREF(list);
}
}
}
PyGILState_Release(gilstate); PyGILState_Release(gilstate);
} }
@ -174,10 +155,6 @@ PyMODINIT_FUNC init_dbapi(void)
import_array(); import_array();
hooktable = PyDict_New();
if(!hooktable)
MODINIT_RET(NULL);
if(pyField_prepare()) if(pyField_prepare())
MODINIT_RET(NULL); MODINIT_RET(NULL);
if(pyRecord_prepare()) if(pyRecord_prepare())
@ -202,8 +179,6 @@ PyMODINIT_FUNC init_dbapi(void)
for(st = statenames; st->name; st++) { for(st = statenames; st->name; st++) {
PyDict_SetItemString(hookdict, st->name, PyInt_FromLong((long)st->state)); PyDict_SetItemString(hookdict, st->name, PyInt_FromLong((long)st->state));
} }
Py_INCREF(hooktable); /* an extra ref for the global pointer */
PyModule_AddObject(mod, "_hooktable", hooktable);
pyField_setup(mod); pyField_setup(mod);
pyRecord_setup(mod); pyRecord_setup(mod);
@ -224,10 +199,6 @@ static void cleanupPy(void *junk)
pyField_cleanup(); pyField_cleanup();
/* release extra reference for hooktable */
Py_XDECREF(hooktable);
hooktable = NULL;
Py_Finalize(); Py_Finalize();
} }

View File

@ -1,5 +1,8 @@
from __future__ import print_function from __future__ import print_function
import traceback
from collections import defaultdict
try: try:
import _dbapi import _dbapi
except ImportError: except ImportError:
@ -13,12 +16,16 @@ __all__ = [
hooknames = _dbapi._hooks.keys() hooknames = _dbapi._hooks.keys()
_revnames = dict([(v,k) for k,v in _dbapi._hooks.iteritems()])
_hooktable = defaultdict(list)
def addHook(state, func): def addHook(state, func):
"""addHook("stats", funcion) """addHook("stats", funcion)
Add callable to IOC start sequence. Add callable to IOC start sequence.
Callables are run in the reverse of the order in Callables are run in the order in
which they were added. which they were added (except for 'AtIocExit').
>>> def show(): >>> def show():
... print 'State Occurred' ... print 'State Occurred'
@ -28,13 +35,7 @@ def addHook(state, func):
for cleanup actions during IOC shutdown. for cleanup actions during IOC shutdown.
""" """
sid = _dbapi._hooks[state] sid = _dbapi._hooks[state]
try: _hooktable[sid].append(func)
slist = _dbapi._hooktable[sid]
except KeyError:
slist = []
_dbapi._hooktable[sid] = slist
slist.append(func)
def debugHooks(): def debugHooks():
@ -44,3 +45,16 @@ def debugHooks():
def _showstate(state=h): def _showstate(state=h):
print('Reached state',state) print('Reached state',state)
addHook(h, _showstate) addHook(h, _showstate)
def _runhook(sid):
name = _revnames[sid]
pop = -1 if name=='AtIocExit' else 0
fns = _hooktable.get(sid)
if fns is not None:
while len(fns)>0:
fn = fns.pop(pop)
try:
fn()
except:
print("Error running",name,"hook",fn)
traceback.print_exc()