Skip to content

Commit

Permalink
Merge pull request #34 from static-frame/33/np2
Browse files Browse the repository at this point in the history
NumPy 2 support
  • Loading branch information
flexatone authored Jul 11, 2024
2 parents 9af0392 + 11d1f63 commit fd0b79d
Show file tree
Hide file tree
Showing 10 changed files with 26 additions and 48 deletions.
5 changes: 2 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ jobs:
matrix:
os: ${{ fromJson(needs.matrix_config.outputs.matrix_os) }}
python:
- {minor: 8, req_build: 'requirements-build-3_08.txt', req_test: 'requirements-dev-3_08.txt'}
- {minor: 9, req_build: 'requirements-build-3_11.txt', req_test: 'requirements-dev-3_11.txt'}
- {minor: 10, req_build: 'requirements-build-3_11.txt', req_test: 'requirements-dev-3_11.txt'}
- {minor: 11, req_build: 'requirements-build-3_11.txt', req_test: 'requirements-dev-3_11.txt'}
Expand All @@ -63,7 +62,7 @@ jobs:
- run: echo '::add-matcher::.github/problem-matchers/msvc.json'
if: startsWith(matrix.os, 'windows-')

- uses: pypa/cibuildwheel@v2.16.2
- uses: pypa/cibuildwheel@v2.18.0
if: matrix.os != 'macos-13-xlarge'
with:
output-dir: dist
Expand All @@ -77,7 +76,7 @@ jobs:

- run: pip install pipx
if: matrix.os == 'macos-13-xlarge'
- uses: pypa/cibuildwheel@v2.16.2
- uses: pypa/cibuildwheel@v2.18.0
if: matrix.os == 'macos-13-xlarge'
with:
output-dir: dist
Expand Down
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ Dependencies

ArrayMap requires the following:

- Python >= 3.8
- NumPy >= 1.18.5
- Python >= 3.9
- NumPy >= 1.19.5



Expand Down
37 changes: 11 additions & 26 deletions arraymap.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ typedef enum KeysArrayType{
NPY_DATETIMEUNIT
dt_unit_from_array(PyArrayObject* a) {
// This is based on get_datetime_metadata_from_dtype in the NumPy source, but that function is private. This does not check that the dytpe is of the appropriate type.
PyArray_DatetimeMetaData* dma = &(((PyArray_DatetimeDTypeMetaData *)PyArray_DESCR(a)->c_metadata)->meta);
PyArray_Descr* dt = PyArray_DESCR(a); // borrowed ref
PyArray_DatetimeMetaData* dma = &(((PyArray_DatetimeDTypeMetaData *)PyDataType_C_METADATA(dt))->meta);
return dma->base;
}

Expand Down Expand Up @@ -451,7 +452,6 @@ typedef struct FAMIObject {
Py_ssize_t index; // current index state, mutated in-place
} FAMIObject;


static void
fami_dealloc(FAMIObject *self)
{
Expand Down Expand Up @@ -550,7 +550,6 @@ static PyTypeObject FAMIType = {
.tp_name = "arraymap.FrozenAutoMapIterator",
};


static PyObject *
fami_new(FAMObject *fam, ViewKind kind, bool reversed)
{
Expand Down Expand Up @@ -601,27 +600,23 @@ name(PyObject *left, PyObject *right) \
return result; \
}


FAMV_SET_OP(famv_and, And)
FAMV_SET_OP(famv_or, Or)
FAMV_SET_OP(famv_subtract, Subtract)
FAMV_SET_OP(famv_xor, Xor)

# undef FAMV_SET_OP


static PyNumberMethods famv_as_number = {
.nb_and = (binaryfunc) famv_and,
.nb_or = (binaryfunc) famv_or,
.nb_subtract = (binaryfunc) famv_subtract,
.nb_xor = (binaryfunc) famv_xor,
};


static int fam_contains(FAMObject *, PyObject *);
static PyObject *famv_fami_new(FAMVObject *);


static int
famv_contains(FAMVObject *self, PyObject *other)
{
Expand All @@ -637,41 +632,35 @@ famv_contains(FAMVObject *self, PyObject *other)
return result;
}


static PySequenceMethods famv_as_sequence = {
.sq_contains = (objobjproc) famv_contains,
};


static void
famv_dealloc(FAMVObject *self)
{
Py_DECREF(self->fam);
PyObject_Del((PyObject *)self);
}


static PyObject *
famv_fami_new(FAMVObject *self)
{
return fami_new(self->fam, self->kind, false);
}


static PyObject *
famv_length_hint(FAMVObject *self)
{
return PyLong_FromSsize_t(self->fam->keys_size);
}


static PyObject *
famv_reversed(FAMVObject *self)
{
return fami_new(self->fam, self->kind, true);
}


static PyObject *
famv_isdisjoint(FAMVObject *self, PyObject *other)
{
Expand All @@ -684,7 +673,6 @@ famv_isdisjoint(FAMVObject *self, PyObject *other)
return PyBool_FromLong(result);
}


static PyObject *
famv_richcompare(FAMVObject *self, PyObject *other, int op)
{
Expand All @@ -703,15 +691,13 @@ famv_richcompare(FAMVObject *self, PyObject *other, int op)
return result;
}


static PyMethodDef famv_methods[] = {
{"__length_hint__", (PyCFunction) famv_length_hint, METH_NOARGS, NULL},
{"__reversed__", (PyCFunction) famv_reversed, METH_NOARGS, NULL},
{"isdisjoint", (PyCFunction) famv_isdisjoint, METH_O, NULL},
{NULL},
};


static PyTypeObject FAMVType = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_as_number = &famv_as_number,
Expand All @@ -724,7 +710,6 @@ static PyTypeObject FAMVType = {
.tp_richcompare = (richcmpfunc) famv_richcompare,
};


static PyObject *
famv_new(FAMObject *fam, ViewKind kind)
{
Expand Down Expand Up @@ -941,7 +926,7 @@ lookup_hash_unicode(
Py_ssize_t table_pos = hash & mask;

PyArrayObject *a = (PyArrayObject *)self->keys;
Py_ssize_t dt_size = PyArray_DESCR(a)->elsize / UCS4_SIZE;
Py_ssize_t dt_size = PyArray_ITEMSIZE(a) / UCS4_SIZE;
Py_ssize_t cmp_bytes = Py_MIN(key_size, dt_size) * UCS4_SIZE;

Py_hash_t h = 0;
Expand Down Expand Up @@ -983,7 +968,7 @@ lookup_hash_string(
Py_ssize_t table_pos = hash & mask;

PyArrayObject *a = (PyArrayObject *)self->keys;
Py_ssize_t dt_size = PyArray_DESCR(a)->elsize;
Py_ssize_t dt_size = PyArray_ITEMSIZE(a);
Py_ssize_t cmp_bytes = Py_MIN(key_size, dt_size);

Py_hash_t h = 0;
Expand Down Expand Up @@ -1284,7 +1269,7 @@ lookup_unicode(FAMObject *self, PyObject* key) {
return -1;
}
PyArrayObject *a = (PyArrayObject *)self->keys;
Py_ssize_t dt_size = PyArray_DESCR(a)->elsize / UCS4_SIZE;
Py_ssize_t dt_size = PyArray_ITEMSIZE(a) / UCS4_SIZE;
// if the key_size is greater than the dtype size of the array, we know there cannot be a match
Py_ssize_t k_size = PyUnicode_GetLength(key);
if (k_size > dt_size) {
Expand All @@ -1305,7 +1290,7 @@ lookup_string(FAMObject *self, PyObject* key) {
return -1;
}
PyArrayObject *a = (PyArrayObject *)self->keys;
Py_ssize_t dt_size = PyArray_DESCR(a)->elsize;
Py_ssize_t dt_size = PyArray_ITEMSIZE(a);
Py_ssize_t k_size = PyBytes_GET_SIZE(key);
if (k_size > dt_size) {
return -1;
Expand Down Expand Up @@ -1650,7 +1635,7 @@ copy_to_new(PyTypeObject *cls, FAMObject *self, FAMObject *new)
new->key_buffer = NULL;
if (new->keys_array_type == KAT_UNICODE) {
PyArrayObject *a = (PyArrayObject *)new->keys;
Py_ssize_t dt_size = PyArray_DESCR(a)->elsize / UCS4_SIZE;
Py_ssize_t dt_size = PyArray_ITEMSIZE(a) / UCS4_SIZE;
new->key_buffer = (Py_UCS4*)PyMem_Malloc((dt_size+1) * UCS4_SIZE);
}

Expand Down Expand Up @@ -1831,7 +1816,7 @@ get(FAMObject *self, PyObject *key, PyObject *missing) {
# define GET_ALL_FLEXIBLE(char_type, get_end_func, lookup_func, hash_func, to_obj_func) \
{ \
char_type* v; \
Py_ssize_t dt_size = PyArray_DESCR(key_array)->elsize / sizeof(char_type);\
Py_ssize_t dt_size = PyArray_ITEMSIZE(key_array) / sizeof(char_type);\
Py_ssize_t k_size; \
for (; i < key_size; i++) { \
v = (char_type*)PyArray_GETPTR1(key_array, i); \
Expand Down Expand Up @@ -2019,7 +2004,7 @@ fam_get_all(FAMObject *self, PyObject *key) {
# define GET_ANY_FLEXIBLE(char_type, get_end_func, lookup_func, hash_func) \
{ \
char_type* v; \
Py_ssize_t dt_size = PyArray_DESCR(key_array)->elsize / sizeof(char_type);\
Py_ssize_t dt_size = PyArray_ITEMSIZE(key_array) / sizeof(char_type);\
Py_ssize_t k_size; \
for (; i < key_size; i++) { \
v = (char_type*)PyArray_GETPTR1(key_array, i); \
Expand Down Expand Up @@ -2539,13 +2524,13 @@ fam_init(PyObject *self, PyObject *args, PyObject *kwargs)
break;
case KAT_UNICODE: {
// Over allocate buffer by 1 so there is room for null at end. This buffer is only used in lookup();
Py_ssize_t dt_size = PyArray_DESCR(a)->elsize / UCS4_SIZE;
Py_ssize_t dt_size = PyArray_ITEMSIZE(a) / UCS4_SIZE;
fam->key_buffer = (Py_UCS4*)PyMem_Malloc((dt_size+1) * UCS4_SIZE);
INSERT_FLEXIBLE(Py_UCS4, insert_unicode, ucs4_get_end_p);
break;
}
case KAT_STRING: {
Py_ssize_t dt_size = PyArray_DESCR(a)->elsize;
Py_ssize_t dt_size = PyArray_ITEMSIZE(a);
INSERT_FLEXIBLE(char, insert_string, char_get_end_p);
break;
}
Expand Down
1 change: 0 additions & 1 deletion requirements-build-3_08.txt

This file was deleted.

2 changes: 1 addition & 1 deletion requirements-build-3_11.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
numpy==1.23.5
numpy==2.0.0
2 changes: 1 addition & 1 deletion requirements-build-3_12.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
numpy==1.26.2
numpy==2.0.0
setuptools==69.*
6 changes: 0 additions & 6 deletions requirements-dev-3_08.txt

This file was deleted.

6 changes: 3 additions & 3 deletions requirements-dev-3_11.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
black==22.3.0
black==24.4.2
hypothesis==6.70.0
invoke==1.7.1
invoke==2.2.0
pytest==7.1.2
tzdata==2022.1
numpy==1.23.5
numpy==1.23.5
2 changes: 1 addition & 1 deletion requirements-dev-3_12.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
black==22.3.0
black==24.4.2
hypothesis==6.70.0
invoke==2.2.0
pytest==7.1.2
Expand Down
9 changes: 5 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
with open("README.rst") as file:
LONG_DESCRIPTION = file.read()


def get_ext_dir(*components: tp.Iterable[str]) -> tp.Sequence[str]:
dirs = []
for sp in site.getsitepackages():
Expand All @@ -17,11 +18,12 @@ def get_ext_dir(*components: tp.Iterable[str]) -> tp.Sequence[str]:
dirs.append(fp)
return dirs


extension = setuptools.Extension(
"arraymap",
["arraymap.c"],
include_dirs=get_ext_dir("numpy", "core", "include"),
library_dirs=get_ext_dir("numpy", "core", "lib"),
include_dirs=get_ext_dir("numpy", "_core", "include"),
library_dirs=get_ext_dir("numpy", "_core", "lib"),
define_macros=[("AM_VERSION", AM_VERSION)],
libraries=["npymath"],
)
Expand All @@ -31,7 +33,7 @@ def get_ext_dir(*components: tp.Iterable[str]) -> tp.Sequence[str]:
version=AM_VERSION,
description="Dictionary-like lookup from NumPy array values to their integer positions",
long_description=LONG_DESCRIPTION,
python_requires=">=3.8.0",
python_requires=">=3.9",
install_requires=["numpy>=1.19.5"],
url="https://github.com/static-frame/arraymap",
author="Christopher Ariza, Brandt Bucher",
Expand All @@ -44,7 +46,6 @@ def get_ext_dir(*components: tp.Iterable[str]) -> tp.Sequence[str]:
"Operating System :: MacOS :: MacOS X",
"Operating System :: Microsoft :: Windows",
"Operating System :: POSIX",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
Expand Down

0 comments on commit fd0b79d

Please sign in to comment.