diff --git a/fmt.c b/fmt.c index ea5deee9..92906292 100644 --- a/fmt.c +++ b/fmt.c @@ -5,23 +5,18 @@ #if !defined(PYPY_VERSION) && !defined(GRAALVM_PYTHON) static void -unknown_presentation_type(Py_UCS4 presentation_type, - const char* type_name) +unknown_presentation_type(Py_UCS4 presentation_type, PyObject* type_name) { /* %c might be out-of-range, hence the two cases. */ if (presentation_type > 32 && presentation_type < 128) { PyErr_Format(PyExc_ValueError, - "Unknown format code '%c' " - "for object of type '%.200s'", - (char)presentation_type, - type_name); + "Unknown format code '%c' for object of type '%U'", + (char)presentation_type, type_name); } else { PyErr_Format(PyExc_ValueError, - "Unknown format code '\\x%x' " - "for object of type '%.200s'", - (unsigned int)presentation_type, - type_name); + "Unknown format code '\\x%x' for object of type '%U'", + (unsigned int)presentation_type, type_name); } } @@ -301,7 +296,7 @@ parse_internal_render_format_spec(PyObject *obj, PyErr_Format(PyExc_ValueError, ("Invalid format specifier '%U' for object " "of type '%.200s'"), actual_format_spec, - Py_TYPE(obj)->tp_name); + PyType_GetName(Py_TYPE(obj))); Py_DECREF(actual_format_spec); } return 0; @@ -492,6 +487,7 @@ _PyUnicode_InsertThousandsGrouping(_PyUnicodeWriter *writer, assert(0 <= d_pos); assert(0 <= n_digits); assert(grouping != NULL); + assert(PyUnicode_Check(thousands_sep)); Py_ssize_t count = 0; Py_ssize_t n_zeros; @@ -509,7 +505,7 @@ _PyUnicode_InsertThousandsGrouping(_PyUnicodeWriter *writer, returns 0. */ GroupGenerator groupgen; GroupGenerator_init(&groupgen, grouping); - const Py_ssize_t thousands_sep_len = PyUnicode_GET_LENGTH(thousands_sep); + const Py_ssize_t thousands_sep_len = PyUnicode_GetLength(thousands_sep); /* if digits are not grouped, thousands separator should be an empty string */ @@ -518,8 +514,8 @@ _PyUnicode_InsertThousandsGrouping(_PyUnicodeWriter *writer, digits_pos = d_pos + n_digits; if (writer) { buffer_pos = writer->pos + n_buffer; - assert(buffer_pos <= PyUnicode_GET_LENGTH(writer->buffer)); - assert(digits_pos <= PyUnicode_GET_LENGTH(digits)); + assert(buffer_pos <= PyUnicode_GetLength(writer->buffer)); + assert(digits_pos <= PyUnicode_GetLength(digits)); } else { buffer_pos = n_buffer; @@ -586,7 +582,7 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix, spec->n_digits = n_end - n_start - n_frac - n_remainder - (has_decimal?1:0); spec->n_lpadding = 0; spec->n_prefix = n_prefix; - spec->n_decimal = has_decimal ? PyUnicode_GET_LENGTH(locale->decimal_point) : 0; + spec->n_decimal = has_decimal ? PyUnicode_GetLength(locale->decimal_point) : 0; spec->n_remainder = n_remainder; spec->n_frac = n_frac; spec->n_spadding = 0; @@ -1032,6 +1028,7 @@ format_long_internal(MPZ_Object *value, const InternalFormatSpec *format) } /* Do the hard part, converting to a string in a given base */ tmp = MPZ_to_str(value, base, OPT_PREFIX); + assert(PyUnicode_Check(tmp)); if (tmp == NULL) { goto done; /* LCOV_EXCL_LINE */ } @@ -1041,11 +1038,11 @@ format_long_internal(MPZ_Object *value, const InternalFormatSpec *format) n_prefix = leading_chars_to_skip; } inumeric_chars = 0; - n_digits = PyUnicode_GET_LENGTH(tmp); + n_digits = PyUnicode_GetLength(tmp); prefix = inumeric_chars; /* Is a sign character present in the output? If so, remember it and skip it */ - if (PyUnicode_READ_CHAR(tmp, inumeric_chars) == '-') { + if (PyUnicode_ReadChar(tmp, inumeric_chars) == '-') { sign_char = '-'; ++prefix; ++leading_chars_to_skip; @@ -1098,7 +1095,7 @@ extern PyObject * to_float(PyObject *self); PyObject * __format__(PyObject *self, PyObject *format_spec) { - Py_ssize_t end = PyUnicode_GET_LENGTH(format_spec); + Py_ssize_t end = PyUnicode_GetLength(format_spec); if (!end) { return PyObject_Str(self); @@ -1141,7 +1138,7 @@ __format__(PyObject *self, PyObject *format_spec) return res; } default: - unknown_presentation_type(format.type, Py_TYPE(self)->tp_name); + unknown_presentation_type(format.type, PyType_GetName(Py_TYPE(self))); return NULL; } } diff --git a/gmp.c b/gmp.c index dec32c6f..d93dd137 100644 --- a/gmp.c +++ b/gmp.c @@ -25,6 +25,7 @@ _Thread_local gmp_global global = { }; uint8_t bits_per_digit; +Py_hash_t pyhash_modulus; static MPZ_Object * MPZ_new(void) @@ -418,7 +419,7 @@ MPZ_to_bytes(MPZ_Object *u, Py_ssize_t length, int is_little, int is_signed) return NULL; /* LCOV_EXCL_LINE */ } - unsigned char *buffer = (unsigned char *)PyBytes_AS_STRING(bytes); + unsigned char *buffer = (unsigned char *)PyBytes_AsString(bytes); zz_err ret = zz_get_bytes(&u->z, (size_t)length, is_signed, &buffer); if (ret == ZZ_OK) { @@ -516,7 +517,7 @@ MPZ_from_bytes(PyObject *obj, int is_little, int is_signed) if (is_little) { free(buffer); } - Py_XDECREF(res); + Py_XDECREF((PyObject *)res); return (MPZ_Object *)PyErr_NoMemory(); /* LCOV_EXCL_STOP */ } @@ -526,6 +527,8 @@ MPZ_from_bytes(PyObject *obj, int is_little, int is_signed) return res; } +typedef PyObject * (*Py_nb_int_func)(PyObject *); + static PyObject * new_impl(PyTypeObject *Py_UNUSED(type), PyObject *arg, PyObject *base_arg) { @@ -540,29 +543,37 @@ new_impl(PyTypeObject *Py_UNUSED(type), PyObject *arg, PyObject *base_arg) } if (PyNumber_Check(arg)) { PyObject *integer = NULL; +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpedantic" +#endif + Py_nb_int_func nb_int = PyType_GetSlot(Py_TYPE(arg), Py_nb_int); +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif - if (Py_TYPE(arg)->tp_as_number->nb_int) { - integer = Py_TYPE(arg)->tp_as_number->nb_int(arg); + if (nb_int) { + integer = nb_int(arg); if (!integer) { return NULL; } if (!PyLong_Check(integer)) { PyErr_Format(PyExc_TypeError, - "__int__ returned non-int (type %.200s)", - Py_TYPE(integer)->tp_name); - Py_DECREF(integer); + "__int__ returned non-int (type %U)", + PyType_GetName(Py_TYPE(integer))); + Py_XDECREF(integer); return NULL; } if (!PyLong_CheckExact(integer) && PyErr_WarnFormat(PyExc_DeprecationWarning, 1, - "__int__ returned non-int (type %.200s). " + "__int__ returned non-int (type %U). " "The ability to return an instance of a " "strict subclass of int " "is deprecated, and may be removed " "in a future version of Python.", - Py_TYPE(integer)->tp_name)) + PyType_GetName(Py_TYPE(integer)))) { - Py_DECREF(integer); + Py_XDECREF(integer); return NULL; } } @@ -573,8 +584,10 @@ new_impl(PyTypeObject *Py_UNUSED(type), PyObject *arg, PyObject *base_arg) } } if (integer) { - Py_SETREF(integer, (PyObject *)MPZ_from_int(integer)); - return integer; + PyObject *mpz = (PyObject *)MPZ_from_int(integer); + + Py_DECREF(integer); + return (PyObject *)mpz; } } goto str; @@ -602,10 +615,10 @@ new_impl(PyTypeObject *Py_UNUSED(type), PyObject *arg, PyObject *base_arg) const char *string; if (PyByteArray_Check(arg)) { - string = PyByteArray_AS_STRING(arg); + string = PyByteArray_AsString(arg); } else { - string = PyBytes_AS_STRING(arg); + string = PyBytes_AsString(arg); } PyObject *str = PyUnicode_FromString(string); @@ -634,7 +647,7 @@ static PyObject * new(PyTypeObject *type, PyObject *args, PyObject *keywds) { static char *kwlist[] = {"", "base", NULL}; - Py_ssize_t argc = PyTuple_GET_SIZE(args); + Py_ssize_t argc = PyTuple_Size(args); PyObject *arg, *base = Py_None; if (type != &MPZ_Type) { @@ -644,7 +657,7 @@ new(PyTypeObject *type, PyObject *args, PyObject *keywds) return NULL; /* LCOV_EXCL_LINE */ } - MPZ_Object *newobj = (MPZ_Object *)type->tp_alloc(type, 0); + MPZ_Object *newobj = (MPZ_Object *)PyType_GenericNew(type, NULL, NULL); if (!newobj) { /* LCOV_EXCL_START */ @@ -665,7 +678,7 @@ new(PyTypeObject *type, PyObject *args, PyObject *keywds) return (PyObject *)MPZ_new(); } if (argc == 1 && !keywds) { - arg = PyTuple_GET_ITEM(args, 0); + arg = PyTuple_GetItem(args, 0); return new_impl(type, arg, Py_None); } if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|O", @@ -676,11 +689,12 @@ new(PyTypeObject *type, PyObject *args, PyObject *keywds) return new_impl(type, arg, base); } +typedef void (*Py_tp_free_func)(void *); + static void dealloc(PyObject *self) { MPZ_Object *u = (MPZ_Object *)self; - PyTypeObject *type = Py_TYPE(self); if (global.gmp_cache_size < CACHE_SIZE && (u->z).alloc <= MAX_CACHE_MPZ_DIGITS @@ -690,7 +704,21 @@ dealloc(PyObject *self) } else { zz_clear(&u->z); - type->tp_free(self); + if (MPZ_CheckExact(self)) { + PyObject_Free(self); + } + else { +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpedantic" +#endif + Py_tp_free_func tp_free = PyType_GetSlot(Py_TYPE(self), Py_tp_free); +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif + + tp_free(self); + } } } @@ -741,7 +769,7 @@ str(PyObject *self) #define CHECK_OP(u, a) \ if (MPZ_Check(a)) { \ u = (MPZ_Object *)a; \ - Py_INCREF(u); \ + Py_INCREF(a); \ } \ else if (PyLong_Check(a)) { \ u = MPZ_from_int(a); \ @@ -862,13 +890,13 @@ hash(PyObject *self) zz_digit_t digits[1]; zz_t w = {false, 1, 1, digits}; - assert((int64_t)INT64_MAX > PyHASH_MODULUS); - (void)zz_div(&u->z, (int64_t)PyHASH_MODULUS, NULL, &w); + assert((int64_t)INT64_MAX > pyhash_modulus); + (void)zz_div(&u->z, (int64_t)pyhash_modulus, NULL, &w); Py_hash_t r = w.size ? (Py_hash_t)w.digits[0] : 0; if (zz_isneg(&u->z) && r) { - r = -((Py_hash_t)PyHASH_MODULUS - r); + r = -(pyhash_modulus - r); } if (r == -1) { r = -2; @@ -909,7 +937,7 @@ to_bool(PyObject *self) #define CHECK_OPv2(u, a) \ if (MPZ_Check(a)) { \ u = (MPZ_Object *)a; \ - Py_INCREF(u); \ + Py_INCREF(a); \ } \ else if (PyLong_Check(a)) { \ ; \ @@ -978,16 +1006,16 @@ done: \ PyErr_NoMemory(); \ } \ end: \ - Py_XDECREF(u); \ - Py_XDECREF(v); \ + Py_XDECREF((PyObject *)u); \ + Py_XDECREF((PyObject *)v); \ return (PyObject *)res; \ fallback: \ - Py_XDECREF(u); \ - Py_XDECREF(v); \ + Py_XDECREF((PyObject *)u); \ + Py_XDECREF((PyObject *)v); \ Py_RETURN_NOTIMPLEMENTED; \ numbers: \ - Py_XDECREF(u); \ - Py_XDECREF(v); \ + Py_XDECREF((PyObject *)u); \ + Py_XDECREF((PyObject *)v); \ \ PyObject *uf, *vf, *rf; \ \ @@ -1045,8 +1073,8 @@ nb_divmod(PyObject *self, PyObject *other) if (!q || !r) { /* LCOV_EXCL_START */ - Py_XDECREF(q); - Py_XDECREF(r); + Py_XDECREF((PyObject *)q); + Py_XDECREF((PyObject *)r); return NULL; /* LCOV_EXCL_STOP */ } @@ -1066,21 +1094,21 @@ nb_divmod(PyObject *self, PyObject *other) } Py_DECREF(u); Py_DECREF(v); - PyTuple_SET_ITEM(res, 0, (PyObject *)q); - PyTuple_SET_ITEM(res, 1, (PyObject *)r); + (void)PyTuple_SetItem(res, 0, (PyObject *)q); + (void)PyTuple_SetItem(res, 1, (PyObject *)r); return res; /* LCOV_EXCL_START */ end: Py_DECREF(res); - Py_XDECREF(u); - Py_XDECREF(v); + Py_XDECREF((PyObject *)u); + Py_XDECREF((PyObject *)v); return NULL; /* LCOV_EXCL_STOP */ fallback: numbers: Py_DECREF(res); - Py_XDECREF(u); - Py_XDECREF(v); + Py_XDECREF((PyObject *)u); + Py_XDECREF((PyObject *)v); Py_RETURN_NOTIMPLEMENTED; } @@ -1278,16 +1306,16 @@ nb_truediv(PyObject *self, PyObject *other) PyErr_NoMemory(); /* LCOV_EXCL_LINE */ } end: - Py_XDECREF(u); - Py_XDECREF(v); + Py_XDECREF((PyObject *)u); + Py_XDECREF((PyObject *)v); return res; fallback: - Py_XDECREF(u); - Py_XDECREF(v); + Py_XDECREF((PyObject *)u); + Py_XDECREF((PyObject *)v); Py_RETURN_NOTIMPLEMENTED; numbers: - Py_XDECREF(u); - Py_XDECREF(v); + Py_XDECREF((PyObject *)u); + Py_XDECREF((PyObject *)v); PyObject *uf, *vf; @@ -1323,7 +1351,7 @@ nb_truediv(PyObject *self, PyObject *other) #define CHECK_OP_INT(u, a) \ if (MPZ_Check(a)) { \ u = (MPZ_Object *)a; \ - Py_INCREF(u); \ + Py_INCREF(a); \ } \ else { \ u = MPZ_from_int(a); \ @@ -1373,8 +1401,8 @@ nb_truediv(PyObject *self, PyObject *other) /* LCOV_EXCL_STOP */ \ } \ end: \ - Py_XDECREF(u); \ - Py_XDECREF(v); \ + Py_XDECREF((PyObject *)u); \ + Py_XDECREF((PyObject *)v); \ return (PyObject *)res; \ } @@ -1445,8 +1473,8 @@ done: \ /* LCOV_EXCL_STOP */ \ } \ end: \ - Py_XDECREF(u); \ - Py_XDECREF(v); \ + Py_XDECREF((PyObject *)u); \ + Py_XDECREF((PyObject *)v); \ return (PyObject *)res; \ } @@ -1498,6 +1526,8 @@ zz_rshift(const zz_t *u, const zz_t *v, zz_t *w) BINOP_INT(lshift) BINOP_INT(rshift) +typedef PyObject * (*Py_nb_power_func)(PyObject *, PyObject *, PyObject *); + static PyObject * power(PyObject *self, PyObject *other, PyObject *module) { @@ -1522,7 +1552,18 @@ power(PyObject *self, PyObject *other, PyObject *module) Py_DECREF(uf); return NULL; } - resf = PyFloat_Type.tp_as_number->nb_power(uf, vf, Py_None); + +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpedantic" +#endif + Py_nb_power_func nb_power = PyType_GetSlot(&PyFloat_Type, + Py_nb_power); +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif + + resf = nb_power(uf, vf, Py_None); Py_DECREF(uf); Py_DECREF(vf); return resf; @@ -1566,16 +1607,16 @@ power(PyObject *self, PyObject *other, PyObject *module) Py_DECREF(w); } end: - Py_XDECREF(u); - Py_XDECREF(v); + Py_XDECREF((PyObject *)u); + Py_XDECREF((PyObject *)v); return (PyObject *)res; fallback: - Py_XDECREF(u); - Py_XDECREF(v); + Py_XDECREF((PyObject *)u); + Py_XDECREF((PyObject *)v); Py_RETURN_NOTIMPLEMENTED; numbers: - Py_XDECREF(u); - Py_XDECREF(v); + Py_XDECREF((PyObject *)u); + Py_XDECREF((PyObject *)v); PyObject *uf, *vf; @@ -1727,7 +1768,7 @@ to_bytes(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *arg = args[argidx[1]]; if (PyUnicode_Check(arg)) { - const char *byteorder = PyUnicode_AsUTF8(arg); + const char *byteorder = PyUnicode_AsUTF8AndSize(arg, NULL); if (!byteorder) { return NULL; /* LCOV_EXCL_LINE */ @@ -1786,7 +1827,7 @@ from_bytes(PyTypeObject *Py_UNUSED(type), PyObject *const *args, PyObject *arg = args[argidx[1]]; if (PyUnicode_Check(arg)) { - const char *byteorder = PyUnicode_AsUTF8(arg); + const char *byteorder = PyUnicode_AsUTF8AndSize(arg, NULL); if (!byteorder) { return NULL; /* LCOV_EXCL_LINE */ @@ -1978,9 +2019,22 @@ digits(PyObject *self, PyObject *const *args, Py_ssize_t nargs, return MPZ_to_str((MPZ_Object *)self, base, 0); } -PyDoc_STRVAR( - to_bytes__doc__, - "to_bytes($self, /, length=1, byteorder=\'big\', *, signed=False)\n--\n\n\ +extern PyObject * __format__(PyObject *self, PyObject *format_spec); + +/* Explicit signatures for METH_NOARGS methods are redundant + since CPython 3.13. */ + +static PyMethodDef methods[] = { + {"conjugate", (PyCFunction)plus, METH_NOARGS, + "conjugate($self, /)\n--\n\nReturns self."}, + {"bit_length", bit_length, METH_NOARGS, + ("bit_length($self, /)\n--\n\nNumber of bits necessary " + "to represent self in binary.")}, + {"bit_count", bit_count, METH_NOARGS, + ("bit_count($self, /)\n--\n\nNumber of ones in the binary " + "representation of the absolute value of self.")}, + {"to_bytes", (PyCFunction)to_bytes, METH_FASTCALL | METH_KEYWORDS, + "to_bytes($self, /, length=1, byteorder=\'big\', *, signed=False)\n--\n\n\ Return an array of bytes representing self.\n\n\ The integer is represented using length bytes. An OverflowError is\n\ raised if self is not representable with the given number of bytes.\n\n\ @@ -1989,10 +2043,10 @@ Accepted values are \'big\' and \'little\', when the most significant\n\ byte is at the beginning or at the end of the byte array, respectively.\n\n\ The signed argument determines whether two\'s complement is used to\n\ represent self. If signed is False and a negative integer is given,\n\ -an OverflowError is raised."); -PyDoc_STRVAR( - from_bytes__doc__, - "from_bytes($type, /, bytes, byteorder=\'big\', *, signed=False)\n--\n\n\ +an OverflowError is raised."}, + {"from_bytes", (PyCFunction)from_bytes, + METH_FASTCALL | METH_KEYWORDS | METH_CLASS, + "from_bytes($type, /, bytes, byteorder=\'big\', *, signed=False)\n--\n\n\ Return the integer represented by the given array of bytes.\n\n\ The argument bytes must either be a bytes-like object or an iterable\n\ producing bytes.\n\n\ @@ -2000,28 +2054,17 @@ The byteorder argument determines the byte order used to represent the\n\ integer. Accepted values are \'big\' and \'little\', when the most\n\ significant byte is at the beginning or at the end of the byte array,\n\ respectively.\n\n\ -The signed argument indicates whether two’s complement is used."); - -extern PyObject * __format__(PyObject *self, PyObject *format_spec); - -static PyMethodDef methods[] = { - {"conjugate", (PyCFunction)plus, METH_NOARGS, - "Returns self."}, - {"bit_length", bit_length, METH_NOARGS, - "Number of bits necessary to represent self in binary."}, - {"bit_count", bit_count, METH_NOARGS, - ("Number of ones in the binary representation of the " - "absolute value of self.")}, - {"to_bytes", (PyCFunction)to_bytes, METH_FASTCALL | METH_KEYWORDS, - to_bytes__doc__}, - {"from_bytes", (PyCFunction)from_bytes, - METH_FASTCALL | METH_KEYWORDS | METH_CLASS, from_bytes__doc__}, +The signed argument indicates whether two’s complement is used."}, {"as_integer_ratio", as_integer_ratio, METH_NOARGS, - ("Return a pair of integers, whose ratio is equal to self.\n\n" + ("as_integer_ratio($self, /)\n--\n\nReturn a pair of integers, " + "whose ratio is equal to self.\n\n" "The ratio is in lowest terms and has a positive denominator.")}, - {"__trunc__", (PyCFunction)plus, METH_NOARGS, "Returns self."}, - {"__floor__", (PyCFunction)plus, METH_NOARGS, "Returns self."}, - {"__ceil__", (PyCFunction)plus, METH_NOARGS, "Returns self."}, + {"__trunc__", (PyCFunction)plus, METH_NOARGS, + "__trunc__($self, /)\n--\n\nReturns self."}, + {"__floor__", (PyCFunction)plus, METH_NOARGS, + "__floor__($self, /)\n--\n\nReturns self."}, + {"__ceil__", (PyCFunction)plus, METH_NOARGS, + "__ceil__($self, /)\n--\n\nReturns self."}, {"__round__", (PyCFunction)__round__, METH_FASTCALL, ("__round__($self, ndigits=0, /)\n--\n\n" "Round self to to the closest multiple of 10**-ndigits\n\n" @@ -2034,8 +2077,9 @@ static PyMethodDef methods[] = { ("__format__($self, format_spec, /)\n--\n\n" "Convert self to a string according to format_spec.")}, {"__sizeof__", __sizeof__, METH_NOARGS, - "Returns size of self in memory, in bytes."}, - {"is_integer", is_integer, METH_NOARGS, "Returns True."}, + "__sizeof__($self, /)\n--\n\nReturns size of self in memory, in bytes."}, + {"is_integer", is_integer, METH_NOARGS, + "is_integer($self, /)\n--\n\nReturns True."}, {"digits", (PyCFunction)digits, METH_FASTCALL | METH_KEYWORDS, ("digits($self, base=10)\n--\n\n" "Return string representing self in the given base.\n\n" @@ -2116,9 +2160,9 @@ gmp_gcdext(PyObject *Py_UNUSED(module), PyObject *const *args, if (!g || !s || !t) { /* LCOV_EXCL_START */ - Py_XDECREF(g); - Py_XDECREF(s); - Py_XDECREF(t); + Py_XDECREF((PyObject *)g); + Py_XDECREF((PyObject *)s); + Py_XDECREF((PyObject *)t); return PyErr_NoMemory(); /* LCOV_EXCL_STOP */ } @@ -2127,8 +2171,8 @@ gmp_gcdext(PyObject *Py_UNUSED(module), PyObject *const *args, zz_err ret = zz_gcdext(&x->z, &y->z, &g->z, &s->z, &t->z); - Py_XDECREF(x); - Py_XDECREF(y); + Py_XDECREF((PyObject *)x); + Py_XDECREF((PyObject *)y); if (ret == ZZ_MEM) { return PyErr_NoMemory(); /* LCOV_EXCL_LINE */ } @@ -2142,8 +2186,8 @@ gmp_gcdext(PyObject *Py_UNUSED(module), PyObject *const *args, Py_DECREF(g); Py_DECREF(s); Py_DECREF(t); - Py_XDECREF(x); - Py_XDECREF(y); + Py_XDECREF((PyObject *)x); + Py_XDECREF((PyObject *)y); return NULL; } @@ -2214,8 +2258,8 @@ gmp_isqrt_rem(PyObject *Py_UNUSED(module), PyObject *arg) if (!root || !rem) { /* LCOV_EXCL_START */ - Py_XDECREF(root); - Py_XDECREF(rem); + Py_XDECREF((PyObject *)root); + Py_XDECREF((PyObject *)rem); return NULL; /* LCOV_EXCL_STOP */ } @@ -2263,7 +2307,7 @@ gmp_fac(PyObject *Py_UNUSED(module), PyObject *arg) LONG_MAX); goto err; } - Py_XDECREF(x); + Py_XDECREF((PyObject *)x); if (zz_fac((zz_digit_t)n, &res->z)) { /* LCOV_EXCL_START */ PyErr_NoMemory(); @@ -2308,8 +2352,8 @@ gmp_comb(PyObject *self, PyObject *const *args, Py_ssize_t nargs) ULONG_MAX); goto err; } - Py_XDECREF(x); - Py_XDECREF(y); + Py_XDECREF((PyObject *)x); + Py_XDECREF((PyObject *)y); if (zz_bin((zz_digit_t)n, (zz_digit_t)k, &res->z)) { /* LCOV_EXCL_START */ PyErr_NoMemory(); @@ -2357,8 +2401,8 @@ gmp_perm(PyObject *self, PyObject *const *args, Py_ssize_t nargs) ULONG_MAX); goto err; } - Py_XDECREF(x); - Py_XDECREF(y); + Py_XDECREF((PyObject *)x); + Py_XDECREF((PyObject *)y); if (k > n) { return (PyObject *)res; } @@ -2406,9 +2450,10 @@ get_round_mode(PyObject *rndstr) return (zz_rnd)-1; } - Py_UCS4 rndchr = PyUnicode_READ_CHAR(rndstr, 0); + Py_UCS4 rndchr = PyUnicode_ReadChar(rndstr, 0); zz_rnd rnd = ZZ_RNDN; + assert(rndchr != -1); switch (rndchr) { case (Py_UCS4)'f': rnd = ZZ_RNDD; @@ -2559,8 +2604,8 @@ gmp__mpmath_normalize(PyObject *self, PyObject *const *args, Py_ssize_t nargs) &man->z, &exp->z, &bc)) { /* LCOV_EXCL_START */ - Py_XDECREF(man); - Py_XDECREF(exp); + Py_XDECREF((PyObject *)man); + Py_XDECREF((PyObject *)exp); return PyErr_NoMemory(); /* LCOV_EXCL_STOP */ } @@ -2643,7 +2688,7 @@ gmp__mpmath_create(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { /* LCOV_EXCL_START */ Py_DECREF(man); - Py_XDECREF(exp); + Py_XDECREF((PyObject *)exp); return PyErr_NoMemory(); /* LCOV_EXCL_STOP */ } @@ -2666,10 +2711,9 @@ gmp__free_cache(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) for (size_t i = 0; i < global.gmp_cache_size; i++) { MPZ_Object *u = global.gmp_cache[i]; PyObject *self = (PyObject *)u; - PyTypeObject *type = Py_TYPE(self); zz_clear(&u->z); - type->tp_free(self); + PyObject_Free(self); } global.gmp_cache_size = 0; Py_RETURN_NONE; @@ -2746,12 +2790,10 @@ gmp_exec(PyObject *m) if (mpz_info == NULL) { return -1; /* LCOV_EXCL_LINE */ } - PyStructSequence_SET_ITEM(mpz_info, 0, - PyLong_FromLong(bits_per_digit)); - PyStructSequence_SET_ITEM(mpz_info, 1, - PyLong_FromLong(layout->digit_size)); - PyStructSequence_SET_ITEM(mpz_info, 2, - PyLong_FromUInt64(zz_get_bitcnt_max())); + PyStructSequence_SetItem(mpz_info, 0, PyLong_FromLong(bits_per_digit)); + PyStructSequence_SetItem(mpz_info, 1, PyLong_FromLong(layout->digit_size)); + PyStructSequence_SetItem(mpz_info, 2, + PyLong_FromUInt64(zz_get_bitcnt_max())); if (PyErr_Occurred()) { /* LCOV_EXCL_START */ fail1: @@ -2785,13 +2827,44 @@ gmp_exec(PyObject *m) "gmp.__all__ = ['comb', 'factorial', 'gcd', 'isqrt',\n" " 'lcm', 'mpz', 'perm']\n" "gmp.__version__ = imp.version('python-gmp')\n"); - PyObject *res = PyRun_String(str, Py_file_input, ns, ns); + PyObject *codeobj = Py_CompileString(str, "", Py_file_input); + PyObject *res; - Py_DECREF(ns); + if (!codeobj) { + goto fail1; /* LCOV_EXCL_LINE */ + } + res = PyEval_EvalCode(codeobj, ns, NULL); + Py_DECREF(codeobj); if (!res) { goto fail1; /* LCOV_EXCL_LINE */ } Py_DECREF(res); + + PyObject *sys_mod = PyImport_ImportModuleLevel("sys", NULL, NULL, NULL, 0); + + if (!sys_mod || PyDict_SetItemString(ns, "sys", sys_mod) < 0) { + /* LCOV_EXCL_START */ + Py_DECREF(ns); + goto fail1; + /* LCOV_EXCL_STOP */ + } + codeobj = Py_CompileString("sys.hash_info.modulus", "", + Py_eval_input); + if (!codeobj || !(res = PyEval_EvalCode(codeobj, ns, NULL))) { + /* LCOV_EXCL_START */ + Py_XDECREF(codeobj); + Py_DECREF(ns); + goto fail1; + /* LCOV_EXCL_STOP */ + } + Py_DECREF(codeobj); + Py_DECREF(sys_mod); + Py_DECREF(ns); + pyhash_modulus = (Py_hash_t)PyLong_AsSsize_t(res); + Py_DECREF(res); + if (pyhash_modulus == -1) { + goto fail1; /* LCOV_EXCL_LINE */ + } return 0; } diff --git a/pyproject.toml b/pyproject.toml index 42706960..a17002a0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,7 +36,7 @@ classifiers = ["Development Status :: 4 - Beta", "Operating System :: MacOS", "Topic :: Scientific/Engineering :: Mathematics", "Topic :: Software Development :: Libraries :: Python Modules"] -requires-python = ">= 3.9" +requires-python = ">= 3.11" [project.urls] Homepage = "https://github.com/diofant/python-gmp" diff --git a/pythoncapi_compat.h b/pythoncapi_compat.h index 3320f68e..cdfdafa8 100644 --- a/pythoncapi_compat.h +++ b/pythoncapi_compat.h @@ -25,9 +25,6 @@ extern "C" { #if PY_VERSION_HEX < 0x030b00B4 && !defined(PYPY_VERSION) # include "frameobject.h" // PyFrameObject, PyFrame_GetBack() #endif -#if PY_VERSION_HEX < 0x030C00A3 -# include // T_SHORT, READONLY -#endif #ifndef _Py_CAST @@ -1919,33 +1916,33 @@ PyLongWriter_Finish(PyLongWriter *writer) #if PY_VERSION_HEX < 0x030C00A3 -# define Py_T_SHORT T_SHORT -# define Py_T_INT T_INT -# define Py_T_LONG T_LONG -# define Py_T_FLOAT T_FLOAT -# define Py_T_DOUBLE T_DOUBLE -# define Py_T_STRING T_STRING -# define _Py_T_OBJECT T_OBJECT -# define Py_T_CHAR T_CHAR -# define Py_T_BYTE T_BYTE -# define Py_T_UBYTE T_UBYTE -# define Py_T_USHORT T_USHORT -# define Py_T_UINT T_UINT -# define Py_T_ULONG T_ULONG -# define Py_T_STRING_INPLACE T_STRING_INPLACE -# define Py_T_BOOL T_BOOL -# define Py_T_OBJECT_EX T_OBJECT_EX -# define Py_T_LONGLONG T_LONGLONG -# define Py_T_ULONGLONG T_ULONGLONG -# define Py_T_PYSSIZET T_PYSSIZET +# define Py_T_SHORT 0 +# define Py_T_INT 1 +# define Py_T_LONG 2 +# define Py_T_FLOAT 3 +# define Py_T_DOUBLE 4 +# define Py_T_STRING 5 +# define _Py_T_OBJECT 6 +# define Py_T_CHAR 7 +# define Py_T_BYTE 8 +# define Py_T_UBYTE 9 +# define Py_T_USHORT 10 +# define Py_T_UINT 11 +# define Py_T_ULONG 12 +# define Py_T_STRING_INPLACE 13 +# define Py_T_BOOL 14 +# define Py_T_OBJECT_EX 16 +# define Py_T_LONGLONG 17 +# define Py_T_ULONGLONG 18 +# define Py_T_PYSSIZET 19 # if PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION) -# define _Py_T_NONE T_NONE +# define _Py_T_NONE 20 # endif -# define Py_READONLY READONLY -# define Py_AUDIT_READ READ_RESTRICTED -# define _Py_WRITE_RESTRICTED PY_WRITE_RESTRICTED +# define Py_READONLY 1 +# define Py_AUDIT_READ 2 +# define _Py_WRITE_RESTRICTED 4 #endif @@ -1991,7 +1988,9 @@ static inline int Py_fclose(FILE *file) #endif -#if 0x03090000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030E0000 && !defined(PYPY_VERSION) +#if 0x03080000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030E0000 && !defined(PYPY_VERSION) +PyAPI_FUNC(const PyConfig*) _Py_GetConfig(void); + static inline PyObject* PyConfig_Get(const char *name) { @@ -2032,7 +2031,9 @@ PyConfig_Get(const char *name) PYTHONCAPI_COMPAT_SPEC(module_search_paths, WSTR_LIST, "path"), PYTHONCAPI_COMPAT_SPEC(optimization_level, UINT, _Py_NULL), PYTHONCAPI_COMPAT_SPEC(parser_debug, BOOL, _Py_NULL), +#if 0x03090000 <= PY_VERSION_HEX PYTHONCAPI_COMPAT_SPEC(platlibdir, WSTR, "platlibdir"), +#endif PYTHONCAPI_COMPAT_SPEC(prefix, WSTR_OPT, "prefix"), PYTHONCAPI_COMPAT_SPEC(pycache_prefix, WSTR_OPT, "pycache_prefix"), PYTHONCAPI_COMPAT_SPEC(quiet, BOOL, _Py_NULL), @@ -2125,8 +2126,6 @@ PyConfig_Get(const char *name) return Py_NewRef(value); } - PyAPI_FUNC(const PyConfig*) _Py_GetConfig(void); - const PyConfig *config = _Py_GetConfig(); void *member = (char *)config + spec->offset; switch (spec->type) { @@ -2211,6 +2210,99 @@ PyConfig_GetInt(const char *name, int *value) } #endif // PY_VERSION_HEX > 0x03090000 && !defined(PYPY_VERSION) +// gh-133144 added PyUnstable_Object_IsUniquelyReferenced() to Python 3.14.0b1. +// Adapted from _PyObject_IsUniquelyReferenced() implementation. +#if PY_VERSION_HEX < 0x030E00B0 +static inline int PyUnstable_Object_IsUniquelyReferenced(PyObject *obj) +{ +#if !defined(Py_GIL_DISABLED) + return Py_REFCNT(obj) == 1; +#else + // NOTE: the entire ob_ref_shared field must be zero, including flags, to + // ensure that other threads cannot concurrently create new references to + // this object. + return (_Py_IsOwnedByCurrentThread(obj) && + _Py_atomic_load_uint32_relaxed(&obj->ob_ref_local) == 1 && + _Py_atomic_load_ssize_relaxed(&obj->ob_ref_shared) == 0); +#endif +} +#endif + +// gh-128926 added PyUnstable_TryIncRef() and PyUnstable_EnableTryIncRef() to +// Python 3.14.0a5. Adapted from _Py_TryIncref() and _PyObject_SetMaybeWeakref(). +#if PY_VERSION_HEX < 0x030E00A5 +static inline int PyUnstable_TryIncRef(PyObject *op) +{ +#ifndef Py_GIL_DISABLED + if (Py_REFCNT(op) > 0) { + Py_INCREF(op); + return 1; + } + return 0; +#else + // _Py_TryIncrefFast() + uint32_t local = _Py_atomic_load_uint32_relaxed(&op->ob_ref_local); + local += 1; + if (local == 0) { + // immortal + return 1; + } + if (_Py_IsOwnedByCurrentThread(op)) { + _Py_INCREF_STAT_INC(); + _Py_atomic_store_uint32_relaxed(&op->ob_ref_local, local); +#ifdef Py_REF_DEBUG + _Py_INCREF_IncRefTotal(); +#endif + return 1; + } + + // _Py_TryIncRefShared() + Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&op->ob_ref_shared); + for (;;) { + // If the shared refcount is zero and the object is either merged + // or may not have weak references, then we cannot incref it. + if (shared == 0 || shared == _Py_REF_MERGED) { + return 0; + } + + if (_Py_atomic_compare_exchange_ssize( + &op->ob_ref_shared, + &shared, + shared + (1 << _Py_REF_SHARED_SHIFT))) { +#ifdef Py_REF_DEBUG + _Py_INCREF_IncRefTotal(); +#endif + _Py_INCREF_STAT_INC(); + return 1; + } + } +#endif +} + +static inline void PyUnstable_EnableTryIncRef(PyObject *op) +{ +#ifdef Py_GIL_DISABLED + // _PyObject_SetMaybeWeakref() + if (_Py_IsImmortal(op)) { + return; + } + for (;;) { + Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&op->ob_ref_shared); + if ((shared & _Py_REF_SHARED_FLAG_MASK) != 0) { + // Nothing to do if it's in WEAKREFS, QUEUED, or MERGED states. + return; + } + if (_Py_atomic_compare_exchange_ssize( + &op->ob_ref_shared, &shared, shared | _Py_REF_MAYBE_WEAKREF)) { + return; + } + } +#else + (void)op; // unused argument +#endif +} +#endif + #if PY_VERSION_HEX < 0x030F0000 static inline PyObject* @@ -2277,6 +2369,297 @@ PySys_GetOptionalAttr(PyObject *name, PyObject **value) #endif // PY_VERSION_HEX < 0x030F00A1 +#if PY_VERSION_HEX < 0x030F00A1 +typedef struct PyBytesWriter { + char small_buffer[256]; + PyObject *obj; + Py_ssize_t size; +} PyBytesWriter; + +static inline Py_ssize_t +_PyBytesWriter_GetAllocated(PyBytesWriter *writer) +{ + if (writer->obj == NULL) { + return sizeof(writer->small_buffer); + } + else { + return PyBytes_GET_SIZE(writer->obj); + } +} + + +static inline int +_PyBytesWriter_Resize_impl(PyBytesWriter *writer, Py_ssize_t size, + int resize) +{ + int overallocate = resize; + assert(size >= 0); + + if (size <= _PyBytesWriter_GetAllocated(writer)) { + return 0; + } + + if (overallocate) { +#ifdef MS_WINDOWS + /* On Windows, overallocate by 50% is the best factor */ + if (size <= (PY_SSIZE_T_MAX - size / 2)) { + size += size / 2; + } +#else + /* On Linux, overallocate by 25% is the best factor */ + if (size <= (PY_SSIZE_T_MAX - size / 4)) { + size += size / 4; + } +#endif + } + + if (writer->obj != NULL) { + if (_PyBytes_Resize(&writer->obj, size)) { + return -1; + } + assert(writer->obj != NULL); + } + else { + writer->obj = PyBytes_FromStringAndSize(NULL, size); + if (writer->obj == NULL) { + return -1; + } + + if (resize) { + assert((size_t)size > sizeof(writer->small_buffer)); + memcpy(PyBytes_AS_STRING(writer->obj), + writer->small_buffer, + sizeof(writer->small_buffer)); + } + } + return 0; +} + +static inline void* +PyBytesWriter_GetData(PyBytesWriter *writer) +{ + if (writer->obj == NULL) { + return writer->small_buffer; + } + else { + return PyBytes_AS_STRING(writer->obj); + } +} + +static inline Py_ssize_t +PyBytesWriter_GetSize(PyBytesWriter *writer) +{ + return writer->size; +} + +static inline void +PyBytesWriter_Discard(PyBytesWriter *writer) +{ + if (writer == NULL) { + return; + } + + Py_XDECREF(writer->obj); + PyMem_Free(writer); +} + +static inline PyBytesWriter* +PyBytesWriter_Create(Py_ssize_t size) +{ + if (size < 0) { + PyErr_SetString(PyExc_ValueError, "size must be >= 0"); + return NULL; + } + + PyBytesWriter *writer = (PyBytesWriter*)PyMem_Malloc(sizeof(PyBytesWriter)); + if (writer == NULL) { + PyErr_NoMemory(); + return NULL; + } + + writer->obj = NULL; + writer->size = 0; + + if (size >= 1) { + if (_PyBytesWriter_Resize_impl(writer, size, 0) < 0) { + PyBytesWriter_Discard(writer); + return NULL; + } + writer->size = size; + } + return writer; +} + +static inline PyObject* +PyBytesWriter_FinishWithSize(PyBytesWriter *writer, Py_ssize_t size) +{ + PyObject *result; + if (size == 0) { + result = PyBytes_FromStringAndSize("", 0); + } + else if (writer->obj != NULL) { + if (size != PyBytes_GET_SIZE(writer->obj)) { + if (_PyBytes_Resize(&writer->obj, size)) { + goto error; + } + } + result = writer->obj; + writer->obj = NULL; + } + else { + result = PyBytes_FromStringAndSize(writer->small_buffer, size); + } + PyBytesWriter_Discard(writer); + return result; + +error: + PyBytesWriter_Discard(writer); + return NULL; +} + +static inline PyObject* +PyBytesWriter_Finish(PyBytesWriter *writer) +{ + return PyBytesWriter_FinishWithSize(writer, writer->size); +} + +static inline PyObject* +PyBytesWriter_FinishWithPointer(PyBytesWriter *writer, void *buf) +{ + Py_ssize_t size = (char*)buf - (char*)PyBytesWriter_GetData(writer); + if (size < 0 || size > _PyBytesWriter_GetAllocated(writer)) { + PyBytesWriter_Discard(writer); + PyErr_SetString(PyExc_ValueError, "invalid end pointer"); + return NULL; + } + + return PyBytesWriter_FinishWithSize(writer, size); +} + +static inline int +PyBytesWriter_Resize(PyBytesWriter *writer, Py_ssize_t size) +{ + if (size < 0) { + PyErr_SetString(PyExc_ValueError, "size must be >= 0"); + return -1; + } + if (_PyBytesWriter_Resize_impl(writer, size, 1) < 0) { + return -1; + } + writer->size = size; + return 0; +} + +static inline int +PyBytesWriter_Grow(PyBytesWriter *writer, Py_ssize_t size) +{ + if (size < 0 && writer->size + size < 0) { + PyErr_SetString(PyExc_ValueError, "invalid size"); + return -1; + } + if (size > PY_SSIZE_T_MAX - writer->size) { + PyErr_NoMemory(); + return -1; + } + size = writer->size + size; + + if (_PyBytesWriter_Resize_impl(writer, size, 1) < 0) { + return -1; + } + writer->size = size; + return 0; +} + +static inline void* +PyBytesWriter_GrowAndUpdatePointer(PyBytesWriter *writer, + Py_ssize_t size, void *buf) +{ + Py_ssize_t pos = (char*)buf - (char*)PyBytesWriter_GetData(writer); + if (PyBytesWriter_Grow(writer, size) < 0) { + return NULL; + } + return (char*)PyBytesWriter_GetData(writer) + pos; +} + +static inline int +PyBytesWriter_WriteBytes(PyBytesWriter *writer, + const void *bytes, Py_ssize_t size) +{ + if (size < 0) { + size_t len = strlen((const char*)bytes); + if (len > (size_t)PY_SSIZE_T_MAX) { + PyErr_NoMemory(); + return -1; + } + size = (Py_ssize_t)len; + } + + Py_ssize_t pos = writer->size; + if (PyBytesWriter_Grow(writer, size) < 0) { + return -1; + } + char *buf = (char*)PyBytesWriter_GetData(writer); + memcpy(buf + pos, bytes, (size_t)size); + return 0; +} + +static inline int +PyBytesWriter_Format(PyBytesWriter *writer, const char *format, ...) + Py_GCC_ATTRIBUTE((format(printf, 2, 3))); + +static inline int +PyBytesWriter_Format(PyBytesWriter *writer, const char *format, ...) +{ + va_list vargs; + va_start(vargs, format); + PyObject *str = PyBytes_FromFormatV(format, vargs); + va_end(vargs); + + if (str == NULL) { + return -1; + } + int res = PyBytesWriter_WriteBytes(writer, + PyBytes_AS_STRING(str), + PyBytes_GET_SIZE(str)); + Py_DECREF(str); + return res; +} +#endif // PY_VERSION_HEX < 0x030F00A1 + + +#if PY_VERSION_HEX < 0x030F00A1 +static inline PyObject* +PyTuple_FromArray(PyObject *const *array, Py_ssize_t size) +{ + PyObject *tuple = PyTuple_New(size); + if (tuple == NULL) { + return NULL; + } + for (Py_ssize_t i=0; i < size; i++) { + PyObject *item = array[i]; + PyTuple_SET_ITEM(tuple, i, Py_NewRef(item)); + } + return tuple; +} +#endif + + +#if PY_VERSION_HEX < 0x030F00A1 +static inline Py_hash_t +PyUnstable_Unicode_GET_CACHED_HASH(PyObject *op) +{ +#ifdef PYPY_VERSION + (void)op; // unused argument + return -1; +#elif PY_VERSION_HEX >= 0x03000000 + return ((PyASCIIObject*)op)->hash; +#else + return ((PyUnicodeObject*)op)->hash; +#endif +} +#endif + + #ifdef __cplusplus } #endif diff --git a/tests/test_functions.py b/tests/test_functions.py index efe4a53a..3278a1d2 100644 --- a/tests/test_functions.py +++ b/tests/test_functions.py @@ -235,11 +235,16 @@ def test_interfaces(): gmp._free_cache() # just for coverage -@pytest.mark.skipif(platform.python_implementation() != "CPython" - or sys.version_info < (3, 11), +# See pypy/pypy#5368 and oracle/graalpython#593 +@pytest.mark.skipif(platform.python_implementation() != "CPython", reason="no way to specify a signature") def test_func_api(): for fn in ["comb", "factorial", "gcd", "isqrt", "lcm", "perm"]: f = getattr(math, fn) fz = getattr(gmp, fn) - assert inspect.signature(f) == inspect.signature(fz) + f_sig = inspect.signature(f) + if fn == "factorial" and sys.version_info < (3, 11): + # Parameter x was renamed in python/cpython#32377 + x = f_sig.parameters["x"] + f_sig = inspect.Signature([x.replace(name="n")]) + assert inspect.signature(fz) == f_sig diff --git a/tests/test_mpz.py b/tests/test_mpz.py index e46dcbb2..108bbe10 100644 --- a/tests/test_mpz.py +++ b/tests/test_mpz.py @@ -1071,8 +1071,8 @@ def f(n): assert all(f.result() == 1 for f in futures) -@pytest.mark.skipif(platform.python_implementation() != "CPython" - or sys.version_info < (3, 13), +# See pypy/pypy#5368 and oracle/graalpython#593 +@pytest.mark.skipif(platform.python_implementation() != "CPython", reason="no way to specify a signature") def test_int_api(): for meth in dir(int): @@ -1080,4 +1080,24 @@ def test_int_api(): if meth.startswith("_") or not callable(m): continue mz = getattr(mpz, meth) - assert inspect.signature(m) == inspect.signature(mz) + try: + m_sig = inspect.signature(m) + except ValueError: + if sys.version_info < (3, 13): + continue + mz_sig = inspect.signature(mz) + if sys.version_info < (3, 11): + # to/from_bytes got new defaults in python/cpython#28265 + if meth == "to_bytes" and sys.version_info < (3, 11): + length = m_sig.parameters["length"] + byteorder = m_sig.parameters["byteorder"] + m_sig = inspect.Signature([m_sig.parameters["self"], + length.replace(default=1), + byteorder.replace(default="big"), + m_sig.parameters["signed"]]) + if meth == "from_bytes" and sys.version_info < (3, 11): + byteorder = m_sig.parameters["byteorder"] + m_sig = inspect.Signature([m_sig.parameters["bytes"], + byteorder.replace(default="big"), + m_sig.parameters["signed"]]) + assert m_sig == mz_sig diff --git a/utils.c b/utils.c index 5164a4f1..7e1d3cff 100644 --- a/utils.c +++ b/utils.c @@ -17,7 +17,7 @@ gmp_parse_pyargs(const gmp_pyargs *fnargs, Py_ssize_t argidx[], Py_ssize_t nkws = 0; if (kwnames) { - nkws = PyTuple_GET_SIZE(kwnames); + nkws = PyTuple_Size(kwnames); } if (nkws > fnargs->maxpos) { PyErr_Format(PyExc_TypeError, @@ -33,7 +33,8 @@ gmp_parse_pyargs(const gmp_pyargs *fnargs, Py_ssize_t argidx[], return -1; } for (Py_ssize_t i = 0; i < nkws; i++) { - const char *kwname = PyUnicode_AsUTF8(PyTuple_GET_ITEM(kwnames, i)); + const char *kwname = PyUnicode_AsUTF8AndSize(PyTuple_GetItem(kwnames, + i), NULL); Py_ssize_t j = 0; for (; j < fnargs->maxargs; j++) { @@ -65,11 +66,12 @@ gmp_parse_pyargs(const gmp_pyargs *fnargs, Py_ssize_t argidx[], PyObject * gmp_PyUnicode_TransformDecimalAndSpaceToASCII(PyObject *unicode) { + assert(PyUnicode_Check(unicode)); if (PyUnicode_IS_ASCII(unicode)) { return Py_NewRef(unicode); } - Py_ssize_t len = PyUnicode_GET_LENGTH(unicode); + Py_ssize_t len = PyUnicode_GetLength(unicode); PyObject *result = PyUnicode_New(len, 127); if (result == NULL) {