Skip to content

Commit 59d430f

Browse files
authored
Merge pull request #152 from Quansight/ThomasPnumpy
add hook_enable/hook_disable
2 parents f2f4cea + 662f652 commit 59d430f

4 files changed

Lines changed: 105 additions & 6 deletions

File tree

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
print("**could not install pip or setuptools_scm, version is defaulted")
3434

3535
def myversion():
36-
version = '2.0.22'
36+
version = '2.0.23'
3737
try:
3838
mversion = get_version()
3939
s = mversion.split('.')
@@ -118,6 +118,7 @@ def read(*names, **kwargs):
118118
'Programming Language :: Python :: 3.6',
119119
'Programming Language :: Python :: 3.7',
120120
'Programming Language :: Python :: 3.8',
121+
'Programming Language :: Python :: 3.9',
121122
'Programming Language :: Python :: Implementation :: CPython',
122123
'Programming Language :: Python :: Implementation :: PyPy',
123124
'Topic :: Utilities',

src/pnumpy/_pnumpy.cpp

Lines changed: 93 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ stArangeFunc g_ArangeFuncLUT[ATOP_LAST];
345345

346346

347347
// set to 0 to disable
348-
stSettings g_Settings = { 1, 0, 0, 0, 0 };
348+
stSettings g_Settings = { 1, 0, 0, 0, 0, 0, 0 };
349349

350350
// Macro used just before call a ufunc
351351
#define LEDGER_START() g_Settings.LedgerEnabled = 0; int64_t ledgerStartTime = __rdtsc();
@@ -1555,7 +1555,6 @@ PyObject* newinit(PyObject* self, PyObject* args, PyObject* kwargs) {
15551555

15561556
// Allocate an array of 10
15571557
PyArrayObject* pTemp= AllocateNumpyArray(1, dims, srcdtype);
1558-
//PyArray_Descr* pSrcDtype = PyArray_DescrFromType(srcdtype);
15591558
PyArray_Descr* pSrcDtype = PyArray_DESCR(pTemp);
15601559

15611560
if (pSrcDtype) {
@@ -1662,9 +1661,10 @@ PyObject* newinit(PyObject* self, PyObject* args, PyObject* kwargs) {
16621661
// }
16631662
//}
16641663
}
1665-
//Py_DECREF(pSrcDtype);
1666-
1667-
//Py_DECREF(arr);
1664+
//Py_DECREF(pSrcDtype);
1665+
//Py_DECREF(pTemp);
1666+
//
1667+
16681668
}
16691669
RETURN_NONE;
16701670
}
@@ -1675,6 +1675,94 @@ PyObject* newinit(PyObject* self, PyObject* args, PyObject* kwargs) {
16751675
RETURN_NONE;
16761676
}
16771677

1678+
//---------------------------------------------------------
1679+
// GetItem hook
1680+
//
1681+
extern "C"
1682+
PyObject * GetItemHook(PyObject* aValues, PyObject* aIndex) {
1683+
1684+
// Quick check for an array or we bail
1685+
if (PyType_IsSubtype(aIndex->ob_type, &PyArray_Type)) {
1686+
int32_t numpyValuesType = PyArray_TYPE((PyArrayObject*)aValues);
1687+
int32_t numpyIndexType = PyArray_TYPE((PyArrayObject*)aIndex);
1688+
1689+
PyObject* result = NULL;
1690+
if (numpyIndexType == NPY_BOOL) {
1691+
// special path for boolean
1692+
result = BooleanIndexInternal((PyArrayObject*)aValues, (PyArrayObject*)aIndex);
1693+
if (result) {
1694+
return result;
1695+
}
1696+
// clear error since punting
1697+
PyErr_Clear();
1698+
1699+
} else
1700+
// TODO: improve this to handle strings/unicode/datetime/other
1701+
if (numpyIndexType <= NPY_LONGDOUBLE) {
1702+
result = getitem(aValues, aIndex);
1703+
if (result) {
1704+
return result;
1705+
}
1706+
PyErr_Clear();
1707+
}
1708+
}
1709+
return g_Settings.NumpyGetItem(aValues, aIndex);
1710+
}
1711+
1712+
//---------------------------------------------------------
1713+
// Call to get hook
1714+
extern "C"
1715+
PyObject * hook_enable(PyObject * self, PyObject * args) {
1716+
1717+
if (g_Settings.NumpyGetItem == NULL) {
1718+
npy_intp dims[1] = { 10 };
1719+
1720+
// Allocate an array of 10 bools
1721+
PyArrayObject* pTemp = AllocateNumpyArray(1, dims, 0);
1722+
if (pTemp) {
1723+
struct _typeobject* pNumpyType = ((PyObject*)pTemp)->ob_type;
1724+
1725+
// Not hooked yet
1726+
// PyNumberMethods* numbermethods = pNumpyType->tp_as_number;
1727+
// richcmpfunc comparefunc = pNumpyType->tp_richcompare;
1728+
// __setitem__
1729+
// objobjargproc PyMappingMethods.mp_ass_subscript
1730+
1731+
// __getitem__
1732+
// Reroute hook
1733+
g_Settings.NumpyGetItem= pNumpyType->tp_as_mapping->mp_subscript;
1734+
pNumpyType->tp_as_mapping->mp_subscript = GetItemHook;
1735+
1736+
Py_DECREF(pTemp);
1737+
RETURN_TRUE;
1738+
}
1739+
}
1740+
RETURN_FALSE;
1741+
}
1742+
1743+
//---------------------------------------------------------
1744+
// Call to remove previous hook
1745+
extern "C"
1746+
PyObject * hook_disable(PyObject * self, PyObject * args) {
1747+
if (g_Settings.NumpyGetItem != NULL) {
1748+
npy_intp dims[1] = { 10 };
1749+
1750+
// Allocate an array of 10 bools
1751+
PyArrayObject* pTemp = AllocateNumpyArray(1, dims, 0);
1752+
if (pTemp) {
1753+
struct _typeobject* pNumpyType = ((PyObject*)pTemp)->ob_type;
1754+
// __getitem__
1755+
// Put hook back
1756+
pNumpyType->tp_as_mapping->mp_subscript = g_Settings.NumpyGetItem;
1757+
g_Settings.NumpyGetItem = NULL;
1758+
Py_DECREF(pTemp);
1759+
RETURN_TRUE;
1760+
}
1761+
}
1762+
RETURN_FALSE;
1763+
}
1764+
1765+
16781766
extern "C"
16791767
PyObject * atop_enable(PyObject * self, PyObject * args) {
16801768
g_Settings.AtopEnabled = TRUE;

src/pnumpy/common.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ struct stSettings {
2626
int32_t RecyclerEnabled;
2727
int32_t ZigZag; // set to 0 to disable
2828
int32_t Initialized;
29+
int32_t Reserved;
30+
binaryfunc NumpyGetItem; // optional hook
2931
};
3032

3133
extern stSettings g_Settings;
@@ -112,6 +114,9 @@ extern ArrayInfo* BuildArrayInfo(
112114

113115
extern void FreeArrayInfo(ArrayInfo* pAlloc);
114116

117+
extern PyObject* BooleanIndexInternal(PyArrayObject* aValues, PyArrayObject* aIndex);
118+
extern "C" PyObject *getitem(PyObject * self, PyObject * args);
119+
115120
#define RETURN_NONE Py_INCREF(Py_None); return Py_None;
116121
#define RETURN_FALSE Py_XINCREF(Py_False); return Py_False;
117122
#define RETURN_TRUE Py_XINCREF(Py_True); return Py_True;

src/pnumpy/module_init.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ extern "C" PyObject* recycler_disable(PyObject * self, PyObject * args);
3737
extern "C" PyObject* recycler_isenabled(PyObject * self, PyObject * args);
3838
extern "C" PyObject* recycler_info(PyObject * self, PyObject * args);
3939

40+
extern "C" PyObject * hook_enable(PyObject * self, PyObject * args);
41+
extern "C" PyObject * hook_disable(PyObject * self, PyObject * args);
42+
4043
extern "C" PyObject* timer_gettsc(PyObject * self, PyObject * args);
4144
extern "C" PyObject* timer_getutc(PyObject * self, PyObject * args);
4245
extern "C" PyObject* cpustring(PyObject * self, PyObject * args);
@@ -69,6 +72,8 @@ static PyMethodDef module_functions[] = {
6972
{"thread_zigzag", (PyCFunction)thread_zigzag, METH_VARARGS, "toggle zigzag mode"},
7073
{"timer_gettsc", (PyCFunction)timer_gettsc, METH_VARARGS, TIMER_GETTSC_DOC},
7174
{"timer_getutc", (PyCFunction)timer_getutc, METH_VARARGS, TIMER_GETUTC_DOC},
75+
{"hook_enable", (PyCFunction)hook_enable, METH_VARARGS, "Enable hook for numpy array __getitem__ for fancy and bool indexing"},
76+
{"hook_disable", (PyCFunction)hook_disable, METH_VARARGS, "Disable hook for numpy array __getitem__ for fancy and bool indexing"},
7277
{"ledger_enable", (PyCFunction)ledger_enable, METH_VARARGS, LEDGER_ENABLE_DOC},
7378
{"ledger_disable", (PyCFunction)ledger_disable, METH_VARARGS, LEDGER_DISABLE_DOC},
7479
{"ledger_isenabled", (PyCFunction)ledger_isenabled, METH_VARARGS, LEDGER_ISENABLED_DOC},

0 commit comments

Comments
 (0)