From 88ef0b503d403f3da788d7b0989fe6be5b1aa5eb Mon Sep 17 00:00:00 2001 From: Rodrigo Tobar Date: Thu, 5 Sep 2024 21:29:42 +0800 Subject: [PATCH 01/12] Remove support for Python 2.7 from C code Most of this is removing code for PY_VERSION_MINOR < 3, removing the guards for PY_VERSION_MAJOR >= 3, and removing all unnecessary macros that would now have a single definition (e.g., PyText_Check -> PyUnicode_Check) in favour of using the direct Python C API for clarity. Only in minor circumstances some small logic needed to be changed. Signed-off-by: Rodrigo Tobar --- src/c/_cffi_backend.c | 427 +++++++++------------------------------ src/c/call_python.c | 4 +- src/c/cdlopen.c | 13 +- src/c/cffi1_module.c | 8 +- src/c/cglob.c | 2 +- src/c/commontypes.c | 2 +- src/c/ffi_obj.c | 38 +--- src/c/file_emulator.h | 2 +- src/c/lib_obj.c | 26 ++- src/c/minibuffer.h | 50 +---- src/c/misc_win32.h | 49 ----- src/c/realize_c_type.c | 6 +- src/cffi/_cffi_errors.h | 14 -- src/cffi/_cffi_include.h | 10 +- src/cffi/_embedding.h | 3 - src/cffi/recompiler.py | 20 +- src/cffi/vengine_cpy.py | 39 +--- 17 files changed, 136 insertions(+), 577 deletions(-) diff --git a/src/c/_cffi_backend.c b/src/c/_cffi_backend.c index e5ff9d5b..8de8c8e1 100644 --- a/src/c/_cffi_backend.c +++ b/src/c/_cffi_backend.c @@ -141,59 +141,10 @@ #include "malloc_closure.h" -#if PY_MAJOR_VERSION >= 3 -# define STR_OR_BYTES "bytes" -# define PyText_Type PyUnicode_Type -# define PyText_Check PyUnicode_Check -# define PyTextAny_Check PyUnicode_Check -# define PyText_FromFormat PyUnicode_FromFormat -# define PyText_AsUTF8 PyUnicode_AsUTF8 -# define PyText_AS_UTF8 PyUnicode_AsUTF8 -# if PY_VERSION_HEX >= 0x03030000 -# define PyText_GetSize PyUnicode_GetLength -# else -# define PyText_GetSize PyUnicode_GetSize -# endif -# define PyText_FromString PyUnicode_FromString -# define PyText_FromStringAndSize PyUnicode_FromStringAndSize -# define PyText_InternInPlace PyUnicode_InternInPlace -# define PyText_InternFromString PyUnicode_InternFromString -# define PyIntOrLong_Check PyLong_Check +#if PY_VERSION_HEX >= 0x03030000 +# define PyText_GetSize PyUnicode_GetLength #else -# define STR_OR_BYTES "str" -# define PyText_Type PyString_Type -# define PyText_Check PyString_Check -# define PyTextAny_Check(op) (PyString_Check(op) || PyUnicode_Check(op)) -# define PyText_FromFormat PyString_FromFormat -# define PyText_AsUTF8 PyString_AsString -# define PyText_AS_UTF8 PyString_AS_STRING -# define PyText_GetSize PyString_Size -# define PyText_FromString PyString_FromString -# define PyText_FromStringAndSize PyString_FromStringAndSize -# define PyText_InternInPlace PyString_InternInPlace -# define PyText_InternFromString PyString_InternFromString -# define PyIntOrLong_Check(op) (PyInt_Check(op) || PyLong_Check(op)) -#endif - -#if PY_MAJOR_VERSION >= 3 -# define PyInt_FromLong PyLong_FromLong -# define PyInt_FromSsize_t PyLong_FromSsize_t -# define PyInt_AsSsize_t PyLong_AsSsize_t -# define PyInt_AsLong PyLong_AsLong -#endif - -#if PY_MAJOR_VERSION >= 3 -/* This is the default on Python3 and constant has been removed. */ -# define Py_TPFLAGS_CHECKTYPES 0 -#endif - -#if PY_MAJOR_VERSION < 3 -# undef PyCapsule_GetPointer -# undef PyCapsule_New -# define PyCapsule_GetPointer(capsule, name) \ - (PyCObject_AsVoidPtr(capsule)) -# define PyCapsule_New(pointer, name, destructor) \ - (PyCObject_FromVoidPtr(pointer, destructor)) +# define PyText_GetSize PyUnicode_GetSize #endif #if PY_VERSION_HEX < 0x030900a4 @@ -379,10 +330,7 @@ typedef struct { #endif #include "minibuffer.h" - -#if PY_MAJOR_VERSION >= 3 -# include "file_emulator.h" -#endif +#include "file_emulator.h" #ifdef PyUnicode_KIND /* Python >= 3.3 */ # include "wchar_helper_3.h" @@ -448,7 +396,7 @@ ctypedescr_new_on_top(CTypeDescrObject *ct_base, const char *extra_text, static PyObject * ctypedescr_repr(CTypeDescrObject *ct) { - return PyText_FromFormat("", ct->ct_name); + return PyUnicode_FromFormat("", ct->ct_name); } static void @@ -526,12 +474,12 @@ static PyObject *ctypeget_kind(CTypeDescrObject *ct, void *context) else result = "?"; - return PyText_FromString(result); + return PyUnicode_FromString(result); } static PyObject *ctypeget_cname(CTypeDescrObject *ct, void *context) { - return PyText_FromString(ct->ct_name); + return PyUnicode_FromString(ct->ct_name); } static PyObject *ctypeget_item(CTypeDescrObject *ct, void *context) @@ -547,7 +495,7 @@ static PyObject *ctypeget_length(CTypeDescrObject *ct, void *context) { if (ct->ct_flags & CT_ARRAY) { if (ct->ct_length >= 0) { - return PyInt_FromSsize_t(ct->ct_length); + return PyLong_FromSsize_t(ct->ct_length); } else { Py_INCREF(Py_None); @@ -690,7 +638,7 @@ ctypedescr_dir(PyObject *ct, PyObject *noarg) } else { Py_DECREF(x); - x = PyText_FromString(gsdef->name); + x = PyUnicode_FromString(gsdef->name); err = (x != NULL) ? PyList_Append(res, x) : -1; Py_XDECREF(x); if (err < 0) { @@ -824,12 +772,6 @@ _my_PyLong_AsLongLong(PyObject *ob) Like PyLong_AsLongLong(), this version accepts a Python int too, and does conversions from other types of objects. The difference is that this version refuses floats. */ -#if PY_MAJOR_VERSION < 3 - if (PyInt_Check(ob)) { - return PyInt_AS_LONG(ob); - } - else -#endif if (PyLong_Check(ob)) { return PyLong_AsLongLong(ob); } @@ -847,7 +789,7 @@ _my_PyLong_AsLongLong(PyObject *ob) if (io == NULL) return -1; - if (PyIntOrLong_Check(io)) { + if (PyLong_Check(io)) { res = _my_PyLong_AsLongLong(io); } else { @@ -867,15 +809,6 @@ _my_PyLong_AsUnsignedLongLong(PyObject *ob, int strict) does conversions from other types of objects. If 'strict', complains with OverflowError and refuses floats. If '!strict', rounds floats and masks the result. */ -#if PY_MAJOR_VERSION < 3 - if (PyInt_Check(ob)) { - long value1 = PyInt_AS_LONG(ob); - if (strict && value1 < 0) - goto negative; - return (unsigned PY_LONG_LONG)(PY_LONG_LONG)value1; - } - else -#endif if (PyLong_Check(ob)) { if (strict) { if (_PyLong_Sign(ob) < 0) @@ -900,7 +833,7 @@ _my_PyLong_AsUnsignedLongLong(PyObject *ob, int strict) if (io == NULL) return (unsigned PY_LONG_LONG)-1; - if (PyIntOrLong_Check(io)) { + if (PyLong_Check(io)) { res = _my_PyLong_AsUnsignedLongLong(io, strict); } else { @@ -1117,7 +1050,7 @@ convert_to_object(char *data, CTypeDescrObject *ct) /*READ(data, ct->ct_size)*/ value = read_raw_signed_data(data, ct->ct_size); if (ct->ct_flags & CT_PRIMITIVE_FITS_LONG) - return PyInt_FromLong((long)value); + return PyLong_FromLong((long)value); else return PyLong_FromLongLong(value); } @@ -1141,7 +1074,7 @@ convert_to_object(char *data, CTypeDescrObject *ct) Py_INCREF(x); return x; } - return PyInt_FromLong((long)value); + return PyLong_FromLong((long)value); } else return PyLong_FromUnsignedLongLong(value); @@ -1198,7 +1131,7 @@ convert_to_object_bitfield(char *data, CFieldObject *cf) result = ((PY_LONG_LONG)value) - (PY_LONG_LONG)shiftforsign; if (ct->ct_flags & CT_PRIMITIVE_FITS_LONG) - return PyInt_FromLong((long)result); + return PyLong_FromLong((long)result); else return PyLong_FromLongLong(result); } @@ -1210,7 +1143,7 @@ convert_to_object_bitfield(char *data, CFieldObject *cf) value = (value >> cf->cf_bitshift) & valuemask; if (ct->ct_flags & CT_PRIMITIVE_FITS_LONG) - return PyInt_FromLong((long)value); + return PyLong_FromLong((long)value); else return PyLong_FromUnsignedLongLong(value); } @@ -1225,7 +1158,7 @@ static int _convert_overflow(PyObject *init, const char *ct_name) if (s == NULL) return -1; PyErr_Format(PyExc_OverflowError, "integer %s does not fit '%s'", - PyText_AS_UTF8(s), ct_name); + PyUnicode_AsUTF8(s), ct_name); Py_DECREF(s); return -1; } @@ -1243,7 +1176,7 @@ static int _convert_to_char(PyObject *init) return *(unsigned char *)data; } PyErr_Format(PyExc_TypeError, - "initializer for ctype 'char' must be a "STR_OR_BYTES + "initializer for ctype 'char' must be a bytes" " of length 1, not %.200s", Py_TYPE(init)->tp_name); return -1; } @@ -1508,13 +1441,13 @@ convert_array_from_object(char *data, CTypeDescrObject *ct, PyObject *init) char *srcdata; Py_ssize_t n; if (!PyBytes_Check(init)) { - expected = STR_OR_BYTES" or list or tuple"; + expected = "bytes or list or tuple"; goto cannot_convert; } n = PyBytes_GET_SIZE(init); if (ct->ct_length >= 0 && n > ct->ct_length) { PyErr_Format(PyExc_IndexError, - "initializer "STR_OR_BYTES" is too long for '%s' " + "initializer bytes is too long for '%s' " "(got %zd characters)", ct->ct_name, n); return -1; } @@ -1849,9 +1782,9 @@ convert_from_object_bitfield(char *data, CFieldObject *cf, PyObject *init) PyErr_Format(PyExc_OverflowError, "value %s outside the range allowed by the " "bit field width: %s <= x <= %s", - PyText_AS_UTF8(svalue), - PyText_AS_UTF8(sfmin), - PyText_AS_UTF8(sfmax)); + PyUnicode_AsUTF8(svalue), + PyUnicode_AsUTF8(sfmin), + PyUnicode_AsUTF8(sfmax)); skip: Py_XDECREF(svalue); Py_XDECREF(sfmin); @@ -2107,9 +2040,9 @@ static PyObject *convert_cdata_to_enum_string(CDataObject *cd, int both) if (o == NULL) d_value = NULL; else { - d_value = PyText_FromFormat("%s: %s", - PyText_AS_UTF8(o), - PyText_AS_UTF8(d_value)); + d_value = PyUnicode_FromFormat("%s: %s", + PyUnicode_AsUTF8(o), + PyUnicode_AsUTF8(d_value)); Py_DECREF(o); } } @@ -2137,7 +2070,7 @@ static PyObject *cdata_repr(CDataObject *cd) /*READ(cd->c_data, sizeof(long double)*/ lvalue = read_raw_longdouble_data(cd->c_data); sprintf(buffer, "%LE", lvalue); - s = PyText_FromString(buffer); + s = PyUnicode_FromString(buffer); } else { PyObject *o = convert_to_object(cd->c_data, cd->c_type); @@ -2148,14 +2081,14 @@ static PyObject *cdata_repr(CDataObject *cd) } } else if ((cd->c_type->ct_flags & CT_ARRAY) && cd->c_type->ct_length < 0) { - s = PyText_FromFormat("sliced length %zd", get_array_length(cd)); + s = PyUnicode_FromFormat("sliced length %zd", get_array_length(cd)); } else { if (cd->c_data != NULL) { - s = PyText_FromFormat("%p", cd->c_data); + s = PyUnicode_FromFormat("%p", cd->c_data); } else - s = PyText_FromString("NULL"); + s = PyUnicode_FromString("NULL"); } if (s == NULL) return NULL; @@ -2166,9 +2099,9 @@ static PyObject *cdata_repr(CDataObject *cd) extra = " &"; else extra = ""; - result = PyText_FromFormat("", + result = PyUnicode_FromFormat("", cd->c_type->ct_name, extra, - PyText_AsUTF8(s)); + PyUnicode_AsUTF8(s)); Py_DECREF(s); return result; } @@ -2178,8 +2111,8 @@ static PyObject *_cdata_repr2(CDataObject *cd, char *text, PyObject *x) PyObject *res, *s = PyObject_Repr(x); if (s == NULL) return NULL; - res = PyText_FromFormat("", - cd->c_type->ct_name, text, PyText_AsUTF8(s)); + res = PyUnicode_FromFormat("", + cd->c_type->ct_name, text, PyUnicode_AsUTF8(s)); Py_DECREF(s); return res; } @@ -2206,7 +2139,7 @@ static PyObject *_frombuf_repr(CDataObject *cd, const char *cd_type_name) Py_buffer *view = ((CDataObject_frombuf *)cd)->bufferview; const char *obj_tp_name; if (view->obj == NULL) { - return PyText_FromFormat( + return PyUnicode_FromFormat( "", cd_type_name); } @@ -2215,7 +2148,7 @@ static PyObject *_frombuf_repr(CDataObject *cd, const char *cd_type_name) if (cd->c_type->ct_flags & CT_ARRAY) { Py_ssize_t buflen = get_array_length(cd); - return PyText_FromFormat( + return PyUnicode_FromFormat( "", cd_type_name, buflen, @@ -2223,7 +2156,7 @@ static PyObject *_frombuf_repr(CDataObject *cd, const char *cd_type_name) } else { - return PyText_FromFormat( + return PyUnicode_FromFormat( "", cd_type_name, obj_tp_name); @@ -2247,7 +2180,7 @@ static Py_ssize_t cdataowning_size_bytes(CDataObject *cd) static PyObject *cdataowning_repr(CDataObject *cd) { Py_ssize_t size = cdataowning_size_bytes(cd); - return PyText_FromFormat("", + return PyUnicode_FromFormat("", cd->c_type->ct_name, size); } @@ -2304,37 +2237,33 @@ static PyObject *cdata_int(CDataObject *cd) long value; /*READ(cd->c_data, cd->c_type->ct_size)*/ value = (long)read_raw_signed_data(cd->c_data, cd->c_type->ct_size); - return PyInt_FromLong(value); + return PyLong_FromLong(value); } if (cd->c_type->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_UNSIGNED)) { PyObject *result = convert_to_object(cd->c_data, cd->c_type); if (result != NULL && PyBool_Check(result)) - result = PyInt_FromLong(PyInt_AsLong(result)); + result = PyLong_FromLong(PyLong_AsLong(result)); return result; } else if (cd->c_type->ct_flags & CT_PRIMITIVE_CHAR) { /*READ(cd->c_data, cd->c_type->ct_size)*/ switch (cd->c_type->ct_size) { case sizeof(char): - return PyInt_FromLong((unsigned char)cd->c_data[0]); + return PyLong_FromLong((unsigned char)cd->c_data[0]); case 2: - return PyInt_FromLong((long)*(cffi_char16_t *)cd->c_data); + return PyLong_FromLong((long)*(cffi_char16_t *)cd->c_data); case 4: if (cd->c_type->ct_flags & CT_IS_SIGNED_WCHAR) - return PyInt_FromLong((long)*(int32_t *)cd->c_data); + return PyLong_FromLong((long)*(int32_t *)cd->c_data); else if (sizeof(long) > 4) - return PyInt_FromLong(*(uint32_t *)cd->c_data); + return PyLong_FromLong(*(uint32_t *)cd->c_data); else return PyLong_FromUnsignedLong(*(uint32_t *)cd->c_data); } } else if (cd->c_type->ct_flags & CT_PRIMITIVE_FLOAT) { PyObject *o = cdata_float(cd); -#if PY_MAJOR_VERSION < 3 - PyObject *r = o ? PyNumber_Int(o) : NULL; -#else PyObject *r = o ? PyNumber_Long(o) : NULL; -#endif Py_XDECREF(o); return r; } @@ -2343,19 +2272,6 @@ static PyObject *cdata_int(CDataObject *cd) return NULL; } -#if PY_MAJOR_VERSION < 3 -static PyObject *cdata_long(CDataObject *cd) -{ - PyObject *res = cdata_int(cd); - if (res != NULL && PyInt_CheckExact(res)) { - PyObject *o = PyLong_FromLong(PyInt_AS_LONG(res)); - Py_DECREF(res); - res = o; - } - return res; -} -#endif - static PyObject *cdata_float(CDataObject *cd) { if (cd->c_type->ct_flags & CT_PRIMITIVE_FLOAT) { @@ -2452,10 +2368,6 @@ static PyObject *cdata_richcompare(PyObject *v, PyObject *w, int op) return pyres; } -#if PY_MAJOR_VERSION < 3 -typedef long Py_hash_t; -#endif - static Py_hash_t cdata_hash(PyObject *v) { if (((CDataObject *)v)->c_type->ct_flags & CT_PRIMITIVE_ANY) { @@ -2544,13 +2456,13 @@ _cdata_getslicearg(CDataObject *cd, PySliceObject *slice, Py_ssize_t bounds[]) Py_ssize_t start, stop; CTypeDescrObject *ct; - start = PyInt_AsSsize_t(slice->start); + start = PyLong_AsSsize_t(slice->start); if (start == -1 && PyErr_Occurred()) { if (slice->start == Py_None) PyErr_SetString(PyExc_IndexError, "slice start must be specified"); return NULL; } - stop = PyInt_AsSsize_t(slice->stop); + stop = PyLong_AsSsize_t(slice->stop); if (stop == -1 && PyErr_Occurred()) { if (slice->stop == Py_None) PyErr_SetString(PyExc_IndexError, "slice stop must be specified"); @@ -2847,11 +2759,7 @@ cdata_sub(PyObject *v, PyObject *w) } diff = diff / itemsize; } -#if PY_MAJOR_VERSION < 3 - return PyInt_FromSsize_t(diff); -#else return PyLong_FromSsize_t(diff); -#endif } return _cdata_add_or_sub(v, w, -1); @@ -2864,7 +2772,7 @@ _cdata_attr_errmsg(char *errmsg, CDataObject *cd, PyObject *attr) if (!PyErr_ExceptionMatches(PyExc_AttributeError)) return; PyErr_Clear(); - text = PyText_AsUTF8(attr); + text = PyUnicode_AsUTF8(attr); if (text == NULL) return; PyErr_Format(PyExc_AttributeError, errmsg, cd->c_type->ct_name, text); @@ -3157,11 +3065,7 @@ cdata_call(CDataObject *cd, PyObject *args, PyObject *kwds) } PyTuple_SET_ITEM(fvarargs, i, (PyObject *)ct); } -#if PY_MAJOR_VERSION < 3 - fabi = PyInt_AS_LONG(PyTuple_GET_ITEM(signature, 0)); -#else fabi = PyLong_AS_LONG(PyTuple_GET_ITEM(signature, 0)); -#endif cif_descr = fb_prepare_cif(fvarargs, fresult, nargs_declared, fabi); if (cif_descr == NULL) goto error; @@ -3383,9 +3287,6 @@ static PyNumberMethods CData_as_number = { (binaryfunc)cdata_add, /*nb_add*/ (binaryfunc)cdata_sub, /*nb_subtract*/ 0, /*nb_multiply*/ -#if PY_MAJOR_VERSION < 3 - 0, /*nb_divide*/ -#endif 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ @@ -3399,15 +3300,8 @@ static PyNumberMethods CData_as_number = { 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ -#if PY_MAJOR_VERSION < 3 - 0, /*nb_coerce*/ -#endif (unaryfunc)cdata_int, /*nb_int*/ -#if PY_MAJOR_VERSION < 3 - (unaryfunc)cdata_long, /*nb_long*/ -#else - 0, -#endif + 0, /*nb_reserved*/ (unaryfunc)cdata_float, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ @@ -3453,7 +3347,7 @@ static PyTypeObject CData_Type = { (getattrofunc)cdata_getattro, /* tp_getattro */ (setattrofunc)cdata_setattro, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ "The internal base type for CData objects. Use FFI.CData to access " "it. Always check with isinstance(): subtypes are sometimes returned " "on CPython, for performance reasons.", /* tp_doc */ @@ -3497,7 +3391,7 @@ static PyTypeObject CDataOwning_Type = { 0, /* inherited */ /* tp_getattro */ 0, /* inherited */ /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ "This is an internal subtype of _CDataBase for performance only on " "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */ 0, /* tp_traverse */ @@ -3540,8 +3434,7 @@ static PyTypeObject CDataOwningGC_Type = { 0, /* inherited */ /* tp_getattro */ 0, /* inherited */ /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES /* tp_flags */ - | Py_TPFLAGS_HAVE_GC, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ "This is an internal subtype of _CDataBase for performance only on " "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */ (traverseproc)cdataowninggc_traverse, /* tp_traverse */ @@ -3584,8 +3477,7 @@ static PyTypeObject CDataFromBuf_Type = { 0, /* inherited */ /* tp_getattro */ 0, /* inherited */ /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES /* tp_flags */ - | Py_TPFLAGS_HAVE_GC, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ "This is an internal subtype of _CDataBase for performance only on " "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */ (traverseproc)cdatafrombuf_traverse, /* tp_traverse */ @@ -3628,7 +3520,7 @@ static PyTypeObject CDataGCP_Type = { 0, /* inherited */ /* tp_getattro */ 0, /* inherited */ /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES /* tp_flags */ + Py_TPFLAGS_DEFAULT /* tp_flags */ #ifdef Py_TPFLAGS_HAVE_FINALIZE | Py_TPFLAGS_HAVE_FINALIZE #endif @@ -3994,12 +3886,6 @@ _my_PyObject_AsBool(PyObject *ob) PyNumberMethods *nb; int res; -#if PY_MAJOR_VERSION < 3 - if (PyInt_Check(ob)) { - return PyInt_AS_LONG(ob) != 0; - } - else -#endif if (PyLong_Check(ob)) { return _PyLong_Sign(ob) != 0; } @@ -4033,7 +3919,7 @@ _my_PyObject_AsBool(PyObject *ob) if (io == NULL) return -1; - if (PyIntOrLong_Check(io) || PyFloat_Check(io)) { + if (PyLong_Check(io) || PyFloat_Check(io)) { res = _my_PyObject_AsBool(io); } else { @@ -4067,17 +3953,6 @@ static CDataObject *cast_to_integer_or_char(CTypeDescrObject *ct, PyObject *ob) (CT_POINTER|CT_FUNCTIONPTR|CT_ARRAY)) { value = (Py_intptr_t)((CDataObject *)ob)->c_data; } -#if PY_MAJOR_VERSION < 3 - else if (PyString_Check(ob)) { - if (PyString_GET_SIZE(ob) != 1) { - PyErr_Format(PyExc_TypeError, - "cannot cast string of length %zd to ctype '%s'", - PyString_GET_SIZE(ob), ct->ct_name); - return NULL; - } - value = (unsigned char)PyString_AS_STRING(ob)[0]; - } -#endif else if (PyUnicode_Check(ob)) { char err_buf[80]; cffi_char32_t ordinal; @@ -4343,7 +4218,7 @@ static void dl_dealloc(DynLibObject *dlobj) static PyObject *dl_repr(DynLibObject *dlobj) { - return PyText_FromFormat("", dlobj->dl_name); + return PyUnicode_FromFormat("", dlobj->dl_name); } static int dl_check_closed(DynLibObject *dlobj) @@ -4538,8 +4413,8 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, PyErr_Format(PyExc_RuntimeError, "cannot call dlopen(NULL)"); return NULL; } - *p_temp = PyText_FromFormat("%p", handle); - *p_printable_filename = PyText_AsUTF8(*p_temp); + *p_temp = PyUnicode_FromFormat("%p", handle); + *p_printable_filename = PyUnicode_AsUTF8(*p_temp); *auto_close = 0; return handle; } @@ -4552,13 +4427,7 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, { Py_ssize_t sz1; wchar_t *w1; -#if PY_MAJOR_VERSION < 3 - s = PyUnicode_AsUTF8String(s); - if (s == NULL) - return NULL; - *p_temp = s; -#endif - *p_printable_filename = PyText_AsUTF8(s); + *p_printable_filename = PyUnicode_AsUTF8(s); if (*p_printable_filename == NULL) return NULL; @@ -4578,18 +4447,7 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, if (!PyArg_ParseTuple(args, "et|i:load_library", Py_FileSystemDefaultEncoding, &filename_or_null, &flags)) return NULL; -#if PY_MAJOR_VERSION < 3 - if (PyUnicode_Check(s)) - { - s = PyUnicode_AsUTF8String(s); - if (s == NULL) { - PyMem_Free(filename_or_null); - return NULL; - } - *p_temp = s; - } -#endif - *p_printable_filename = PyText_AsUTF8(s); + *p_printable_filename = PyUnicode_AsUTF8(s); if (*p_printable_filename == NULL) { PyMem_Free(filename_or_null); return NULL; @@ -5084,7 +4942,7 @@ _add_field(PyObject *interned_fields, PyObject *fname, CTypeDescrObject *ftype, cf->cf_flags = flags; Py_INCREF(fname); - PyText_InternInPlace(&fname); + PyUnicode_InternInPlace(&fname); prev_size = PyDict_Size(interned_fields); err = PyDict_SetItem(interned_fields, fname, (PyObject *)cf); Py_DECREF(fname); @@ -5094,7 +4952,7 @@ _add_field(PyObject *interned_fields, PyObject *fname, CTypeDescrObject *ftype, if (PyDict_Size(interned_fields) != prev_size + 1) { PyErr_Format(PyExc_KeyError, "duplicate field name '%s'", - PyText_AS_UTF8(fname)); + PyUnicode_AsUTF8(fname)); return NULL; } return cf; /* borrowed reference */ @@ -5233,7 +5091,7 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) Py_ssize_t foffset = -1; if (!PyArg_ParseTuple(PyList_GET_ITEM(fields, i), "O!O!|in:list item", - &PyText_Type, &fname, + &PyUnicode_Type, &fname, &CTypeDescr_Type, &ftype, &fbitsize, &foffset)) goto error; @@ -5253,7 +5111,7 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) else { PyErr_Format(PyExc_TypeError, "field '%s.%s' has ctype '%s' of unknown size", - ct->ct_name, PyText_AS_UTF8(fname), + ct->ct_name, PyUnicode_AsUTF8(fname), ftype->ct_name); goto error; } @@ -5322,7 +5180,7 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) except to know if we must set CT_CUSTOM_FIELD_POS */ if (detect_custom_layout(ct, sflags, byteoffset, foffset, "wrong offset for field '", - PyText_AS_UTF8(fname), "'") < 0) + PyUnicode_AsUTF8(fname), "'") < 0) goto error; byteoffset = foffset; } @@ -5369,7 +5227,7 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) PyErr_Format(PyExc_TypeError, "field '%s.%s' is a bitfield, " "but a fixed offset is specified", - ct->ct_name, PyText_AS_UTF8(fname)); + ct->ct_name, PyUnicode_AsUTF8(fname)); goto error; } @@ -5378,7 +5236,7 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) CT_PRIMITIVE_CHAR))) { PyErr_Format(PyExc_TypeError, "field '%s.%s' declared as '%s' cannot be a bit field", - ct->ct_name, PyText_AS_UTF8(fname), + ct->ct_name, PyUnicode_AsUTF8(fname), ftype->ct_name); goto error; } @@ -5386,7 +5244,7 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) PyErr_Format(PyExc_TypeError, "bit field '%s.%s' is declared '%s:%d', which " "exceeds the width of the type", - ct->ct_name, PyText_AS_UTF8(fname), + ct->ct_name, PyUnicode_AsUTF8(fname), ftype->ct_name, fbitsize); goto error; } @@ -5401,7 +5259,7 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) if (PyText_GetSize(fname) > 0) { PyErr_Format(PyExc_TypeError, "field '%s.%s' is declared with :0", - ct->ct_name, PyText_AS_UTF8(fname)); + ct->ct_name, PyUnicode_AsUTF8(fname)); goto error; } if (!(sflags & SF_MSVC_BITFIELDS)) { @@ -5441,7 +5299,7 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) PyErr_Format(PyExc_NotImplementedError, "with 'packed', gcc would compile field " "'%s.%s' to reuse some bits in the previous " - "field", ct->ct_name, PyText_AS_UTF8(fname)); + "field", ct->ct_name, PyUnicode_AsUTF8(fname)); goto error; } field_offset_bytes += falign; @@ -6031,7 +5889,7 @@ static PyObject *new_function_type(PyObject *fargs, /* tuple */ fct->ct_stuff = PyTuple_New(2 + funcbuilder.nargs); if (fct->ct_stuff == NULL) goto error; - fabiobj = PyInt_FromLong(fabi); + fabiobj = PyLong_FromLong(fabi); if (fabiobj == NULL) goto error; PyTuple_SET_ITEM(fct->ct_stuff, 0, fabiobj); @@ -6172,7 +6030,7 @@ static void _my_PyErr_WriteUnraisable(PyObject *t, PyObject *v, PyObject *tb, #if PY_VERSION_HEX >= 0x030D0000 PyErr_FormatUnraisable("Exception ignored %S", s); #else - _PyErr_WriteUnraisableMsg(PyText_AS_UTF8(s), NULL); + _PyErr_WriteUnraisableMsg(PyUnicode_AsUTF8(s), NULL); #endif Py_DECREF(s); } @@ -6184,7 +6042,6 @@ static void _my_PyErr_WriteUnraisable(PyObject *t, PyObject *v, PyObject *tb, /* version for Python 2.7 and < 3.8 */ PyObject *f; -#if PY_MAJOR_VERSION >= 3 /* jump through hoops to ensure the tb is attached to v, on Python 3 */ PyErr_NormalizeException(&t, &v, &tb); if (tb == NULL) { @@ -6192,7 +6049,6 @@ static void _my_PyErr_WriteUnraisable(PyObject *t, PyObject *v, PyObject *tb, Py_INCREF(tb); } PyException_SetTraceback(v, tb); -#endif f = PySys_GetObject("stderr"); if (f != NULL) { if (obj != NULL) { @@ -6572,19 +6428,7 @@ static PyObject *b_new_enum_type(PyObject *self, PyObject *args) PyObject *value = PyTuple_GET_ITEM(enumvalues, i); tmpkey = PyTuple_GET_ITEM(enumerators, i); Py_INCREF(tmpkey); - if (!PyText_Check(tmpkey)) { -#if PY_MAJOR_VERSION < 3 - if (PyUnicode_Check(tmpkey)) { - const char *text = PyText_AsUTF8(tmpkey); - if (text == NULL) - goto error; - Py_DECREF(tmpkey); - tmpkey = PyString_FromString(text); - if (tmpkey == NULL) - goto error; - } - else -#endif + if (!PyUnicode_Check(tmpkey)) { { PyErr_SetString(PyExc_TypeError, "enumerators must be a list of strings"); @@ -6640,7 +6484,7 @@ static PyObject *b_alignof(PyObject *self, PyObject *arg) align = get_alignment((CTypeDescrObject *)arg); if (align < 0) return NULL; - return PyInt_FromLong(align); + return PyLong_FromLong(align); } static Py_ssize_t direct_sizeof_cdata(CDataObject *cd) @@ -6678,7 +6522,7 @@ static PyObject *b_sizeof(PyObject *self, PyObject *arg) "expected a 'cdata' or 'ctype' object"); return NULL; } - return PyInt_FromSsize_t(size); + return PyLong_FromSsize_t(size); } static PyObject *b_typeof(PyObject *self, PyObject *arg) @@ -6702,7 +6546,7 @@ static CTypeDescrObject *direct_typeoffsetof(CTypeDescrObject *ct, CTypeDescrObject *res; CFieldObject *cf; - if (PyTextAny_Check(fieldname)) { + if (PyUnicode_Check(fieldname)) { if (!following && (ct->ct_flags & CT_POINTER)) ct = ct->ct_itemdescr; if (!(ct->ct_flags & (CT_STRUCT|CT_UNION))) { @@ -6729,7 +6573,7 @@ static CTypeDescrObject *direct_typeoffsetof(CTypeDescrObject *ct, *offset = cf->cf_offset; } else { - Py_ssize_t index = PyInt_AsSsize_t(fieldname); + Py_ssize_t index = PyLong_AsSsize_t(fieldname); if (index < 0 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "field name or array index expected"); @@ -6819,7 +6663,7 @@ static PyObject *b_getcname(PyObject *self, PyObject *args) memcpy(p, ct->ct_name + ct->ct_name_position, namelen - ct->ct_name_position); - return PyText_FromStringAndSize(s, namelen + replacelen); + return PyUnicode_FromStringAndSize(s, namelen + replacelen); } static PyObject *b_string(PyObject *self, PyObject *args, PyObject *kwds) @@ -6843,7 +6687,7 @@ static PyObject *b_string(PyObject *self, PyObject *args, PyObject *kwds) if (s != NULL) { PyErr_Format(PyExc_RuntimeError, "cannot use string() on %s", - PyText_AS_UTF8(s)); + PyUnicode_AsUTF8(s)); Py_DECREF(s); } return NULL; @@ -6963,7 +6807,7 @@ static PyObject *b_unpack(PyObject *self, PyObject *args, PyObject *kwds) if (s != NULL) { PyErr_Format(PyExc_RuntimeError, "cannot use unpack() on %s", - PyText_AS_UTF8(s)); + PyUnicode_AsUTF8(s)); Py_DECREF(s); } return NULL; @@ -7051,13 +6895,13 @@ static PyObject *b_unpack(PyObject *self, PyObject *args, PyObject *kwds) default: x = convert_to_object(src, ctitem); break; /* special cases for performance only */ - case 0: x = PyInt_FromLong(*(signed char *)src); break; - case 1: x = PyInt_FromLong(*(short *)src); break; - case 2: x = PyInt_FromLong(*(int *)src); break; - case 3: x = PyInt_FromLong(*(long *)src); break; - case 4: x = PyInt_FromLong(*(unsigned char *)src); break; - case 5: x = PyInt_FromLong(*(unsigned short *)src); break; - case 6: x = PyInt_FromLong((long)*(unsigned int *)src); break; + case 0: x = PyLong_FromLong(*(signed char *)src); break; + case 1: x = PyLong_FromLong(*(short *)src); break; + case 2: x = PyLong_FromLong(*(int *)src); break; + case 3: x = PyLong_FromLong(*(long *)src); break; + case 4: x = PyLong_FromLong(*(unsigned char *)src); break; + case 5: x = PyLong_FromLong(*(unsigned short *)src); break; + case 6: x = PyLong_FromLong((long)*(unsigned int *)src); break; case 7: x = PyLong_FromUnsignedLong(*(unsigned long *)src); break; case 8: x = PyFloat_FromDouble(*(float *)src); break; case 9: x = PyFloat_FromDouble(*(double *)src); break; @@ -7141,12 +6985,12 @@ static PyObject *b_get_errno(PyObject *self, PyObject *noarg) restore_errno_only(); err = errno; errno = 0; - return PyInt_FromLong(err); + return PyLong_FromLong(err); } static PyObject *b_set_errno(PyObject *self, PyObject *arg) { - long ival = PyInt_AsLong(arg); + long ival = PyLong_AsLong(arg); if (ival == -1 && PyErr_Occurred()) return NULL; else if (ival < INT_MIN || ival > INT_MAX) { @@ -7228,46 +7072,6 @@ static PyObject *b_from_handle(PyObject *self, PyObject *arg) static int _my_PyObject_GetContiguousBuffer(PyObject *x, Py_buffer *view, int writable_only) { -#if PY_MAJOR_VERSION < 3 - /* Some objects only support the buffer interface and CPython doesn't - translate it into the memoryview interface, mess. Hack a very - minimal content for 'view'. Don't care if the other fields are - uninitialized: we only call PyBuffer_Release(), which only reads - 'view->obj'. */ - PyBufferProcs *pb = x->ob_type->tp_as_buffer; - if (pb && !pb->bf_releasebuffer) { - /* we used to try all three in some vaguely sensible order, - i.e. first the write. But trying to call the write on a - read-only buffer fails with TypeError. So we use a less- - sensible order now. See test_from_buffer_more_cases. - - If 'writable_only', we only try bf_getwritebuffer. - */ - readbufferproc proc = NULL; - if (!writable_only) { - proc = (readbufferproc)pb->bf_getreadbuffer; - if (!proc) - proc = (readbufferproc)pb->bf_getcharbuffer; - } - if (!proc) - proc = (readbufferproc)pb->bf_getwritebuffer; - - if (proc && pb->bf_getsegcount) { - if ((*pb->bf_getsegcount)(x, NULL) != 1) { - PyErr_SetString(PyExc_TypeError, - "expected a single-segment buffer object"); - return -1; - } - view->len = (*proc)(x, 0, &view->buf); - if (view->len < 0) - return -1; - view->obj = x; - Py_INCREF(x); - return 0; - } - } -#endif - if (PyObject_GetBuffer(x, view, writable_only ? PyBUF_WRITABLE : PyBUF_SIMPLE) < 0) return -1; @@ -7715,30 +7519,6 @@ static PyObject *b__testfunc(PyObject *self, PyObject *args) return PyLong_FromVoidPtr(f); } -#if PY_MAJOR_VERSION < 3 -static Py_ssize_t _test_segcountproc(PyObject *o, Py_ssize_t *ignored) -{ - return 1; -} -static Py_ssize_t _test_getreadbuf(PyObject *o, Py_ssize_t i, void **r) -{ - static char buf[] = "RDB"; - *r = buf; - return 3; -} -static Py_ssize_t _test_getwritebuf(PyObject *o, Py_ssize_t i, void **r) -{ - static char buf[] = "WRB"; - *r = buf; - return 3; -} -static Py_ssize_t _test_getcharbuf(PyObject *o, Py_ssize_t i, char **r) -{ - static char buf[] = "CHB"; - *r = buf; - return 3; -} -#endif static int _test_getbuf(PyObject *self, Py_buffer *view, int flags) { static char buf[] = "GTB"; @@ -7761,14 +7541,6 @@ static PyObject *b__testbuff(PyObject *self, PyObject *args) assert(obj->tp_as_buffer != NULL); -#if PY_MAJOR_VERSION < 3 - obj->tp_as_buffer->bf_getsegcount = &_test_segcountproc; - obj->tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER; - obj->tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER; - if (methods & 1) obj->tp_as_buffer->bf_getreadbuffer = &_test_getreadbuf; - if (methods & 2) obj->tp_as_buffer->bf_getwritebuffer = &_test_getwritebuf; - if (methods & 4) obj->tp_as_buffer->bf_getcharbuffer = &_test_getcharbuf; -#endif if (methods & 8) obj->tp_as_buffer->bf_getbuffer = &_test_getbuf; if (methods & 16) obj->tp_as_buffer->bf_getbuffer = &_test_getbuf_ro; @@ -7910,7 +7682,7 @@ static PyObject *_cffi_get_struct_layout(Py_ssize_t nums[]) return NULL; while (--count >= 0) { - PyObject *o = PyInt_FromSsize_t(nums[count]); + PyObject *o = PyLong_FromSsize_t(nums[count]); if (o == NULL) { Py_DECREF(result); return NULL; @@ -8031,7 +7803,6 @@ static struct { const char *name; int value; } all_dlopen_flags[] = { /************************************************************/ -#if PY_MAJOR_VERSION >= 3 static struct PyModuleDef FFIBackendModuleDef = { PyModuleDef_HEAD_INIT, "_cffi_backend", @@ -8044,12 +7815,6 @@ static struct PyModuleDef FFIBackendModuleDef = { PyMODINIT_FUNC PyInit__cffi_backend(void) -#else -#define INITERROR return - -PyMODINIT_FUNC -init_cffi_backend(void) -#endif { PyObject *m, *v; int i; @@ -8072,19 +7837,15 @@ init_cffi_backend(void) }; v = PySys_GetObject("version"); - if (v == NULL || !PyText_Check(v) || - strncmp(PyText_AS_UTF8(v), PY_VERSION, 3) != 0) { + if (v == NULL || !PyUnicode_Check(v) || + strncmp(PyUnicode_AsUTF8(v), PY_VERSION, 3) != 0) { PyErr_Format(PyExc_ImportError, "this module was compiled for Python %c%c%c", PY_VERSION[0], PY_VERSION[1], PY_VERSION[2]); INITERROR; } -#if PY_MAJOR_VERSION >= 3 m = PyModule_Create(&FFIBackendModuleDef); -#else - m = Py_InitModule("_cffi_backend", FFIBackendMethods); -#endif if (m == NULL) INITERROR; @@ -8113,11 +7874,11 @@ init_cffi_backend(void) } if (!init_done) { - v = PyText_FromString("_cffi_backend"); + v = PyUnicode_FromString("_cffi_backend"); if (v == NULL || PyDict_SetItemString(CData_Type.tp_dict, "__module__", v) < 0) INITERROR; - v = PyText_FromString(""); + v = PyUnicode_FromString(""); if (v == NULL || PyDict_SetItemString(CData_Type.tp_dict, "__name__", v) < 0) INITERROR; @@ -8129,7 +7890,7 @@ init_cffi_backend(void) if (v == NULL || PyModule_AddObject(m, "_C_API", v) < 0) INITERROR; - v = PyText_FromString(CFFI_VERSION); + v = PyUnicode_FromString(CFFI_VERSION); if (v == NULL || PyModule_AddObject(m, "__version__", v) < 0) INITERROR; @@ -8166,9 +7927,7 @@ init_cffi_backend(void) if (init_ffi_lib(m) < 0) INITERROR; -#if PY_MAJOR_VERSION >= 3 if (init_file_emulator() < 0) INITERROR; return m; -#endif } diff --git a/src/c/call_python.c b/src/c/call_python.c index d3d2e178..58d9c23a 100644 --- a/src/c/call_python.c +++ b/src/c/call_python.c @@ -47,7 +47,7 @@ static PyObject *_get_interpstate_dict(void) /* from there on, we know the (sub-)interpreter is still valid */ if (attr_name == NULL) { - attr_name = PyText_InternFromString("__cffi_backend_extern_py"); + attr_name = PyUnicode_InternFromString("__cffi_backend_extern_py"); if (attr_name == NULL) goto error; } @@ -90,7 +90,7 @@ static PyObject *_ffi_def_extern_decorator(PyObject *outer_args, PyObject *fn) name = PyObject_GetAttrString(fn, "__name__"); if (name == NULL) return NULL; - s = PyText_AsUTF8(name); + s = PyUnicode_AsUTF8(name); if (s == NULL) { Py_DECREF(name); return NULL; diff --git a/src/c/cdlopen.c b/src/c/cdlopen.c index 7db7ae28..d07fcd25 100644 --- a/src/c/cdlopen.c +++ b/src/c/cdlopen.c @@ -7,7 +7,7 @@ static void *cdlopen_fetch(PyObject *libname, void *libhandle, if (libhandle == NULL) { PyErr_Format(FFIError, "library '%s' has been closed", - PyText_AS_UTF8(libname)); + PyUnicode_AsUTF8(libname)); return NULL; } @@ -16,7 +16,7 @@ static void *cdlopen_fetch(PyObject *libname, void *libhandle, if (address == NULL) { const char *error = dlerror(); PyErr_Format(FFIError, "symbol '%s' not found in library '%s': %s", - symbol, PyText_AS_UTF8(libname), error); + symbol, PyUnicode_AsUTF8(libname), error); } return address; } @@ -32,7 +32,7 @@ static int cdlopen_close(PyObject *libname, void *libhandle) if (libhandle != NULL && dlclose(libhandle) != 0) { const char *error = dlerror(); PyErr_Format(FFIError, "closing library '%s': %s", - PyText_AS_UTF8(libname), error); + PyUnicode_AsUTF8(libname), error); return -1; } return 0; @@ -195,13 +195,6 @@ static int ffiobj_init(PyObject *self, PyObject *args, PyObject *kwds) _CFFI_GETOP(nglobs[i].type_op) == _CFFI_OP_ENUM) { PyObject *o = PyTuple_GET_ITEM(globals, i * 2 + 1); nglobs[i].address = &_cdl_realize_global_int; -#if PY_MAJOR_VERSION < 3 - if (PyInt_Check(o)) { - nintconsts[i].neg = PyInt_AS_LONG(o) <= 0; - nintconsts[i].value = (long long)PyInt_AS_LONG(o); - } - else -#endif { nintconsts[i].neg = PyObject_RichCompareBool(o, Py_False, Py_LE); diff --git a/src/c/cffi1_module.c b/src/c/cffi1_module.c index 06a84fea..ba6bfeab 100644 --- a/src/c/cffi1_module.c +++ b/src/c/cffi1_module.c @@ -46,7 +46,7 @@ static int init_ffi_lib(PyObject *m) return -1; for (i = 0; all_dlopen_flags[i].name != NULL; i++) { - x = PyInt_FromLong(all_dlopen_flags[i].value); + x = PyLong_FromLong(all_dlopen_flags[i].value); if (x == NULL) return -1; res = PyDict_SetItemString(FFI_Type.tp_dict, @@ -116,7 +116,6 @@ static int make_included_tuples(char *module_name, static PyObject *_my_Py_InitModule(char *module_name) { -#if PY_MAJOR_VERSION >= 3 struct PyModuleDef *module_def, local_module_def = { PyModuleDef_HEAD_INIT, module_name, @@ -131,9 +130,6 @@ static PyObject *_my_Py_InitModule(char *module_name) return PyErr_NoMemory(); *module_def = local_module_def; return PyModule_Create(module_def); -#else - return Py_InitModule(module_name, NULL); -#endif } static PyObject *b_init_cffi_1_0_external_module(PyObject *self, PyObject *arg) @@ -205,12 +201,10 @@ static PyObject *b_init_cffi_1_0_external_module(PyObject *self, PyObject *arg) (PyObject *)lib) < 0) return NULL; -#if PY_MAJOR_VERSION >= 3 /* add manually 'module_name' in sys.modules: it seems that Py_InitModule() is not enough to do that */ if (PyDict_SetItemString(modules_dict, module_name, m) < 0) return NULL; -#endif return m; } diff --git a/src/c/cglob.c b/src/c/cglob.c index e97767c9..6c6fd4ba 100644 --- a/src/c/cglob.c +++ b/src/c/cglob.c @@ -74,7 +74,7 @@ static void *fetch_global_var_addr(GlobSupportObject *gs) } if (data == NULL) { PyErr_Format(FFIError, "global variable '%s' is at address NULL", - PyText_AS_UTF8(gs->gs_name)); + PyUnicode_AsUTF8(gs->gs_name)); return NULL; } return data; diff --git a/src/c/commontypes.c b/src/c/commontypes.c index 2337bf99..a15c3ae8 100644 --- a/src/c/commontypes.c +++ b/src/c/commontypes.c @@ -205,7 +205,7 @@ static PyObject *b__get_common_types(PyObject *self, PyObject *arg) size_t i; for (i = 0; i < num_common_simple_types; i++) { const char *s = common_simple_types[i]; - PyObject *o = PyText_FromString(s + strlen(s) + 1); + PyObject *o = PyUnicode_FromString(s + strlen(s) + 1); if (o == NULL) return NULL; err = PyDict_SetItemString(arg, s, o); diff --git a/src/c/ffi_obj.c b/src/c/ffi_obj.c index f1541466..de023b5b 100644 --- a/src/c/ffi_obj.c +++ b/src/c/ffi_obj.c @@ -183,12 +183,12 @@ static CTypeDescrObject *_ffi_type(FFIObject *ffi, PyObject *arg, /* Returns the CTypeDescrObject from the user-supplied 'arg'. Does not return a new reference! */ - if ((accept & ACCEPT_STRING) && PyText_Check(arg)) { + if ((accept & ACCEPT_STRING) && PyUnicode_Check(arg)) { PyObject *types_dict = ffi->types_builder.types_dict; PyObject *x = PyDict_GetItem(types_dict, arg); if (x == NULL) { - const char *input_text = PyText_AS_UTF8(arg); + const char *input_text = PyUnicode_AsUTF8(arg); int err, index = parse_c_type(&ffi->info, input_text); if (index < 0) return _ffi_bad_type(ffi, input_text); @@ -226,17 +226,6 @@ static CTypeDescrObject *_ffi_type(FFIObject *ffi, PyObject *arg, else if ((accept & ACCEPT_CDATA) && CData_Check(arg)) { return ((CDataObject *)arg)->c_type; } -#if PY_MAJOR_VERSION < 3 - else if (PyUnicode_Check(arg)) { - CTypeDescrObject *result; - arg = PyUnicode_AsASCIIString(arg); - if (arg == NULL) - return NULL; - result = _ffi_type(ffi, arg, accept); - Py_DECREF(arg); - return result; - } -#endif else { const char *m1 = (accept & ACCEPT_STRING) ? "string" : ""; const char *m2 = (accept & ACCEPT_CTYPE) ? "ctype object" : ""; @@ -272,7 +261,7 @@ static PyObject *ffi_sizeof(FFIObject *self, PyObject *arg) return NULL; } } - return PyInt_FromSsize_t(size); + return PyLong_FromSsize_t(size); } PyDoc_STRVAR(ffi_alignof_doc, @@ -289,7 +278,7 @@ static PyObject *ffi_alignof(FFIObject *self, PyObject *arg) align = get_alignment(ct); if (align < 0) return NULL; - return PyInt_FromLong(align); + return PyLong_FromLong(align); } PyDoc_STRVAR(ffi_typeof_doc, @@ -507,7 +496,7 @@ static PyObject *ffi_offsetof(FFIObject *self, PyObject *args) return NULL; offset += ofs1; } - return PyInt_FromSsize_t(offset); + return PyLong_FromSsize_t(offset); } PyDoc_STRVAR(ffi_addressof_doc, @@ -620,9 +609,7 @@ static PyObject *ffi_getctype(FFIObject *self, PyObject *args, PyObject *kwds) CTypeDescrObject *ct; size_t replace_with_len; static char *keywords[] = {"cdecl", "replace_with", NULL}; -#if PY_MAJOR_VERSION >= 3 PyObject *u; -#endif if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|s:getctype", keywords, &c_decl, &replace_with)) @@ -656,14 +643,12 @@ static PyObject *ffi_getctype(FFIObject *self, PyObject *args, PyObject *kwds) if (add_paren) p[replace_with_len] = ')'; -#if PY_MAJOR_VERSION >= 3 /* bytes -> unicode string */ u = PyUnicode_DecodeLatin1(PyBytes_AS_STRING(res), PyBytes_GET_SIZE(res), NULL); Py_DECREF(res); res = u; -#endif return res; } @@ -912,7 +897,7 @@ static PyObject *ffi_list_types(FFIObject *self, PyObject *noargs) goto error; for (i = 0; i < n1; i++) { - o = PyText_FromString(self->types_builder.ctx.typenames[i].name); + o = PyUnicode_FromString(self->types_builder.ctx.typenames[i].name); if (o == NULL) goto error; PyList_SET_ITEM(lst[0], i, o); @@ -926,7 +911,7 @@ static PyObject *ffi_list_types(FFIObject *self, PyObject *noargs) if (s->name[0] == '$') continue; - o = PyText_FromString(s->name); + o = PyUnicode_FromString(s->name); if (o == NULL) goto error; index = (s->flags & _CFFI_F_UNION) ? 2 : 1; @@ -971,14 +956,6 @@ PyDoc_STRVAR(ffi_init_once_doc, "of function() is done. If function() raises an exception, it is\n" "propagated and nothing is cached."); -#if PY_MAJOR_VERSION < 3 -/* PyCapsule_New is redefined to be PyCObject_FromVoidPtr in _cffi_backend, - which gives 2.6 compatibility; but the destructor signature is different */ -static void _free_init_once_lock(void *lock) -{ - PyThread_free_lock((PyThread_type_lock)lock); -} -#else static void _free_init_once_lock(PyObject *capsule) { PyThread_type_lock lock; @@ -986,7 +963,6 @@ static void _free_init_once_lock(PyObject *capsule) if (lock != NULL) PyThread_free_lock(lock); } -#endif static PyObject *ffi_init_once(FFIObject *self, PyObject *args, PyObject *kwds) { diff --git a/src/c/file_emulator.h b/src/c/file_emulator.h index 82a34c0c..bfdcdece 100644 --- a/src/c/file_emulator.h +++ b/src/c/file_emulator.h @@ -51,7 +51,7 @@ static FILE *PyFile_AsFile(PyObject *ob_file) ob_mode = PyObject_GetAttrString(ob_file, "mode"); if (ob_mode == NULL) goto fail; - mode = PyText_AsUTF8(ob_mode); + mode = PyUnicode_AsUTF8(ob_mode); if (mode == NULL) goto fail; diff --git a/src/c/lib_obj.c b/src/c/lib_obj.c index bd9ba3fc..6e41d270 100644 --- a/src/c/lib_obj.c +++ b/src/c/lib_obj.c @@ -111,8 +111,8 @@ static int lib_traverse(LibObject *lib, visitproc visit, void *arg) static PyObject *lib_repr(LibObject *lib) { - return PyText_FromFormat("", - PyText_AS_UTF8(lib->l_libname)); + return PyUnicode_FromFormat("", + PyUnicode_AsUTF8(lib->l_libname)); } static PyObject *lib_build_cpython_func(LibObject *lib, @@ -131,7 +131,7 @@ static PyObject *lib_build_cpython_func(LibObject *lib, int i, type_index = _CFFI_GETARG(g->type_op); _cffi_opcode_t *opcodes = lib->l_types_builder->ctx.types; static const char *const format = ";\n\nCFFI C function from %s.lib"; - const char *libname = PyText_AS_UTF8(lib->l_libname); + const char *libname = PyUnicode_AsUTF8(lib->l_libname); struct funcbuilder_s funcbuilder; /* return type: */ @@ -214,7 +214,7 @@ static PyObject *lib_build_and_cache_attr(LibObject *lib, PyObject *name, const struct _cffi_global_s *g; CTypeDescrObject *ct; builder_c_t *types_builder = lib->l_types_builder; - const char *s = PyText_AsUTF8(name); + const char *s = PyUnicode_AsUTF8(name); if (s == NULL) return NULL; @@ -269,7 +269,7 @@ static PyObject *lib_build_and_cache_attr(LibObject *lib, PyObject *name, PyErr_Format(PyExc_AttributeError, "cffi library '%.200s' has no function, constant " "or global variable named '%.200s'", - PyText_AS_UTF8(lib->l_libname), s); + PyUnicode_AsUTF8(lib->l_libname), s); return NULL; } @@ -465,7 +465,7 @@ static PyObject *_lib_dir1(LibObject *lib, int ignore_global_vars) if (op == _CFFI_OP_GLOBAL_VAR || op == _CFFI_OP_GLOBAL_VAR_F) continue; } - s = PyText_FromString(g[i].name); + s = PyUnicode_FromString(g[i].name); if (s == NULL) goto error; PyList_SET_ITEM(lst, count, s); @@ -489,7 +489,7 @@ static PyObject *_lib_dict(LibObject *lib) return NULL; for (i = 0; i < total; i++) { - name = PyText_FromString(g[i].name); + name = PyUnicode_FromString(g[i].name); if (name == NULL) goto error; @@ -521,7 +521,7 @@ static PyObject *lib_getattr(LibObject *lib, PyObject *name) missing: /*** ATTRIBUTEERROR IS SET HERE ***/ - p = PyText_AsUTF8(name); + p = PyUnicode_AsUTF8(name); if (p == NULL) return NULL; if (strcmp(p, "__all__") == 0) { @@ -545,16 +545,14 @@ static PyObject *lib_getattr(LibObject *lib, PyObject *name) module-like behavior */ if (strcmp(p, "__name__") == 0) { PyErr_Clear(); - return PyText_FromFormat("%s.lib", PyText_AS_UTF8(lib->l_libname)); + return PyUnicode_FromFormat("%s.lib", PyUnicode_AsUTF8(lib->l_libname)); } -#if PY_MAJOR_VERSION >= 3 if (strcmp(p, "__loader__") == 0 || strcmp(p, "__spec__") == 0) { /* some more module-like behavior hacks */ PyErr_Clear(); Py_INCREF(Py_None); return Py_None; } -#endif return NULL; } @@ -574,7 +572,7 @@ static int lib_setattr(LibObject *lib, PyObject *name, PyObject *val) PyErr_Format(PyExc_AttributeError, "cannot write to function or constant '%.200s'", - PyText_Check(name) ? PyText_AS_UTF8(name) : "?"); + PyUnicode_Check(name) ? PyUnicode_AsUTF8(name) : "?"); return -1; } @@ -632,7 +630,7 @@ static LibObject *lib_internal_new(FFIObject *ffi, const char *module_name, LibObject *lib; PyObject *libname, *dict; - libname = PyText_FromString(module_name); + libname = PyUnicode_FromString(module_name); if (libname == NULL) goto err1; @@ -699,7 +697,7 @@ static PyObject *address_of_global_var(PyObject *args) /* rebuild a string from 'varname', to do typechecks and to force a unicode back to a plain string (on python 2) */ - o_varname = PyText_FromString(varname); + o_varname = PyUnicode_FromString(varname); if (o_varname == NULL) return NULL; diff --git a/src/c/minibuffer.h b/src/c/minibuffer.h index c2956eb1..882cff70 100644 --- a/src/c/minibuffer.h +++ b/src/c/minibuffer.h @@ -50,7 +50,7 @@ static int mb_ass_item(MiniBufferObj *self, Py_ssize_t idx, PyObject *other) } else { PyErr_Format(PyExc_TypeError, - "must assign a "STR_OR_BYTES + "must assign a bytes" " of length 1, not %.200s", Py_TYPE(other)->tp_name); return -1; } @@ -85,29 +85,6 @@ static int mb_ass_slice(MiniBufferObj *self, return 0; } -#if PY_MAJOR_VERSION < 3 -static Py_ssize_t mb_getdata(MiniBufferObj *self, Py_ssize_t idx, void **pp) -{ - *pp = self->mb_data; - return self->mb_size; -} - -static Py_ssize_t mb_getsegcount(MiniBufferObj *self, Py_ssize_t *lenp) -{ - if (lenp) - *lenp = self->mb_size; - return 1; -} - -static PyObject *mb_str(MiniBufferObj *self) -{ - /* Python 2: we want str(buffer) to behave like buffer[:], because - that's what bytes(buffer) does on Python 3 and there is no way - we can prevent this. */ - return PyString_FromStringAndSize(self->mb_data, self->mb_size); -} -#endif - static int mb_getbuf(MiniBufferObj *self, Py_buffer *view, int flags) { return PyBuffer_FillInfo(view, (PyObject *)self, @@ -126,12 +103,6 @@ static PySequenceMethods mb_as_sequence = { }; static PyBufferProcs mb_as_buffer = { -#if PY_MAJOR_VERSION < 3 - (readbufferproc)mb_getdata, - (writebufferproc)mb_getdata, - (segcountproc)mb_getsegcount, - (charbufferproc)mb_getdata, -#endif (getbufferproc)mb_getbuf, (releasebufferproc)0, }; @@ -235,7 +206,6 @@ mb_richcompare(PyObject *self, PyObject *other, int op) return res; } -#if PY_MAJOR_VERSION >= 3 /* pfffffffffffff pages of copy-paste from listobject.c */ /* pfffffffffffff#2: the PySlice_GetIndicesEx() *macro* should not @@ -318,13 +288,6 @@ static PyMappingMethods mb_as_mapping = { (binaryfunc)mb_subscript, /*mp_subscript*/ (objobjargproc)mb_ass_subscript, /*mp_ass_subscript*/ }; -#endif - -#if PY_MAJOR_VERSION >= 3 -# define MINIBUF_TPFLAGS 0 -#else -# define MINIBUF_TPFLAGS (Py_TPFLAGS_HAVE_GETCHARBUFFER | Py_TPFLAGS_HAVE_NEWBUFFER) -#endif PyDoc_STRVAR(ffi_buffer_doc, "ffi.buffer(cdata[, byte_size]):\n" @@ -355,23 +318,14 @@ static PyTypeObject MiniBuffer_Type = { 0, /* tp_repr */ 0, /* tp_as_number */ &mb_as_sequence, /* tp_as_sequence */ -#if PY_MAJOR_VERSION < 3 - 0, /* tp_as_mapping */ -#else &mb_as_mapping, /* tp_as_mapping */ -#endif 0, /* tp_hash */ 0, /* tp_call */ -#if PY_MAJOR_VERSION < 3 - (reprfunc)mb_str, /* tp_str */ -#else 0, /* tp_str */ -#endif PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ &mb_as_buffer, /* tp_as_buffer */ - (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - MINIBUF_TPFLAGS), /* tp_flags */ + (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC), /* tp_flags */ ffi_buffer_doc, /* tp_doc */ (traverseproc)mb_traverse, /* tp_traverse */ (inquiry)mb_clear, /* tp_clear */ diff --git a/src/c/misc_win32.h b/src/c/misc_win32.h index f332940c..5bc134a8 100644 --- a/src/c/misc_win32.h +++ b/src/c/misc_win32.h @@ -84,7 +84,6 @@ static void restore_errno(void) /************************************************************/ -#if PY_MAJOR_VERSION >= 3 static PyObject *b_getwinerror(PyObject *self, PyObject *args, PyObject *kwds) { int err = -1; @@ -133,54 +132,6 @@ static PyObject *b_getwinerror(PyObject *self, PyObject *args, PyObject *kwds) LocalFree(s_buf); return v; } -#else -static PyObject *b_getwinerror(PyObject *self, PyObject *args, PyObject *kwds) -{ - int err = -1; - int len; - char *s; - char *s_buf = NULL; /* Free via LocalFree */ - char s_small_buf[40]; /* Room for "Windows Error 0xFFFFFFFFFFFFFFFF" */ - PyObject *v; - static char *keywords[] = {"code", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", keywords, &err)) - return NULL; - - if (err == -1) { - struct cffi_tls_s *p = get_cffi_tls(); - if (p == NULL) - return PyErr_NoMemory(); - err = p->saved_lasterror; - } - - len = FormatMessage( - /* Error API error */ - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, /* no message source */ - err, - MAKELANGID(LANG_NEUTRAL, - SUBLANG_DEFAULT), /* Default language */ - (LPTSTR) &s_buf, - 0, /* size not used */ - NULL); /* no args */ - if (len==0) { - /* Only seen this in out of mem situations */ - sprintf(s_small_buf, "Windows Error 0x%X", err); - s = s_small_buf; - } else { - s = s_buf; - /* remove trailing cr/lf and dots */ - while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.')) - s[--len] = '\0'; - } - v = Py_BuildValue("(is)", err, s); - LocalFree(s_buf); - return v; -} -#endif /************************************************************/ diff --git a/src/c/realize_c_type.c b/src/c/realize_c_type.c index d9b9f19b..98689e3e 100644 --- a/src/c/realize_c_type.c +++ b/src/c/realize_c_type.c @@ -211,13 +211,13 @@ static PyObject *realize_global_int(builder_c_t *builder, int gindex) case 0: if (value <= (unsigned long long)LONG_MAX) - return PyInt_FromLong((long)value); + return PyLong_FromLong((long)value); else return PyLong_FromUnsignedLongLong(value); case 1: if ((long long)value >= (long long)LONG_MIN) - return PyInt_FromLong((long)value); + return PyLong_FromLong((long)value); else return PyLong_FromLongLong((long long)value); @@ -501,7 +501,7 @@ realize_c_type_or_func_now(builder_c_t *builder, _cffi_opcode_t op, j = 0; while (p[j] != ',' && p[j] != '\0') j++; - tmp = PyText_FromStringAndSize(p, j); + tmp = PyUnicode_FromStringAndSize(p, j); if (tmp == NULL) break; PyTuple_SET_ITEM(enumerators, i, tmp); diff --git a/src/cffi/_cffi_errors.h b/src/cffi/_cffi_errors.h index 158e0590..0931379c 100644 --- a/src/cffi/_cffi_errors.h +++ b/src/cffi/_cffi_errors.h @@ -36,11 +36,7 @@ static PyObject *_cffi_start_error_capture(void) if (result == NULL) goto error; -#if PY_MAJOR_VERSION >= 3 bi = PyImport_ImportModule("builtins"); -#else - bi = PyImport_ImportModule("__builtin__"); -#endif if (bi == NULL) goto error; PyDict_SetItemString(result, "__builtins__", bi); @@ -81,15 +77,9 @@ static PyObject *_cffi_start_error_capture(void) static DWORD WINAPI _cffi_bootstrap_dialog(LPVOID ignored) { Sleep(666); /* may be interrupted if the whole process is closing */ -#if PY_MAJOR_VERSION >= 3 MessageBoxW(NULL, (wchar_t *)_cffi_bootstrap_text, L"Python-CFFI error", MB_OK | MB_ICONERROR); -#else - MessageBoxA(NULL, (char *)_cffi_bootstrap_text, - "Python-CFFI error", - MB_OK | MB_ICONERROR); -#endif _cffi_bootstrap_text = NULL; return 0; } @@ -111,11 +101,7 @@ static void _cffi_stop_error_capture(PyObject *ecap) /* Show a dialog box, but in a background thread, and never show multiple dialog boxes at once. */ -#if PY_MAJOR_VERSION >= 3 text = PyUnicode_AsWideCharString(s, NULL); -#else - text = PyString_AsString(s); -#endif _cffi_bootstrap_text = text; diff --git a/src/cffi/_cffi_include.h b/src/cffi/_cffi_include.h index 908a1d73..44b25d19 100644 --- a/src/cffi/_cffi_include.h +++ b/src/cffi/_cffi_include.h @@ -128,13 +128,9 @@ extern "C" { #ifndef PYPY_VERSION -#if PY_MAJOR_VERSION >= 3 -# define PyInt_FromLong PyLong_FromLong -#endif - #define _cffi_from_c_double PyFloat_FromDouble #define _cffi_from_c_float PyFloat_FromDouble -#define _cffi_from_c_long PyInt_FromLong +#define _cffi_from_c_long PyLong_FromLong #define _cffi_from_c_ulong PyLong_FromUnsignedLong #define _cffi_from_c_longlong PyLong_FromLongLong #define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong @@ -146,12 +142,12 @@ extern "C" { #define _cffi_from_c_int(x, type) \ (((type)-1) > 0 ? /* unsigned */ \ (sizeof(type) < sizeof(long) ? \ - PyInt_FromLong((long)x) : \ + PyLong_FromLong((long)x) : \ sizeof(type) == sizeof(long) ? \ PyLong_FromUnsignedLong((unsigned long)x) : \ PyLong_FromUnsignedLongLong((unsigned long long)x)) : \ (sizeof(type) <= sizeof(long) ? \ - PyInt_FromLong((long)x) : \ + PyLong_FromLong((long)x) : \ PyLong_FromLongLong((long long)x))) #define _cffi_to_c_int(o, type) \ diff --git a/src/cffi/_embedding.h b/src/cffi/_embedding.h index 40b90f2c..e0295b55 100644 --- a/src/cffi/_embedding.h +++ b/src/cffi/_embedding.h @@ -177,9 +177,6 @@ static int _cffi_initialize_python(void) if (PyDict_SetItemString(global_dict, "__builtins__", builtins) < 0) goto error; x = PyEval_EvalCode( -#if PY_MAJOR_VERSION < 3 - (PyCodeObject *) -#endif pycode, global_dict, global_dict); if (x == NULL) goto error; diff --git a/src/cffi/recompiler.py b/src/cffi/recompiler.py index 7734a348..8b263b75 100644 --- a/src/cffi/recompiler.py +++ b/src/cffi/recompiler.py @@ -317,11 +317,8 @@ def write_c_source_to_f(self, f, preamble): prnt('#ifdef PYPY_VERSION') prnt('# define _CFFI_PYTHON_STARTUP_FUNC _cffi_pypyinit_%s' % ( base_module_name,)) - prnt('#elif PY_MAJOR_VERSION >= 3') - prnt('# define _CFFI_PYTHON_STARTUP_FUNC PyInit_%s' % ( - base_module_name,)) prnt('#else') - prnt('# define _CFFI_PYTHON_STARTUP_FUNC init%s' % ( + prnt('# define _CFFI_PYTHON_STARTUP_FUNC PyInit_%s' % ( base_module_name,)) prnt('#endif') lines = self._rel_readlines('_embedding.h') @@ -429,35 +426,22 @@ def write_c_source_to_f(self, f, preamble): prnt(' }') prnt(' p[0] = (const void *)0x%x;' % self._version) prnt(' p[1] = &_cffi_type_context;') - prnt('#if PY_MAJOR_VERSION >= 3') prnt(' return NULL;') - prnt('#endif') prnt('}') # on Windows, distutils insists on putting init_cffi_xyz in # 'export_symbols', so instead of fighting it, just give up and # give it one prnt('# ifdef _MSC_VER') prnt(' PyMODINIT_FUNC') - prnt('# if PY_MAJOR_VERSION >= 3') prnt(' PyInit_%s(void) { return NULL; }' % (base_module_name,)) - prnt('# else') - prnt(' init%s(void) { }' % (base_module_name,)) - prnt('# endif') prnt('# endif') - prnt('#elif PY_MAJOR_VERSION >= 3') + prnt('#else') prnt('PyMODINIT_FUNC') prnt('PyInit_%s(void)' % (base_module_name,)) prnt('{') prnt(' return _cffi_init("%s", 0x%x, &_cffi_type_context);' % ( self.module_name, self._version)) prnt('}') - prnt('#else') - prnt('PyMODINIT_FUNC') - prnt('init%s(void)' % (base_module_name,)) - prnt('{') - prnt(' _cffi_init("%s", 0x%x, &_cffi_type_context);' % ( - self.module_name, self._version)) - prnt('}') prnt('#endif') prnt() prnt('#ifdef __GNUC__') diff --git a/src/cffi/vengine_cpy.py b/src/cffi/vengine_cpy.py index eb0b6f70..8cdfa6d6 100644 --- a/src/cffi/vengine_cpy.py +++ b/src/cffi/vengine_cpy.py @@ -102,8 +102,6 @@ def write_source_to_f(self): # standard init. modname = self.verifier.get_module_name() constants = self._chained_list_constants[False] - prnt('#if PY_MAJOR_VERSION >= 3') - prnt() prnt('static struct PyModuleDef _cffi_module_def = {') prnt(' PyModuleDef_HEAD_INIT,') prnt(' "%s",' % modname) @@ -127,21 +125,6 @@ def write_source_to_f(self): prnt(' return lib;') prnt('}') prnt() - prnt('#else') - prnt() - prnt('PyMODINIT_FUNC') - prnt('init%s(void)' % modname) - prnt('{') - prnt(' PyObject *lib;') - prnt(' lib = Py_InitModule("%s", _cffi_methods);' % modname) - prnt(' if (lib == NULL)') - prnt(' return;') - prnt(' if (%s < 0 || _cffi_init() < 0)' % (constants,)) - prnt(' return;') - prnt(' return;') - prnt('}') - prnt() - prnt('#endif') def load_library(self, flags=None): # XXX review all usages of 'self' here! @@ -870,21 +853,9 @@ def _generate_setup_custom(self): # define _cffi_double_complex_t double _Complex #endif -#if PY_MAJOR_VERSION < 3 -# undef PyCapsule_CheckExact -# undef PyCapsule_GetPointer -# define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule)) -# define PyCapsule_GetPointer(capsule, name) \ - (PyCObject_AsVoidPtr(capsule)) -#endif - -#if PY_MAJOR_VERSION >= 3 -# define PyInt_FromLong PyLong_FromLong -#endif - #define _cffi_from_c_double PyFloat_FromDouble #define _cffi_from_c_float PyFloat_FromDouble -#define _cffi_from_c_long PyInt_FromLong +#define _cffi_from_c_long PyLong_FromLong #define _cffi_from_c_ulong PyLong_FromUnsignedLong #define _cffi_from_c_longlong PyLong_FromLongLong #define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong @@ -896,21 +867,21 @@ def _generate_setup_custom(self): #define _cffi_from_c_int_const(x) \ (((x) > 0) ? \ ((unsigned long long)(x) <= (unsigned long long)LONG_MAX) ? \ - PyInt_FromLong((long)(x)) : \ + PyLong_FromLong((long)(x)) : \ PyLong_FromUnsignedLongLong((unsigned long long)(x)) : \ ((long long)(x) >= (long long)LONG_MIN) ? \ - PyInt_FromLong((long)(x)) : \ + PyLong_FromLong((long)(x)) : \ PyLong_FromLongLong((long long)(x))) #define _cffi_from_c_int(x, type) \ (((type)-1) > 0 ? /* unsigned */ \ (sizeof(type) < sizeof(long) ? \ - PyInt_FromLong((long)x) : \ + PyLong_FromLong((long)x) : \ sizeof(type) == sizeof(long) ? \ PyLong_FromUnsignedLong((unsigned long)x) : \ PyLong_FromUnsignedLongLong((unsigned long long)x)) : \ (sizeof(type) <= sizeof(long) ? \ - PyInt_FromLong((long)x) : \ + PyLong_FromLong((long)x) : \ PyLong_FromLongLong((long long)x))) #define _cffi_to_c_int(o, type) \ From db6983cc02f91a8666fb8f54d5c6cd12c47177f2 Mon Sep 17 00:00:00 2001 From: Rodrigo Tobar Date: Thu, 5 Sep 2024 23:15:23 +0800 Subject: [PATCH 02/12] Remove support for Python <3.8 from C code Similarly to the previous commit, the bulk of the work is removing code for PY_VERSION_HEX < 0x03080000, removing #if guards around PY_VERSION_HEX >= 0x03080000, and removing unnecessary macro definitions. Signed-off-by: Rodrigo Tobar --- src/c/_cffi_backend.c | 68 +++----------------------------------- src/c/call_python.c | 13 -------- src/c/minibuffer.h | 7 ---- src/c/misc_thread_common.h | 10 +----- src/cffi/_embedding.h | 35 -------------------- 5 files changed, 6 insertions(+), 127 deletions(-) diff --git a/src/c/_cffi_backend.c b/src/c/_cffi_backend.c index 8de8c8e1..1d504406 100644 --- a/src/c/_cffi_backend.c +++ b/src/c/_cffi_backend.c @@ -141,20 +141,10 @@ #include "malloc_closure.h" -#if PY_VERSION_HEX >= 0x03030000 -# define PyText_GetSize PyUnicode_GetLength -#else -# define PyText_GetSize PyUnicode_GetSize -#endif - #if PY_VERSION_HEX < 0x030900a4 # define Py_SET_REFCNT(obj, val) (Py_REFCNT(obj) = (val)) #endif -#if PY_VERSION_HEX >= 0x03080000 -# define USE_WRITEUNRAISABLEMSG -#endif - /************************************************************/ /* base type flag: exactly one of the following: */ @@ -4431,7 +4421,7 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, if (*p_printable_filename == NULL) return NULL; - sz1 = PyText_GetSize(filename_unicode) + 1; + sz1 = PyUnicode_GetLength(filename_unicode) + 1; sz1 *= 2; /* should not be needed, but you never know */ w1 = alloca(sizeof(wchar_t) * sz1); sz1 = PyUnicode_AsWideChar(filename_unicode, @@ -5141,7 +5131,7 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) if (!(sflags & SF_GCC_ARM_BITFIELDS) && fbitsize >= 0) { if (!(sflags & SF_MSVC_BITFIELDS)) { /* GCC: anonymous bitfields (of any size) don't cause alignment */ - do_align = PyText_GetSize(fname) > 0; + do_align = PyUnicode_GetLength(fname) > 0; } else { /* MSVC: zero-sized bitfields don't cause alignment */ @@ -5185,7 +5175,7 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) byteoffset = foffset; } - if (PyText_GetSize(fname) == 0 && + if (PyUnicode_GetLength(fname) == 0 && ftype->ct_flags & (CT_STRUCT|CT_UNION)) { /* a nested anonymous struct or union */ CFieldObject *cfsrc = (CFieldObject *)ftype->ct_extra; @@ -5256,7 +5246,7 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) field_offset_bytes &= ~(falign - 1); if (fbitsize == 0) { - if (PyText_GetSize(fname) > 0) { + if (PyUnicode_GetLength(fname) > 0) { PyErr_Format(PyExc_TypeError, "field '%s.%s' is declared with :0", ct->ct_name, PyUnicode_AsUTF8(fname)); @@ -5345,7 +5335,7 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args) if (sflags & SF_GCC_BIG_ENDIAN) bitshift = 8 * ftype->ct_size - fbitsize - bitshift; - if (PyText_GetSize(fname) > 0) { + if (PyUnicode_GetLength(fname) > 0) { *previous = _add_field(interned_fields, fname, ftype, field_offset_bytes, bitshift, fbitsize, @@ -6000,7 +5990,6 @@ static void _my_PyErr_WriteUnraisable(PyObject *t, PyObject *v, PyObject *tb, char *extra_error_line) { /* like PyErr_WriteUnraisable(), but write a full traceback */ -#ifdef USE_WRITEUNRAISABLEMSG /* PyErr_WriteUnraisable actually writes the full traceback anyway from Python 3.4, but we can't really get the formatting of the @@ -6037,34 +6026,6 @@ static void _my_PyErr_WriteUnraisable(PyObject *t, PyObject *v, PyObject *tb, else PyErr_WriteUnraisable(obj); /* best effort */ PyErr_Clear(); - -#else - - /* version for Python 2.7 and < 3.8 */ - PyObject *f; - /* jump through hoops to ensure the tb is attached to v, on Python 3 */ - PyErr_NormalizeException(&t, &v, &tb); - if (tb == NULL) { - tb = Py_None; - Py_INCREF(tb); - } - PyException_SetTraceback(v, tb); - f = PySys_GetObject("stderr"); - if (f != NULL) { - if (obj != NULL) { - PyFile_WriteString(objdescr, f); - PyFile_WriteObject(obj, f, 0); - PyFile_WriteString(":\n", f); - } - if (extra_error_line != NULL) - PyFile_WriteString(extra_error_line, f); - PyErr_Display(t, v, tb); - } - Py_XDECREF(t); - Py_XDECREF(v); - Py_XDECREF(tb); - -#endif } static void general_invoke_callback(int decode_args_from_libffi, @@ -6114,11 +6075,7 @@ static void general_invoke_callback(int decode_args_from_libffi, goto error; if (convert_from_object_fficallback(result, SIGNATURE(1), py_res, decode_args_from_libffi) < 0) { -#ifdef USE_WRITEUNRAISABLEMSG extra_error_line = ", trying to convert the result back to C"; -#else - extra_error_line = "Trying to convert the result back to C:\n"; -#endif goto error; } done: @@ -6170,16 +6127,9 @@ static void general_invoke_callback(int decode_args_from_libffi, _my_PyErr_WriteUnraisable(exc1, val1, tb1, "From cffi callback ", py_ob, extra_error_line); -#ifdef USE_WRITEUNRAISABLEMSG _my_PyErr_WriteUnraisable(exc2, val2, tb2, "during handling of the above exception by 'onerror'", NULL, NULL); -#else - extra_error_line = ("\nDuring the call to 'onerror', " - "another exception occurred:\n\n"); - _my_PyErr_WriteUnraisable(exc2, val2, tb2, - NULL, NULL, extra_error_line); -#endif _cffi_stop_error_capture(ecap); } } @@ -6247,14 +6197,6 @@ static PyObject *prepare_callback_info_tuple(CTypeDescrObject *ct, infotuple = Py_BuildValue("OOOO", ct, ob, py_rawerr, onerror_ob); Py_DECREF(py_rawerr); -#if defined(WITH_THREAD) && PY_VERSION_HEX < 0x03070000 - /* We must setup the GIL here, in case the callback is invoked in - some other non-Pythonic thread. This is the same as ctypes. - But PyEval_InitThreads() is always a no-op from CPython 3.7 - (the call from ctypes was removed some time later I think). */ - PyEval_InitThreads(); -#endif - return infotuple; } diff --git a/src/c/call_python.c b/src/c/call_python.c index 58d9c23a..db9e1253 100644 --- a/src/c/call_python.c +++ b/src/c/call_python.c @@ -1,16 +1,7 @@ -#if PY_VERSION_HEX >= 0x03080000 -# define HAVE_PYINTERPSTATE_GETDICT -#endif - - static PyObject *_current_interp_key(void) { PyInterpreterState *interp = PyThreadState_GET()->interp; -#ifdef HAVE_PYINTERPSTATE_GETDICT return PyInterpreterState_GetDict(interp); /* shared reference */ -#else - return interp->modules; -#endif } static PyObject *_get_interpstate_dict(void) @@ -33,11 +24,7 @@ static PyObject *_get_interpstate_dict(void) } interp = tstate->interp; -#ifdef HAVE_PYINTERPSTATE_GETDICT interpdict = PyInterpreterState_GetDict(interp); /* shared reference */ -#else - interpdict = interp->builtins; -#endif if (interpdict == NULL) { /* subinterpreter was cleared already, or is being cleared right now, to a point that is too much for us to continue */ diff --git a/src/c/minibuffer.h b/src/c/minibuffer.h index 882cff70..414c9cc0 100644 --- a/src/c/minibuffer.h +++ b/src/c/minibuffer.h @@ -208,13 +208,6 @@ mb_richcompare(PyObject *self, PyObject *other, int op) /* pfffffffffffff pages of copy-paste from listobject.c */ -/* pfffffffffffff#2: the PySlice_GetIndicesEx() *macro* should not - be called, because C extension modules compiled with it differ - on ABI between 3.6.0, 3.6.1 and 3.6.2. */ -#if PY_VERSION_HEX < 0x03070000 && defined(PySlice_GetIndicesEx) && !defined(PYPY_VERSION) -#undef PySlice_GetIndicesEx -#endif - static PyObject *mb_subscript(MiniBufferObj *self, PyObject *item) { if (PyIndex_Check(item)) { diff --git a/src/c/misc_thread_common.h b/src/c/misc_thread_common.h index 7d29634b..2823665e 100644 --- a/src/c/misc_thread_common.h +++ b/src/c/misc_thread_common.h @@ -325,20 +325,12 @@ static void restore_errno_only(void) It was added in 3.5.2 but should never be used in 3.5.x because it is not available in 3.5.0 or 3.5.1. */ -#if PY_VERSION_HEX >= 0x03050100 && PY_VERSION_HEX < 0x03060000 -PyAPI_DATA(void *volatile) _PyThreadState_Current; -#endif - static PyThreadState *get_current_ts(void) { #if PY_VERSION_HEX >= 0x030D0000 return PyThreadState_GetUnchecked(); -#elif PY_VERSION_HEX >= 0x03060000 - return _PyThreadState_UncheckedGet(); -#elif defined(_Py_atomic_load_relaxed) - return (PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current); #else - return (PyThreadState*)_PyThreadState_Current; /* assume atomic read */ + return _PyThreadState_UncheckedGet(); #endif } diff --git a/src/cffi/_embedding.h b/src/cffi/_embedding.h index e0295b55..93af3c6c 100644 --- a/src/cffi/_embedding.h +++ b/src/cffi/_embedding.h @@ -244,10 +244,6 @@ static int _cffi_initialize_python(void) goto done; } -#if PY_VERSION_HEX < 0x03080000 -PyAPI_DATA(char *) _PyParser_TokenNames[]; /* from CPython */ -#endif - static int _cffi_carefully_make_gil(void) { /* This does the basic initialization of Python. It can be called @@ -292,27 +288,6 @@ static int _cffi_carefully_make_gil(void) */ #ifdef WITH_THREAD -# if PY_VERSION_HEX < 0x03080000 - char *volatile *lock = (char *volatile *)_PyParser_TokenNames; - char *old_value, *locked_value; - - while (1) { /* spin loop */ - old_value = *lock; - locked_value = old_value + 1; - if (old_value[0] == 'E') { - assert(old_value[1] == 'N'); - if (cffi_compare_and_swap(lock, old_value, locked_value)) - break; - } - else { - assert(old_value[0] == 'N'); - /* should ideally do a spin loop instruction here, but - hard to do it portably and doesn't really matter I - think: PyEval_InitThreads() should be very fast, and - this is only run at start-up anyway. */ - } - } -# else # if PY_VERSION_HEX < 0x030C0000 int volatile *lock = (int volatile *)&PyCapsule_Type.tp_version_tag; int old_value, locked_value = -42; @@ -345,26 +320,16 @@ static int _cffi_carefully_make_gil(void) this is only run at start-up anyway. */ } } -# endif #endif /* call Py_InitializeEx() */ if (!Py_IsInitialized()) { _cffi_py_initialize(); -#if PY_VERSION_HEX < 0x03070000 - PyEval_InitThreads(); -#endif PyEval_SaveThread(); /* release the GIL */ /* the returned tstate must be the one that has been stored into the autoTLSkey by _PyGILState_Init() called from Py_Initialize(). */ } else { -#if PY_VERSION_HEX < 0x03070000 - /* PyEval_InitThreads() is always a no-op from CPython 3.7 */ - PyGILState_STATE state = PyGILState_Ensure(); - PyEval_InitThreads(); - PyGILState_Release(state); -#endif } #ifdef WITH_THREAD From 2631a8cc3b80dd951169acf83d15dfb8d16a92fe Mon Sep 17 00:00:00 2001 From: Rodrigo Tobar Date: Thu, 5 Sep 2024 16:04:43 +0800 Subject: [PATCH 03/12] Move fast fail on win32 closer to its cause The block was previously at the bottom of the function, making it a bit more difficult to follow the overall logic of the function. Moving this win32-specific error to the specific scope where it is triggered on should make it less confusing. Signed-off-by: Rodrigo Tobar --- src/c/_cffi_backend.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/c/_cffi_backend.c b/src/c/_cffi_backend.c index 1d504406..517e865e 100644 --- a/src/c/_cffi_backend.c +++ b/src/c/_cffi_backend.c @@ -4379,12 +4379,17 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, *auto_close = 1; if (PyTuple_GET_SIZE(args) == 0 || PyTuple_GET_ITEM(args, 0) == Py_None) { +#ifdef MS_WIN32 + PyErr_SetString(PyExc_OSError, "dlopen(None) not supported on Windows"); + return NULL; +#else PyObject *dummy; if (!PyArg_ParseTuple(args, "|Oi:load_library", &dummy, &flags)) return NULL; filename_or_null = NULL; *p_printable_filename = ""; +#endif } else if (CData_Check(PyTuple_GET_ITEM(args, 0))) { @@ -4446,13 +4451,6 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, if ((flags & (RTLD_NOW | RTLD_LAZY)) == 0) flags |= RTLD_NOW; -#ifdef MS_WIN32 - if (filename_or_null == NULL) { - PyErr_SetString(PyExc_OSError, "dlopen(None) not supported on Windows"); - return NULL; - } -#endif - handle = dlopen(filename_or_null, flags); PyMem_Free(filename_or_null); From 7932c3a117d8cad42180e742d8b5a2ac410bb6b4 Mon Sep 17 00:00:00 2001 From: Rodrigo Tobar Date: Thu, 5 Sep 2024 16:10:08 +0800 Subject: [PATCH 04/12] Refactor handle error handling into function This avoid the need to use a goto statement and a win32 ifdef, making the logic a tad more difficult to follow. Signed-off-by: Rodrigo Tobar --- src/c/_cffi_backend.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/c/_cffi_backend.c b/src/c/_cffi_backend.c index 517e865e..057f3e80 100644 --- a/src/c/_cffi_backend.c +++ b/src/c/_cffi_backend.c @@ -4364,6 +4364,17 @@ static PyTypeObject dl_type = { dl_methods, /* tp_methods */ }; +static void *b_handle_or_error(void *handle, const char *printable_filename) +{ + if (handle == NULL) { + const char *error = dlerror(); + PyErr_Format(PyExc_OSError, "cannot load library '%s': %s", + printable_filename, error); + return NULL; + } + return handle; +} + static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, PyObject **p_temp, int *auto_close) { @@ -4435,7 +4446,7 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, return NULL; w1[sz1] = 0; handle = dlopenWinW(w1, flags); - goto got_handle; + return b_handle_or_error(handle, p_printable_filename); } PyErr_Clear(); #endif @@ -4454,16 +4465,7 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, handle = dlopen(filename_or_null, flags); PyMem_Free(filename_or_null); -#ifdef MS_WIN32 - got_handle: -#endif - if (handle == NULL) { - const char *error = dlerror(); - PyErr_Format(PyExc_OSError, "cannot load library '%s': %s", - *p_printable_filename, error); - return NULL; - } - return handle; + return b_handle_or_error(handle, *p_printable_filename); } static PyObject *b_load_library(PyObject *self, PyObject *args) From 288318e88fed2d119f2af576ca85c327061dd0c4 Mon Sep 17 00:00:00 2001 From: Rodrigo Tobar Date: Fri, 6 Sep 2024 10:29:37 +0800 Subject: [PATCH 05/12] Clarify encoding of p_printable_filename It's always UTF8-encoded, so there's no need for "maybe". Signed-off-by: Rodrigo Tobar --- src/c/_cffi_backend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/c/_cffi_backend.c b/src/c/_cffi_backend.c index 057f3e80..3501577c 100644 --- a/src/c/_cffi_backend.c +++ b/src/c/_cffi_backend.c @@ -4380,7 +4380,7 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, { /* Logic to call the correct version of dlopen(). Returns NULL in case of error. Otherwise, '*p_printable_filename' will point to a printable char version of - the filename (maybe utf-8-encoded). '*p_temp' will be set either to NULL or + the filename (utf-8-encoded). '*p_temp' will be set either to NULL or to a temporary object that must be freed after looking at printable_filename. */ void *handle; From 7d53c3a370ef24743334c1d329fe9c5f1df8314f Mon Sep 17 00:00:00 2001 From: Rodrigo Tobar Date: Fri, 6 Sep 2024 10:42:19 +0800 Subject: [PATCH 06/12] Split win32-specific dlopen logic This is so it's a bit easier to follow, and to allow easier refactoring of the higher-level function later on. Signed-off-by: Rodrigo Tobar --- src/c/_cffi_backend.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/c/_cffi_backend.c b/src/c/_cffi_backend.c index 3501577c..0714f480 100644 --- a/src/c/_cffi_backend.c +++ b/src/c/_cffi_backend.c @@ -4375,6 +4375,25 @@ static void *b_handle_or_error(void *handle, const char *printable_filename) return handle; } +#ifdef MS_WIN32 +static void *b_do_dlopen_win32(PyObject *filename_unicode, int flags, const char *printable_filename) +{ + Py_ssize_t sz1; + wchar_t *w1; + + sz1 = PyUnicode_GetLength(filename_unicode) + 1; + sz1 *= 2; /* should not be needed, but you never know */ + w1 = alloca(sizeof(wchar_t) * sz1); + sz1 = PyUnicode_AsWideChar(filename_unicode, + w1, sz1 - 1); + if (sz1 < 0) + return NULL; + w1[sz1] = 0; + void *handle = dlopenWinW(w1, flags); + return b_handle_or_error(handle, printable_filename); +} +#endif + static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, PyObject **p_temp, int *auto_close) { @@ -4431,22 +4450,10 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, PyObject *filename_unicode; if (PyArg_ParseTuple(args, "U|i:load_library", &filename_unicode, &flags)) { - Py_ssize_t sz1; - wchar_t *w1; *p_printable_filename = PyUnicode_AsUTF8(s); if (*p_printable_filename == NULL) return NULL; - - sz1 = PyUnicode_GetLength(filename_unicode) + 1; - sz1 *= 2; /* should not be needed, but you never know */ - w1 = alloca(sizeof(wchar_t) * sz1); - sz1 = PyUnicode_AsWideChar(filename_unicode, - w1, sz1 - 1); - if (sz1 < 0) - return NULL; - w1[sz1] = 0; - handle = dlopenWinW(w1, flags); - return b_handle_or_error(handle, p_printable_filename); + return b_do_dlopen_win32(filename_unicode, flags, *p_printable_filename); } PyErr_Clear(); #endif From cd3cac61c61286ece755fbe44cd716d1c1c614df Mon Sep 17 00:00:00 2001 From: Rodrigo Tobar Date: Fri, 6 Sep 2024 11:06:55 +0800 Subject: [PATCH 07/12] Split posix-specific dlopen logic This allows us to have an quick return in the dlopen(None) case instead of having to follow the main main b_dlopen function all the way to the end. Signed-off-by: Rodrigo Tobar --- src/c/_cffi_backend.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/c/_cffi_backend.c b/src/c/_cffi_backend.c index 0714f480..a65b9e07 100644 --- a/src/c/_cffi_backend.c +++ b/src/c/_cffi_backend.c @@ -4375,6 +4375,15 @@ static void *b_handle_or_error(void *handle, const char *printable_filename) return handle; } +static void *b_do_dlopen_posix(const char *filename_or_null, int flags, const char *printable_filename) +{ + if ((flags & (RTLD_NOW | RTLD_LAZY)) == 0) + flags |= RTLD_NOW; + + void *handle = dlopen(filename_or_null, flags); + return b_handle_or_error(handle, printable_filename); +} + #ifdef MS_WIN32 static void *b_do_dlopen_win32(PyObject *filename_unicode, int flags, const char *printable_filename) { @@ -4417,8 +4426,8 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, if (!PyArg_ParseTuple(args, "|Oi:load_library", &dummy, &flags)) return NULL; - filename_or_null = NULL; *p_printable_filename = ""; + return b_do_dlopen_posix(NULL, flags, *p_printable_filename); #endif } else if (CData_Check(PyTuple_GET_ITEM(args, 0))) @@ -4466,13 +4475,9 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, return NULL; } } - if ((flags & (RTLD_NOW | RTLD_LAZY)) == 0) - flags |= RTLD_NOW; - - handle = dlopen(filename_or_null, flags); + handle = b_do_dlopen_posix(filename_or_null, flags, *p_printable_filename); PyMem_Free(filename_or_null); - - return b_handle_or_error(handle, *p_printable_filename); + return handle; } static PyObject *b_load_library(PyObject *self, PyObject *args) From 28003b01ea7eec08d1cc02302f0c74efdca01d9e Mon Sep 17 00:00:00 2001 From: Rodrigo Tobar Date: Fri, 6 Sep 2024 11:33:42 +0800 Subject: [PATCH 08/12] Perform filesystem encoding manually on filename In python 3.12 the Py_FileSystemDefaultEncoding global variable has been deprecated. This was used in combination with a "et" PyArgs format specifier to get a raw C string with the encoded bytes for the input filename. This commit replaces the usage of Py_FileSystemDefaultEncoding with a manual call to PyUnicode_EncodeFSDefault instead (only within b_do_dlopen_posix). This function requires a unicode object as an input, and therefore we now need to accept the argument with the "U" format specifier. While this is a departure from the "et" specifier, which accepts not only strings, but also bytes and bytearrays, this is inconsequential, since the higher-level cffi API already ensures we get a string object here. Moreover, we were already calling PyUnicode_AsUTF8 on it, which would have failed if we received bytes. Thus this new constrain is fine. With this change there's no need anymore to keep around the raw C pointer in the b_do_dlopen() function, and it can be moved down to b_do_dlopen_posix(), where it doensn't need to be freed (as it's now taken from a PyBytes object via PyBytes_AsString). We can also now remove the unnecessary "s" variable since the filename_unicode variable (previously used only in the win32 case, now always) holds the same value. --- src/c/_cffi_backend.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/c/_cffi_backend.c b/src/c/_cffi_backend.c index a65b9e07..ee2ac982 100644 --- a/src/c/_cffi_backend.c +++ b/src/c/_cffi_backend.c @@ -4375,12 +4375,21 @@ static void *b_handle_or_error(void *handle, const char *printable_filename) return handle; } -static void *b_do_dlopen_posix(const char *filename_or_null, int flags, const char *printable_filename) +static void *b_do_dlopen_posix(PyObject *filename_unicode, int flags, const char *printable_filename) { + char *filename_or_null = NULL; + PyObject *filename_bytes = NULL; + if (filename_unicode) { + filename_bytes = PyUnicode_EncodeFSDefault(filename_unicode); + if (filename_bytes == NULL) + return NULL; + filename_or_null = PyBytes_AsString(filename_bytes); + } if ((flags & (RTLD_NOW | RTLD_LAZY)) == 0) flags |= RTLD_NOW; void *handle = dlopen(filename_or_null, flags); + Py_XDECREF(filename_bytes); return b_handle_or_error(handle, printable_filename); } @@ -4412,7 +4421,6 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, to a temporary object that must be freed after looking at printable_filename. */ void *handle; - char *filename_or_null; int flags = 0; *p_temp = NULL; *auto_close = 1; @@ -4454,30 +4462,25 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, } else { - PyObject *s = PyTuple_GET_ITEM(args, 0); -#ifdef MS_WIN32 PyObject *filename_unicode; +#ifdef MS_WIN32 if (PyArg_ParseTuple(args, "U|i:load_library", &filename_unicode, &flags)) { - *p_printable_filename = PyUnicode_AsUTF8(s); + *p_printable_filename = PyUnicode_AsUTF8(filename_unicode); if (*p_printable_filename == NULL) return NULL; return b_do_dlopen_win32(filename_unicode, flags, *p_printable_filename); } PyErr_Clear(); #endif - if (!PyArg_ParseTuple(args, "et|i:load_library", - Py_FileSystemDefaultEncoding, &filename_or_null, &flags)) + if (!PyArg_ParseTuple(args, "U|i:load_library", &filename_unicode, &flags)) return NULL; - *p_printable_filename = PyUnicode_AsUTF8(s); + *p_printable_filename = PyUnicode_AsUTF8(filename_unicode); if (*p_printable_filename == NULL) { - PyMem_Free(filename_or_null); return NULL; } + return b_do_dlopen_posix(filename_unicode, flags, *p_printable_filename); } - handle = b_do_dlopen_posix(filename_or_null, flags, *p_printable_filename); - PyMem_Free(filename_or_null); - return handle; } static PyObject *b_load_library(PyObject *self, PyObject *args) From ff200b8b406d36978796aed7fd942caba090aea2 Mon Sep 17 00:00:00 2001 From: Rodrigo Tobar Date: Fri, 6 Sep 2024 12:26:47 +0800 Subject: [PATCH 09/12] Unify common logic for dlopen(str) With the clarity that the input filename has to be a str object at this stage, we can now bring together the common logic that the win32 and posix branches took. Notice how the win32 implementation previously clearer the error if PyArgs_ParseTuple failed, only to try again with the "et" format variant (now "U" as per the previous commit). As noted in the previous comment this was moot, both because the filename argument is guaranteed to be a string at this point, and because it was used in PyUnicode_AsUTF8, which would have failed if it wasn't given a str object. Signed-off-by: Rodrigo Tobar --- src/c/_cffi_backend.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/c/_cffi_backend.c b/src/c/_cffi_backend.c index ee2ac982..e5831390 100644 --- a/src/c/_cffi_backend.c +++ b/src/c/_cffi_backend.c @@ -4463,23 +4463,17 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, else { PyObject *filename_unicode; -#ifdef MS_WIN32 - if (PyArg_ParseTuple(args, "U|i:load_library", &filename_unicode, &flags)) - { - *p_printable_filename = PyUnicode_AsUTF8(filename_unicode); - if (*p_printable_filename == NULL) - return NULL; - return b_do_dlopen_win32(filename_unicode, flags, *p_printable_filename); - } - PyErr_Clear(); -#endif if (!PyArg_ParseTuple(args, "U|i:load_library", &filename_unicode, &flags)) return NULL; *p_printable_filename = PyUnicode_AsUTF8(filename_unicode); if (*p_printable_filename == NULL) { return NULL; } +#ifdef MS_WIN32 + return b_do_dlopen_win32(filename_unicode, flags, *p_printable_filename); +#else return b_do_dlopen_posix(filename_unicode, flags, *p_printable_filename); +#endif } } From 7c4799ade7d21578d6e95aa64675e43958b45a71 Mon Sep 17 00:00:00 2001 From: Rodrigo Tobar Date: Fri, 6 Sep 2024 12:34:48 +0800 Subject: [PATCH 10/12] Move win32-specific behaviour to b_do_dlopen_win32 Signed-off-by: Rodrigo Tobar --- src/c/_cffi_backend.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/c/_cffi_backend.c b/src/c/_cffi_backend.c index e5831390..8c0ed31c 100644 --- a/src/c/_cffi_backend.c +++ b/src/c/_cffi_backend.c @@ -4396,6 +4396,10 @@ static void *b_do_dlopen_posix(PyObject *filename_unicode, int flags, const char #ifdef MS_WIN32 static void *b_do_dlopen_win32(PyObject *filename_unicode, int flags, const char *printable_filename) { + if (filename_unicode == NULL) { + PyErr_SetString(PyExc_OSError, "dlopen(None) not supported on Windows"); + return NULL; + } Py_ssize_t sz1; wchar_t *w1; @@ -4426,15 +4430,14 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, *auto_close = 1; if (PyTuple_GET_SIZE(args) == 0 || PyTuple_GET_ITEM(args, 0) == Py_None) { -#ifdef MS_WIN32 - PyErr_SetString(PyExc_OSError, "dlopen(None) not supported on Windows"); - return NULL; -#else PyObject *dummy; if (!PyArg_ParseTuple(args, "|Oi:load_library", &dummy, &flags)) return NULL; *p_printable_filename = ""; +#ifdef MS_WIN32 + return b_do_dlopen_win32(NULL, flags, *p_printable_filename); +#else return b_do_dlopen_posix(NULL, flags, *p_printable_filename); #endif } From 1c40835fbe510088bdb188c0ef5dcdcc4d934980 Mon Sep 17 00:00:00 2001 From: Rodrigo Tobar Date: Fri, 6 Sep 2024 12:35:32 +0800 Subject: [PATCH 11/12] Add b_do_dlopen_dispatch This way the higher-level b_do_dlopen function now doesn't have to worry about OS-specific logic, and can concentrate on dealing with the different types of arguments instead. Signed-off-by: Rodrigo Tobar --- src/c/_cffi_backend.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/c/_cffi_backend.c b/src/c/_cffi_backend.c index 8c0ed31c..dd13d598 100644 --- a/src/c/_cffi_backend.c +++ b/src/c/_cffi_backend.c @@ -4416,6 +4416,15 @@ static void *b_do_dlopen_win32(PyObject *filename_unicode, int flags, const char } #endif +static void *b_do_dlopen_dispatch(PyObject *filename_unicode, int flags, const char *printable_filename) +{ +#ifdef MS_WIN32 + return b_do_dlopen_win32(filename_unicode, flags, printable_filename); +#else + return b_do_dlopen_posix(filename_unicode, flags, printable_filename); +#endif +} + static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, PyObject **p_temp, int *auto_close) { @@ -4435,11 +4444,7 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, &dummy, &flags)) return NULL; *p_printable_filename = ""; -#ifdef MS_WIN32 - return b_do_dlopen_win32(NULL, flags, *p_printable_filename); -#else - return b_do_dlopen_posix(NULL, flags, *p_printable_filename); -#endif + return b_do_dlopen_dispatch(NULL, flags, *p_printable_filename); } else if (CData_Check(PyTuple_GET_ITEM(args, 0))) { @@ -4472,11 +4477,7 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, if (*p_printable_filename == NULL) { return NULL; } -#ifdef MS_WIN32 - return b_do_dlopen_win32(filename_unicode, flags, *p_printable_filename); -#else - return b_do_dlopen_posix(filename_unicode, flags, *p_printable_filename); -#endif + return b_do_dlopen_dispatch(filename_unicode, flags, *p_printable_filename); } } From bbc263ec7da09a986d8bbf228eb56b0818131613 Mon Sep 17 00:00:00 2001 From: Rodrigo Tobar Date: Fri, 6 Sep 2024 12:36:30 +0800 Subject: [PATCH 12/12] Simplify argument parsing logic Instead of having different flavours of PyArgs_ParseTuple we can instead use a single one where all arguments are optional, then check the type of the first argument (when present). The main difference in this new implementation is that instead of raising a TypeError if the argument is not a str object in the final case, we simply assert it, making it clear that the higher-level API that calls us ensures this is the case. Signed-off-by: Rodrigo Tobar --- src/c/_cffi_backend.c | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/src/c/_cffi_backend.c b/src/c/_cffi_backend.c index dd13d598..6a4e218c 100644 --- a/src/c/_cffi_backend.c +++ b/src/c/_cffi_backend.c @@ -4433,24 +4433,22 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, the filename (utf-8-encoded). '*p_temp' will be set either to NULL or to a temporary object that must be freed after looking at printable_filename. */ - void *handle; + PyObject *filename = NULL; int flags = 0; *p_temp = NULL; *auto_close = 1; - - if (PyTuple_GET_SIZE(args) == 0 || PyTuple_GET_ITEM(args, 0) == Py_None) { - PyObject *dummy; - if (!PyArg_ParseTuple(args, "|Oi:load_library", - &dummy, &flags)) - return NULL; + + if (!PyArg_ParseTuple(args, "|Oi:load_library", &filename, &flags)) + return NULL; + + if (filename == NULL || filename == Py_None) { *p_printable_filename = ""; return b_do_dlopen_dispatch(NULL, flags, *p_printable_filename); } - else if (CData_Check(PyTuple_GET_ITEM(args, 0))) + + if (CData_Check(filename)) { - CDataObject *cd; - if (!PyArg_ParseTuple(args, "O|i:load_library", &cd, &flags)) - return NULL; + CDataObject *cd = (CDataObject *)filename; /* 'flags' is accepted but ignored in this case */ if ((cd->c_type->ct_flags & CT_IS_VOID_PTR) == 0) { PyErr_Format(PyExc_TypeError, @@ -4458,7 +4456,7 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, cd->c_type->ct_name); return NULL; } - handle = cd->c_data; + void *handle = cd->c_data; if (handle == NULL) { PyErr_Format(PyExc_RuntimeError, "cannot call dlopen(NULL)"); return NULL; @@ -4468,17 +4466,13 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, *auto_close = 0; return handle; } - else - { - PyObject *filename_unicode; - if (!PyArg_ParseTuple(args, "U|i:load_library", &filename_unicode, &flags)) - return NULL; - *p_printable_filename = PyUnicode_AsUTF8(filename_unicode); - if (*p_printable_filename == NULL) { - return NULL; - } - return b_do_dlopen_dispatch(filename_unicode, flags, *p_printable_filename); + + assert(PyUnicode_Check(filename)); + *p_printable_filename = PyUnicode_AsUTF8(filename); + if (*p_printable_filename == NULL) { + return NULL; } + return b_do_dlopen_dispatch(filename, flags, *p_printable_filename); } static PyObject *b_load_library(PyObject *self, PyObject *args)