mirror of https://github.com/swig/swig
Replace use of tp_name in builtin wrappers for Py_LIMITED_API support
Add SWIG_PyType_GetFullyQualifiedName which is just a wrapper around PyType_GetFullyQualifiedName, but is only available in python-3.13. Code up the equivalent for earlier versions - loosely based on the python-3.13 implementation. PyType_GetFullyQualifiedName is recommended in PEP-737 for getting the fully qualified type name of a type.
This commit is contained in:
parent
5ea4449c3e
commit
af6120329c
|
@ -81,6 +81,7 @@ CPP_TEST_CASES += \
|
|||
python_strict_unicode \
|
||||
python_threads \
|
||||
python_typemap_macro \
|
||||
python_various \
|
||||
simutry \
|
||||
std_containers \
|
||||
swigobject \
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
from python_various import *
|
||||
import datetime
|
||||
import sys
|
||||
|
||||
class MyClass:
|
||||
pass
|
||||
|
||||
# Only implemented for python 3
|
||||
if sys.version_info[0:2] < (3, 0):
|
||||
exit(0)
|
||||
|
||||
type = GetFullyQualifiedName(1234) # Test builtins type
|
||||
if type != "int":
|
||||
raise RuntimeError("wrong type {}".format(type))
|
||||
|
||||
type = GetFullyQualifiedName(MyClass()) # Test __main__ type
|
||||
if type != "MyClass":
|
||||
raise RuntimeError("wrong type {}".format(type))
|
||||
|
||||
type = GetFullyQualifiedName(WrappedClass()) # Test a SWIG wrapped class
|
||||
if type != "python_various.WrappedClass":
|
||||
raise RuntimeError("wrong type {}".format(type))
|
||||
|
||||
type = GetFullyQualifiedName(datetime.date(2020, 1, 20)) # Test a Python standard library class
|
||||
if type != "datetime.date":
|
||||
raise RuntimeError("wrong type {}".format(type))
|
|
@ -0,0 +1,14 @@
|
|||
%module python_various
|
||||
|
||||
%inline %{
|
||||
struct WrappedClass {};
|
||||
|
||||
// A unit test for SWIG_PyType_GetFullyQualifiedName
|
||||
PyObject *GetFullyQualifiedName(PyObject *type) {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
return SWIG_PyType_GetFullyQualifiedName(Py_TYPE(type));
|
||||
#else
|
||||
return type;
|
||||
#endif
|
||||
}
|
||||
%}
|
|
@ -32,7 +32,13 @@ SWIG_PyNumber_AsPyHash(PyObject *obj) {
|
|||
|
||||
SWIGINTERN int
|
||||
SwigPyBuiltin_BadInit(PyObject *self, PyObject *SWIGUNUSEDPARM(args), PyObject *SWIGUNUSEDPARM(kwds)) {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(Py_TYPE(self));
|
||||
PyErr_Format(PyExc_TypeError, "Cannot create new instances of type '%S'", tpname);
|
||||
SWIG_Py_DECREF(tpname);
|
||||
#else
|
||||
PyErr_Format(PyExc_TypeError, "Cannot create new instances of type '%s'", Py_TYPE(self)->tp_name);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -40,7 +46,13 @@ SWIGINTERN void
|
|||
SwigPyBuiltin_BadDealloc(PyObject *obj) {
|
||||
SwigPyObject *sobj = (SwigPyObject *)obj;
|
||||
if (sobj->own) {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(Py_TYPE(obj));
|
||||
PyErr_Format(PyExc_TypeError, "Swig detected a memory leak in type '%S': no callable destructor found.", tpname);
|
||||
SWIG_Py_DECREF(tpname);
|
||||
#else
|
||||
PyErr_Format(PyExc_TypeError, "Swig detected a memory leak in type '%s': no callable destructor found.", Py_TYPE(obj)->tp_name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,12 +99,24 @@ SwigPyBuiltin_SetterClosure (PyObject *obj, PyObject *val, void *closure) {
|
|||
return -1;
|
||||
}
|
||||
if (!val) {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(Py_TYPE(obj));
|
||||
PyErr_Format(PyExc_AttributeError, "Illegal member variable deletion in type '%S'", tpname);
|
||||
SWIG_Py_DECREF(tpname);
|
||||
#else
|
||||
PyErr_Format(PyExc_AttributeError, "Illegal member variable deletion in type '%s'", Py_TYPE(obj)->tp_name);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
getset = (SwigPyGetSet *)closure;
|
||||
if (!getset->set) {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(Py_TYPE(obj));
|
||||
PyErr_Format(PyExc_AttributeError, "Illegal member variable assignment in type '%S'", tpname);
|
||||
SWIG_Py_DECREF(tpname);
|
||||
#else
|
||||
PyErr_Format(PyExc_AttributeError, "Illegal member variable assignment in type '%s'", Py_TYPE(obj)->tp_name);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
tuple = PyTuple_New(1);
|
||||
|
@ -114,12 +138,24 @@ SwigPyBuiltin_FunpackSetterClosure (PyObject *obj, PyObject *val, void *closure)
|
|||
return -1;
|
||||
}
|
||||
if (!val) {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(Py_TYPE(obj));
|
||||
PyErr_Format(PyExc_AttributeError, "Illegal member variable deletion in type '%S'", tpname);
|
||||
SWIG_Py_DECREF(tpname);
|
||||
#else
|
||||
PyErr_Format(PyExc_AttributeError, "Illegal member variable deletion in type '%s'", Py_TYPE(obj)->tp_name);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
getset = (SwigPyGetSet *)closure;
|
||||
if (!getset->set) {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(Py_TYPE(obj));
|
||||
PyErr_Format(PyExc_AttributeError, "Illegal member variable assignment in type '%S'", tpname);
|
||||
SWIG_Py_DECREF(tpname);
|
||||
#else
|
||||
PyErr_Format(PyExc_AttributeError, "Illegal member variable assignment in type '%s'", Py_TYPE(obj)->tp_name);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
result = (*getset->set)(obj, val);
|
||||
|
@ -138,7 +174,6 @@ SwigPyStaticVar_dealloc(PyDescrObject *descr) {
|
|||
SWIGINTERN PyObject *
|
||||
SwigPyStaticVar_repr(PyGetSetDescrObject *descr) {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
|
||||
return PyUnicode_FromFormat("<class attribute '%S' of type '%s'>", PyDescr_NAME(descr), PyDescr_TYPE(descr)->tp_name);
|
||||
#else
|
||||
return PyString_FromFormat("<class attribute '%s' of type '%s'>", PyString_AsString(PyDescr_NAME(descr)), PyDescr_TYPE(descr)->tp_name);
|
||||
|
@ -181,24 +216,29 @@ SWIGINTERN int
|
|||
SwigPyObjectType_setattro(PyObject *typeobject, PyObject *name, PyObject *value) {
|
||||
PyObject *attribute;
|
||||
PyTypeObject *type;
|
||||
descrsetfunc local_set;
|
||||
|
||||
assert(PyType_Check(typeobject));
|
||||
type = (PyTypeObject *)typeobject;
|
||||
attribute = _PyType_Lookup(type, name);
|
||||
if (attribute != NULL) {
|
||||
/* Implement descriptor functionality, if any */
|
||||
local_set = Py_TYPE(attribute)->tp_descr_set;
|
||||
if (local_set != NULL)
|
||||
return local_set(attribute, (PyObject *)type, value);
|
||||
descrsetfunc local_set = Py_TYPE(attribute)->tp_descr_set;
|
||||
if (local_set == NULL) {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
PyErr_Format(PyExc_AttributeError, "cannot modify read-only attribute '%s.%S'", type->tp_name, name);
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(type);
|
||||
PyErr_Format(PyExc_AttributeError, "cannot modify read-only attribute '%S.%S'", tpname, name);
|
||||
SWIG_Py_DECREF(tpname);
|
||||
#else
|
||||
PyErr_Format(PyExc_AttributeError, "cannot modify read-only attribute '%s.%s'", type->tp_name, PyString_AS_STRING(name));
|
||||
PyErr_Format(PyExc_AttributeError, "cannot modify read-only attribute '%s.%s'", type->tp_name, PyString_AS_STRING(name));
|
||||
#endif
|
||||
} else {
|
||||
return local_set(attribute, (PyObject *)type, value);
|
||||
}
|
||||
} else {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
PyErr_Format(PyExc_AttributeError, "type '%s' has no attribute '%S'", type->tp_name, name);
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(type);
|
||||
PyErr_Format(PyExc_AttributeError, "type '%S' has no attribute '%S'", tpname, name);
|
||||
SWIG_Py_DECREF(tpname);
|
||||
#else
|
||||
PyErr_Format(PyExc_AttributeError, "type '%s' has no attribute '%s'", type->tp_name, PyString_AS_STRING(name));
|
||||
#endif
|
||||
|
|
|
@ -66,7 +66,7 @@ SWIG_PyUnicode_AsUTF8AndSize(PyObject *str, Py_ssize_t *psize, PyObject **pbytes
|
|||
#endif
|
||||
}
|
||||
|
||||
SWIGINTERN PyObject*
|
||||
SWIGINTERN PyObject *
|
||||
SWIG_Python_str_FromChar(const char *c)
|
||||
{
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
|
@ -132,3 +132,31 @@ SWIG_Python_str_FromChar(const char *c)
|
|||
# define SWIG_Py_DECREF Py_DECREF
|
||||
# define SWIG_Py_XDECREF Py_XDECREF
|
||||
#endif
|
||||
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
SWIGINTERN PyObject *
|
||||
SWIG_PyType_GetFullyQualifiedName(PyTypeObject *type) {
|
||||
#if PY_VERSION_HEX >= 0x030d0000
|
||||
return PyType_GetFullyQualifiedName(type);
|
||||
#else
|
||||
PyObject *result = NULL;
|
||||
PyObject *qualname = PyObject_GetAttrString((PyObject *)type, "__qualname__");
|
||||
if (qualname) {
|
||||
PyObject *mod = PyObject_GetAttrString((PyObject *)type, "__module__");
|
||||
if (mod) {
|
||||
if (PyUnicode_Check(mod) && PyUnicode_CompareWithASCIIString(mod, "builtins") && PyUnicode_CompareWithASCIIString(mod, "__main__")) {
|
||||
result = PyUnicode_FromFormat("%U%c%U", mod, '.', qualname);
|
||||
SWIG_Py_DECREF(qualname);
|
||||
} else {
|
||||
result = qualname;
|
||||
}
|
||||
SWIG_Py_DECREF(mod);
|
||||
} else {
|
||||
result = qualname;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -2082,7 +2082,13 @@ SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) {
|
|||
if (!PyString_Check(name))
|
||||
# endif
|
||||
{
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(Py_TYPE(name));
|
||||
PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%S'", tpname);
|
||||
SWIG_Py_DECREF(tpname);
|
||||
#else
|
||||
PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%s'", Py_TYPE(name)->tp_name);
|
||||
#endif
|
||||
return -1;
|
||||
} else {
|
||||
SWIG_Py_INCREF(name);
|
||||
|
@ -2106,7 +2112,15 @@ SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) {
|
|||
if (!encoded_name)
|
||||
goto done;
|
||||
}
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
{
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(tp);
|
||||
PyErr_Format(PyExc_AttributeError, "'%S' object has no attribute '%s'", tpname, PyString_AsString(encoded_name));
|
||||
SWIG_Py_DECREF(tpname);
|
||||
}
|
||||
#else
|
||||
PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", tp->tp_name, PyString_AsString(encoded_name));
|
||||
#endif
|
||||
SWIG_Py_DECREF(encoded_name);
|
||||
} else {
|
||||
res = f(descr, obj, value);
|
||||
|
|
Loading…
Reference in New Issue