aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/libshiboken/pep384impl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken2/libshiboken/pep384impl.cpp')
-rw-r--r--sources/shiboken2/libshiboken/pep384impl.cpp186
1 files changed, 118 insertions, 68 deletions
diff --git a/sources/shiboken2/libshiboken/pep384impl.cpp b/sources/shiboken2/libshiboken/pep384impl.cpp
index c7ca98c46..c04848eb3 100644
--- a/sources/shiboken2/libshiboken/pep384impl.cpp
+++ b/sources/shiboken2/libshiboken/pep384impl.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "pep384impl.h"
+#include "sbkpython.h"
#include "autodecref.h"
#include "sbkstaticstrings.h"
#include "sbkstaticstrings_p.h"
@@ -50,26 +50,19 @@ extern "C"
/*
* The documentation is located in pep384impl_doc.rst
*/
-
-/*****************************************************************************
- *
- * Support for object.h
- *
- */
-
+#if PY_VERSION_HEX < 0x03000000
+#define IS_PY2
+#endif // PY_VERSION_HEX < 0x03000000
/*
* Here is the verification code for PyTypeObject.
* We create a type object and check if its fields
* appear at the right offsets.
*/
+#ifdef Py_LIMITED_API
#define make_dummy_int(x) (x * sizeof(void *))
#define make_dummy(x) (reinterpret_cast<void *>(make_dummy_int(x)))
-#ifdef Py_LIMITED_API
-datetime_struc *PyDateTimeAPI = NULL;
-#endif
-
static PyObject *
dummy_func(PyObject * /* self */, PyObject * /* args */)
{
@@ -180,18 +173,18 @@ check_PyTypeObject_valid()
Py_DECREF(probe_tp_mro);
}
-
-#ifdef Py_LIMITED_API
-
#if PY_VERSION_HEX < PY_ISSUE33738_SOLVED
#include "pep384_issue33738.cpp"
#endif
+#endif // Py_LIMITED_API
+
/*****************************************************************************
*
* Support for unicodeobject.h
*
*/
+#ifdef Py_LIMITED_API
char *
_PepUnicode_AsString(PyObject *str)
@@ -207,15 +200,15 @@ _PepUnicode_AsString(PyObject *str)
#define TOSTRING(x) STRINGIFY(x)
#define AT __FILE__ ":" TOSTRING(__LINE__)
- static PyObject *cstring_dict = NULL;
- if (cstring_dict == NULL) {
+ static PyObject *cstring_dict = nullptr;
+ if (cstring_dict == nullptr) {
cstring_dict = PyDict_New();
- if (cstring_dict == NULL)
+ if (cstring_dict == nullptr)
Py_FatalError("Error in " AT);
}
- PyObject *bytesStr = PyUnicode_AsEncodedString(str, "utf8", NULL);
- PyObject *entry = PyDict_GetItem(cstring_dict, bytesStr);
- if (entry == NULL) {
+ PyObject *bytesStr = PyUnicode_AsEncodedString(str, "utf8", nullptr);
+ PyObject *entry = PyDict_GetItemWithError(cstring_dict, bytesStr);
+ if (entry == nullptr) {
int e = PyDict_SetItem(cstring_dict, bytesStr, bytesStr);
if (e != 0)
Py_FatalError("Error in " AT);
@@ -225,12 +218,14 @@ _PepUnicode_AsString(PyObject *str)
Py_DECREF(bytesStr);
return PyBytes_AsString(entry);
}
+#endif // Py_LIMITED_API
/*****************************************************************************
*
* Support for longobject.h
*
*/
+#ifdef Py_LIMITED_API
/*
* This is the original Python function _PyLong_AsInt() from longobject.c .
@@ -253,15 +248,18 @@ _PepLong_AsInt(PyObject *obj)
"Python int too large to convert to C int");
return -1;
}
- return (int)result;
+ return int(result);
}
+#endif // Py_LIMITED_API
/*****************************************************************************
*
* Support for pydebug.h
*
*/
-static PyObject *sys_flags = NULL;
+#ifdef Py_LIMITED_API
+
+static PyObject *sys_flags = nullptr;
int
Pep_GetFlag(const char *name)
@@ -271,13 +269,13 @@ Pep_GetFlag(const char *name)
if (!initialized) {
sys_flags = PySys_GetObject("flags");
- // func gives no error if NULL is returned and does not incref.
+ // func gives no error if nullptr is returned and does not incref.
Py_XINCREF(sys_flags);
initialized = 1;
}
- if (sys_flags != NULL) {
+ if (sys_flags != nullptr) {
PyObject *ob_ret = PyObject_GetAttrString(sys_flags, name);
- if (ob_ret != NULL) {
+ if (ob_ret != nullptr) {
long long_ret = PyLong_AsLong(ob_ret);
Py_DECREF(ob_ret);
ret = (int) long_ret;
@@ -299,12 +297,14 @@ Pep_GetVerboseFlag()
}
return verbose_flag;
}
+#endif // Py_LIMITED_API
/*****************************************************************************
*
* Support for code.h
*
*/
+#ifdef Py_LIMITED_API
int
PepCode_Get(PyCodeObject *co, const char *name)
@@ -314,28 +314,32 @@ PepCode_Get(PyCodeObject *co, const char *name)
int ret = -1;
ob_ret = PyObject_GetAttrString(ob, name);
- if (ob_ret != NULL) {
+ if (ob_ret != nullptr) {
long long_ret = PyLong_AsLong(ob_ret);
Py_DECREF(ob_ret);
ret = (int) long_ret;
}
return ret;
}
+#endif // Py_LIMITED_API
/*****************************************************************************
*
* Support for datetime.h
*
*/
+#ifdef Py_LIMITED_API
+
+datetime_struc *PyDateTimeAPI = nullptr;
static PyTypeObject *dt_getCheck(const char *name)
{
PyObject *op = PyObject_GetAttrString(PyDateTimeAPI->module, name);
- if (op == NULL) {
+ if (op == nullptr) {
fprintf(stderr, "datetime.%s not found\n", name);
Py_FatalError("aborting");
}
- return (PyTypeObject *)op;
+ return reinterpret_cast<PyTypeObject *>(op);
}
// init_DateTime is called earlier than our module init.
@@ -346,10 +350,10 @@ init_DateTime(void)
static int initialized = 0;
if (!initialized) {
PyDateTimeAPI = (datetime_struc *)malloc(sizeof(datetime_struc));
- if (PyDateTimeAPI == NULL)
+ if (PyDateTimeAPI == nullptr)
Py_FatalError("PyDateTimeAPI malloc error, aborting");
PyDateTimeAPI->module = PyImport_ImportModule("datetime");
- if (PyDateTimeAPI->module == NULL)
+ if (PyDateTimeAPI->module == nullptr)
Py_FatalError("datetime module not found, aborting");
PyDateTimeAPI->DateType = dt_getCheck("date");
PyDateTimeAPI->DateTimeType = dt_getCheck("datetime");
@@ -368,7 +372,7 @@ PyDateTime_Get(PyObject *ob, const char *name)
int ret = -1;
ob_ret = PyObject_GetAttrString(ob, name);
- if (ob_ret != NULL) {
+ if (ob_ret != nullptr) {
long long_ret = PyLong_AsLong(ob_ret);
Py_DECREF(ob_ret);
ret = (int) long_ret;
@@ -398,21 +402,23 @@ PyTime_FromTime(int hour, int min, int sec, int usec)
return PyObject_CallFunction((PyObject *)PyDateTimeAPI->TimeType,
(char *)"(iiii)", hour, min, sec, usec);
}
+#endif // Py_LIMITED_API
/*****************************************************************************
*
* Support for pythonrun.h
*
*/
+#ifdef Py_LIMITED_API
// Flags are ignored in these simple helpers.
PyObject *
PyRun_String(const char *str, int start, PyObject *globals, PyObject *locals)
{
PyObject *code = Py_CompileString(str, "pyscript", start);
- PyObject *ret = NULL;
+ PyObject *ret = nullptr;
- if (code != NULL) {
+ if (code != nullptr) {
ret = PyEval_EvalCode(code, globals, locals);
}
Py_XDECREF(code);
@@ -423,9 +429,9 @@ PyRun_String(const char *str, int start, PyObject *globals, PyObject *locals)
// This is only a simple local helper that returns a computed variable.
// Used also in Python 2.
-#if defined(Py_LIMITED_API) || PY_VERSION_HEX < 0x03000000
+#if defined(Py_LIMITED_API) || defined(IS_PY2)
static PyObject *
-PepRun_GetResult(const char *command, const char *resvar)
+PepRun_GetResult(const char *command)
{
PyObject *d, *v, *res;
@@ -435,30 +441,29 @@ PepRun_GetResult(const char *command, const char *resvar)
return nullptr;
}
v = PyRun_String(command, Py_file_input, d, d);
- res = v ? PyDict_GetItemString(d, resvar) : NULL;
+ res = v ? PyDict_GetItem(d, Shiboken::PyName::result()) : nullptr;
Py_XDECREF(v);
Py_DECREF(d);
return res;
}
-#endif // Py_LIMITED_API || Python 2
-
-#ifdef Py_LIMITED_API
+#endif // defined(Py_LIMITED_API) || defined(IS_PY2)
/*****************************************************************************
*
* Support for classobject.h
*
*/
+#ifdef Py_LIMITED_API
-PyTypeObject *PepMethod_TypePtr = NULL;
+PyTypeObject *PepMethod_TypePtr = nullptr;
static PyTypeObject *getMethodType(void)
{
static const char prog[] =
"class _C:\n"
" def _m(self): pass\n"
- "MethodType = type(_C()._m)\n";
- return (PyTypeObject *) PepRun_GetResult(prog, "MethodType");
+ "result = type(_C()._m)\n";
+ return reinterpret_cast<PyTypeObject *>(PepRun_GetResult(prog));
}
// We have no access to PyMethod_New and must call types.MethodType, instead.
@@ -489,12 +494,14 @@ PyMethod_Self(PyObject *im)
Py_DECREF(ret);
return ret;
}
+#endif // Py_LIMITED_API
/*****************************************************************************
*
* Support for funcobject.h
*
*/
+#ifdef Py_LIMITED_API
PyObject *
PepFunction_Get(PyObject *ob, const char *name)
@@ -509,22 +516,64 @@ PepFunction_Get(PyObject *ob, const char *name)
// This became necessary after Windows was activated.
-PyTypeObject *PepFunction_TypePtr = NULL;
+PyTypeObject *PepFunction_TypePtr = nullptr;
static PyTypeObject *getFunctionType(void)
{
static const char prog[] =
- "from types import FunctionType\n";
- return (PyTypeObject *) PepRun_GetResult(prog, "FunctionType");
+ "from types import FunctionType as result\n";
+ return reinterpret_cast<PyTypeObject *>(PepRun_GetResult(prog));
}
+#endif // Py_LIMITED_API || Python 2
+
+/*****************************************************************************
+ *
+ * Support for dictobject.h
+ *
+ */
+
+// PYSIDE-803, PYSIDE-813: We need that GIL-free version from Python 2.7.12 .
+#ifdef IS_PY2
+
+/* Variant of PyDict_GetItem() that doesn't suppress exceptions.
+ This returns NULL *with* an exception set if an exception occurred.
+ It returns NULL *without* an exception set if the key wasn't present.
+*/
+PyObject *
+PyDict_GetItemWithError(PyObject *op, PyObject *key)
+{
+ long hash;
+ PyDictObject *mp = reinterpret_cast<PyDictObject *>(op);
+ PyDictEntry *ep;
+ if (!PyDict_Check(op)) {
+ PyErr_BadInternalCall();
+ return nullptr;
+ }
+ if (!PyString_CheckExact(key) ||
+ (hash = (reinterpret_cast<PyStringObject *>(key))->ob_shash) == -1)
+ {
+ hash = PyObject_Hash(key);
+ if (hash == -1) {
+ return nullptr;
+ }
+ }
+
+ ep = (mp->ma_lookup)(mp, key, hash);
+ if (ep == nullptr) {
+ return nullptr;
+ }
+ return ep->me_value;
+}
+#endif // IS_PY2
/*****************************************************************************
*
* Extra support for signature.cpp
*
*/
+#ifdef Py_LIMITED_API
-PyTypeObject *PepStaticMethod_TypePtr = NULL;
+PyTypeObject *PepStaticMethod_TypePtr = nullptr;
static PyTypeObject *
getStaticMethodType(void)
@@ -533,8 +582,8 @@ getStaticMethodType(void)
// "StaticMethodType = type(str.__dict__['maketrans'])\n";
static const char prog[] =
"from xxsubtype import spamlist\n"
- "StaticMethod_Type = type(spamlist.__dict__['staticmeth'])\n";
- return (PyTypeObject *) PepRun_GetResult(prog, "StaticMethod_Type");
+ "result = type(spamlist.__dict__['staticmeth'])\n";
+ return reinterpret_cast<PyTypeObject *>(PepRun_GetResult(prog));
}
typedef struct {
@@ -548,25 +597,25 @@ PyStaticMethod_New(PyObject *callable)
{
staticmethod *sm = (staticmethod *)
PyType_GenericAlloc(PepStaticMethod_TypePtr, 0);
- if (sm != NULL) {
+ if (sm != nullptr) {
Py_INCREF(callable);
sm->sm_callable = callable;
}
- return (PyObject *)sm;
+ return reinterpret_cast<PyObject *>(sm);
}
#endif // Py_LIMITED_API
-#if PY_VERSION_HEX < 0x03000000
-PyTypeObject *PepMethodDescr_TypePtr = NULL;
+#ifdef IS_PY2
+PyTypeObject *PepMethodDescr_TypePtr = nullptr;
static PyTypeObject *
getMethodDescrType(void)
{
static const char prog[] =
- "MethodDescr_Type = type(str.split)\n";
- return (PyTypeObject *) PepRun_GetResult(prog, "MethodDescr_Type");
+ "result = type(str.split)\n";
+ return reinterpret_cast<PyTypeObject *>(PepRun_GetResult(prog));
}
-#endif
+#endif // IS_PY2
/*****************************************************************************
*
@@ -595,9 +644,9 @@ PepType_GetNameStr(PyTypeObject *type)
#ifdef Py_LIMITED_API
// We keep these definitions local, because they don't work in Python 2.
-#define PyUnicode_GET_LENGTH(op) PyUnicode_GetLength((PyObject *)(op))
-#define PyUnicode_READ_CHAR(u, i) PyUnicode_ReadChar((PyObject *)(u), (i))
-#endif
+# define PyUnicode_GET_LENGTH(op) PyUnicode_GetLength((PyObject *)(op))
+# define PyUnicode_READ_CHAR(u, i) PyUnicode_ReadChar((PyObject *)(u), (i))
+#endif // Py_LIMITED_API
PyObject *
_Pep_PrivateMangle(PyObject *self, PyObject *name)
@@ -607,9 +656,9 @@ _Pep_PrivateMangle(PyObject *self, PyObject *name)
* This function is modelled after _Py_Mangle, but is optimized
* a little for our purpose.
*/
-#if PY_VERSION_HEX < 0X03000000
+#ifdef IS_PY2
const char *namestr = PyString_AsString(name);
- if (namestr == NULL || namestr[0] != '_' || namestr[1] != '_') {
+ if (namestr == nullptr || namestr[0] != '_' || namestr[1] != '_') {
Py_INCREF(name);
return name;
}
@@ -634,7 +683,7 @@ _Pep_PrivateMangle(PyObject *self, PyObject *name)
Py_INCREF(name);
return name;
}
-#endif
+#endif // IS_PY2
Shiboken::AutoDecRef privateobj(PyObject_GetAttr(
reinterpret_cast<PyObject *>(Py_TYPE(self)), Shiboken::PyMagicName::name()));
#ifndef Py_LIMITED_API
@@ -655,7 +704,7 @@ _Pep_PrivateMangle(PyObject *self, PyObject *name)
if (plen + nlen >= PY_SSIZE_T_MAX - 1) {
PyErr_SetString(PyExc_OverflowError,
"private identifier too large to be mangled");
- return NULL;
+ return nullptr;
}
size_t const amount = ipriv + 1 + plen + nlen;
size_t const big_stack = 1000;
@@ -673,7 +722,7 @@ _Pep_PrivateMangle(PyObject *self, PyObject *name)
if (amount > big_stack)
free(resbuf);
return result;
-#endif // Py_LIMITED_API
+#endif // else Py_LIMITED_API
}
/*****************************************************************************
@@ -704,17 +753,18 @@ init_PepRuntime()
void
Pep384_Init()
{
- check_PyTypeObject_valid();
init_PepRuntime();
#ifdef Py_LIMITED_API
+ check_PyTypeObject_valid();
Pep_GetVerboseFlag();
PepMethod_TypePtr = getMethodType();
PepFunction_TypePtr = getFunctionType();
PepStaticMethod_TypePtr = getStaticMethodType();
-#endif
-#if PY_VERSION_HEX < 0x03000000
+#endif // Py_LIMITED_API
+
+#ifdef IS_PY2
PepMethodDescr_TypePtr = getMethodDescrType();
-#endif
+#endif // IS_PY2
}
} // extern "C"