Skip to content

Commit 36fb95d

Browse files
committed
fix: tp_init accept 2 positional args and keyword data for PyPy
PyPy doesn't support tp_vectorcall, so tp_init is the only constructor path. Accept up to 2 positional args (data, seed) and keyword data= and seed=, with duplicate detection for both.
1 parent 5351994 commit 36fb95d

1 file changed

Lines changed: 112 additions & 16 deletions

File tree

src/_xxhash.c

Lines changed: 112 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -528,24 +528,48 @@ static int PYXXH32_init(PYXXH32Object *self, PyObject *args, PyObject *kwargs)
528528
Py_buffer buf = {NULL, NULL};
529529
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
530530

531+
/* positional args: data, then optional seed */
531532
if (nargs >= 1) {
532533
data_obj = PyTuple_GET_ITEM(args, 0);
533534
if (kwargs && PyDict_GetItemString(kwargs, "data")) {
534-
PyErr_SetString(PyExc_TypeError, "__init__() got multiple values for argument 'data'");
535+
PyErr_SetString(PyExc_TypeError,
536+
"__init__() got multiple values for argument 'data'");
535537
return -1;
536538
}
537-
if (nargs > 1) {
538-
PyErr_SetString(PyExc_TypeError, "__init__() takes at most 1 positional argument");
539+
}
540+
if (nargs >= 2) {
541+
seed = (XXH32_hash_t)PyLong_AsUnsignedLongMask(PyTuple_GET_ITEM(args, 1));
542+
if (PyErr_Occurred()) return -1;
543+
if (kwargs && PyDict_GetItemString(kwargs, "seed")) {
544+
PyErr_SetString(PyExc_TypeError,
545+
"__init__() got multiple values for argument 'seed'");
539546
return -1;
540547
}
541548
}
549+
if (nargs > 2) {
550+
PyErr_SetString(PyExc_TypeError,
551+
"__init__() takes at most 2 positional arguments");
552+
return -1;
553+
}
554+
555+
/* keyword args */
542556
if (kwargs) {
543-
PyObject *val = PyDict_GetItemString(kwargs, "seed");
557+
PyObject *val = PyDict_GetItemString(kwargs, "data");
558+
if (val) {
559+
if (data_obj) {
560+
PyErr_SetString(PyExc_TypeError,
561+
"__init__() got multiple values for argument 'data'");
562+
return -1;
563+
}
564+
data_obj = val;
565+
}
566+
val = PyDict_GetItemString(kwargs, "seed");
544567
if (val) {
545568
seed = (XXH32_hash_t)PyLong_AsUnsignedLongMask(val);
546569
if (PyErr_Occurred()) return -1;
547570
}
548571
}
572+
549573
if (data_obj) {
550574
if (_get_buffer_or_str(data_obj, &buf) < 0)
551575
return -1;
@@ -913,24 +937,48 @@ static int PYXXH64_init(PYXXH64Object *self, PyObject *args, PyObject *kwargs)
913937
Py_buffer buf = {NULL, NULL};
914938
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
915939

940+
/* positional args: data, then optional seed */
916941
if (nargs >= 1) {
917942
data_obj = PyTuple_GET_ITEM(args, 0);
918943
if (kwargs && PyDict_GetItemString(kwargs, "data")) {
919-
PyErr_SetString(PyExc_TypeError, "__init__() got multiple values for argument 'data'");
944+
PyErr_SetString(PyExc_TypeError,
945+
"__init__() got multiple values for argument 'data'");
920946
return -1;
921947
}
922-
if (nargs > 1) {
923-
PyErr_SetString(PyExc_TypeError, "__init__() takes at most 1 positional argument");
948+
}
949+
if (nargs >= 2) {
950+
seed = PyLong_AsUnsignedLongLongMask(PyTuple_GET_ITEM(args, 1));
951+
if (PyErr_Occurred()) return -1;
952+
if (kwargs && PyDict_GetItemString(kwargs, "seed")) {
953+
PyErr_SetString(PyExc_TypeError,
954+
"__init__() got multiple values for argument 'seed'");
924955
return -1;
925956
}
926957
}
958+
if (nargs > 2) {
959+
PyErr_SetString(PyExc_TypeError,
960+
"__init__() takes at most 2 positional arguments");
961+
return -1;
962+
}
963+
964+
/* keyword args */
927965
if (kwargs) {
928-
PyObject *val = PyDict_GetItemString(kwargs, "seed");
966+
PyObject *val = PyDict_GetItemString(kwargs, "data");
967+
if (val) {
968+
if (data_obj) {
969+
PyErr_SetString(PyExc_TypeError,
970+
"__init__() got multiple values for argument 'data'");
971+
return -1;
972+
}
973+
data_obj = val;
974+
}
975+
val = PyDict_GetItemString(kwargs, "seed");
929976
if (val) {
930977
seed = PyLong_AsUnsignedLongLongMask(val);
931978
if (PyErr_Occurred()) return -1;
932979
}
933980
}
981+
934982
if (data_obj) {
935983
if (_get_buffer_or_str(data_obj, &buf) < 0)
936984
return -1;
@@ -1297,24 +1345,48 @@ static int PYXXH3_64_init(PYXXH3_64Object *self, PyObject *args, PyObject *kwarg
12971345
Py_buffer buf = {NULL, NULL};
12981346
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
12991347

1348+
/* positional args: data, then optional seed */
13001349
if (nargs >= 1) {
13011350
data_obj = PyTuple_GET_ITEM(args, 0);
13021351
if (kwargs && PyDict_GetItemString(kwargs, "data")) {
1303-
PyErr_SetString(PyExc_TypeError, "__init__() got multiple values for argument 'data'");
1352+
PyErr_SetString(PyExc_TypeError,
1353+
"__init__() got multiple values for argument 'data'");
13041354
return -1;
13051355
}
1306-
if (nargs > 1) {
1307-
PyErr_SetString(PyExc_TypeError, "__init__() takes at most 1 positional argument");
1356+
}
1357+
if (nargs >= 2) {
1358+
seed = PyLong_AsUnsignedLongLongMask(PyTuple_GET_ITEM(args, 1));
1359+
if (PyErr_Occurred()) return -1;
1360+
if (kwargs && PyDict_GetItemString(kwargs, "seed")) {
1361+
PyErr_SetString(PyExc_TypeError,
1362+
"__init__() got multiple values for argument 'seed'");
13081363
return -1;
13091364
}
13101365
}
1366+
if (nargs > 2) {
1367+
PyErr_SetString(PyExc_TypeError,
1368+
"__init__() takes at most 2 positional arguments");
1369+
return -1;
1370+
}
1371+
1372+
/* keyword args */
13111373
if (kwargs) {
1312-
PyObject *val = PyDict_GetItemString(kwargs, "seed");
1374+
PyObject *val = PyDict_GetItemString(kwargs, "data");
1375+
if (val) {
1376+
if (data_obj) {
1377+
PyErr_SetString(PyExc_TypeError,
1378+
"__init__() got multiple values for argument 'data'");
1379+
return -1;
1380+
}
1381+
data_obj = val;
1382+
}
1383+
val = PyDict_GetItemString(kwargs, "seed");
13131384
if (val) {
13141385
seed = PyLong_AsUnsignedLongLongMask(val);
13151386
if (PyErr_Occurred()) return -1;
13161387
}
13171388
}
1389+
13181390
if (data_obj) {
13191391
if (_get_buffer_or_str(data_obj, &buf) < 0)
13201392
return -1;
@@ -1690,24 +1762,48 @@ static int PYXXH3_128_init(PYXXH3_128Object *self, PyObject *args, PyObject *kwa
16901762
Py_buffer buf = {NULL, NULL};
16911763
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
16921764

1765+
/* positional args: data, then optional seed */
16931766
if (nargs >= 1) {
16941767
data_obj = PyTuple_GET_ITEM(args, 0);
16951768
if (kwargs && PyDict_GetItemString(kwargs, "data")) {
1696-
PyErr_SetString(PyExc_TypeError, "__init__() got multiple values for argument 'data'");
1769+
PyErr_SetString(PyExc_TypeError,
1770+
"__init__() got multiple values for argument 'data'");
16971771
return -1;
16981772
}
1699-
if (nargs > 1) {
1700-
PyErr_SetString(PyExc_TypeError, "__init__() takes at most 1 positional argument");
1773+
}
1774+
if (nargs >= 2) {
1775+
seed = PyLong_AsUnsignedLongLongMask(PyTuple_GET_ITEM(args, 1));
1776+
if (PyErr_Occurred()) return -1;
1777+
if (kwargs && PyDict_GetItemString(kwargs, "seed")) {
1778+
PyErr_SetString(PyExc_TypeError,
1779+
"__init__() got multiple values for argument 'seed'");
17011780
return -1;
17021781
}
17031782
}
1783+
if (nargs > 2) {
1784+
PyErr_SetString(PyExc_TypeError,
1785+
"__init__() takes at most 2 positional arguments");
1786+
return -1;
1787+
}
1788+
1789+
/* keyword args */
17041790
if (kwargs) {
1705-
PyObject *val = PyDict_GetItemString(kwargs, "seed");
1791+
PyObject *val = PyDict_GetItemString(kwargs, "data");
1792+
if (val) {
1793+
if (data_obj) {
1794+
PyErr_SetString(PyExc_TypeError,
1795+
"__init__() got multiple values for argument 'data'");
1796+
return -1;
1797+
}
1798+
data_obj = val;
1799+
}
1800+
val = PyDict_GetItemString(kwargs, "seed");
17061801
if (val) {
17071802
seed = PyLong_AsUnsignedLongLongMask(val);
17081803
if (PyErr_Occurred()) return -1;
17091804
}
17101805
}
1806+
17111807
if (data_obj) {
17121808
if (_get_buffer_or_str(data_obj, &buf) < 0)
17131809
return -1;

0 commit comments

Comments
 (0)