Browse Source

Separate out Python compat hacks from py_panda.h into py_compat.h

rdb 8 years ago
parent
commit
f54b8be676

+ 1 - 0
dtool/src/interrogatedb/p3interrogatedb_composite2.cxx

@@ -5,4 +5,5 @@
 #include "interrogate_interface.cxx"
 #include "interrogate_interface.cxx"
 #include "interrogate_request.cxx"
 #include "interrogate_request.cxx"
 #include "py_panda.cxx"
 #include "py_panda.cxx"
+#include "py_compat.cxx"
 #include "py_wrappers.cxx"
 #include "py_wrappers.cxx"

+ 54 - 0
dtool/src/interrogatedb/py_compat.cxx

@@ -0,0 +1,54 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file py_compat.cxx
+ * @author rdb
+ * @date 2017-12-03
+ */
+
+#include "py_compat.h"
+
+#ifdef HAVE_PYTHON
+
+PyTupleObject Dtool_EmptyTuple = {PyVarObject_HEAD_INIT(nullptr, 0)};
+
+#if PY_MAJOR_VERSION < 3
+/**
+ * Given a long or int, returns a size_t, or raises an OverflowError if it is
+ * out of range.
+ */
+size_t PyLongOrInt_AsSize_t(PyObject *vv) {
+  if (PyInt_Check(vv)) {
+    long value = PyInt_AS_LONG(vv);
+    if (value < 0) {
+      PyErr_SetString(PyExc_OverflowError,
+                      "can't convert negative value to size_t");
+      return (size_t)-1;
+    }
+    return (size_t)value;
+  }
+
+  if (!PyLong_Check(vv)) {
+    Dtool_Raise_TypeError("a long or int was expected");
+    return (size_t)-1;
+  }
+
+  size_t bytes;
+  int one = 1;
+  int res = _PyLong_AsByteArray((PyLongObject *)vv, (unsigned char *)&bytes,
+                                SIZEOF_SIZE_T, (int)*(unsigned char*)&one, 0);
+
+  if (res < 0) {
+    return (size_t)res;
+  } else {
+    return bytes;
+  }
+}
+#endif
+
+#endif  // HAVE_PYTHON

+ 169 - 0
dtool/src/interrogatedb/py_compat.h

@@ -0,0 +1,169 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file py_compat.h
+ * @author rdb
+ * @date 2017-12-02
+ */
+
+#ifndef PY_COMPAT_H
+#define PY_COMPAT_H
+
+#include "dtoolbase.h"
+
+#ifdef HAVE_PYTHON
+
+// The contents of this file were originally part of py_panda.h.  It
+// specifically contains polyfills that are required to maintain compatibility
+// with Python 2 and older versions of Python 3.
+
+// These compatibility hacks are sorted by Python version that removes the
+// need for the respective hack.
+
+#ifdef _POSIX_C_SOURCE
+#  undef _POSIX_C_SOURCE
+#endif
+
+#ifdef _XOPEN_SOURCE
+#  undef _XOPEN_SOURCE
+#endif
+
+// See PEP 353
+#define PY_SSIZE_T_CLEAN 1
+
+#include "Python.h"
+
+/* Python 2.4 */
+
+// 2.4 macros which aren't available in 2.3
+#ifndef Py_RETURN_NONE
+#  define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
+#endif
+
+#ifndef Py_RETURN_TRUE
+#  define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
+#endif
+
+#ifndef Py_RETURN_FALSE
+#  define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
+#endif
+
+/* Python 2.5 */
+
+// Prior to Python 2.5, we didn't have Py_ssize_t.
+#if PY_VERSION_HEX < 0x02050000
+typedef int Py_ssize_t;
+#  define PyInt_FromSsize_t PyInt_FromLong
+#  define PyInt_AsSsize_t PyInt_AsLong
+#endif
+
+/* Python 2.6 */
+
+#ifndef Py_TYPE
+#  define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
+#endif
+
+/* Python 2.7, 3.1 */
+
+#ifndef PyVarObject_HEAD_INIT
+  #define PyVarObject_HEAD_INIT(type, size) \
+    PyObject_HEAD_INIT(type) size,
+#endif
+
+/* Python 2.7, 3.2 */
+
+#if PY_VERSION_HEX < 0x03020000
+#  define PyErr_NewExceptionWithDoc(name, doc, base, dict) \
+          PyErr_NewException(name, base, dict)
+#endif
+
+/* Python 3.0 */
+
+// Always on in Python 3
+#ifndef Py_TPFLAGS_CHECKTYPES
+#  define Py_TPFLAGS_CHECKTYPES 0
+#endif
+
+// Macros for writing code that will compile in both versions.
+#if PY_MAJOR_VERSION >= 3
+#  define nb_nonzero nb_bool
+#  define nb_divide nb_true_divide
+#  define nb_inplace_divide nb_inplace_true_divide
+
+#  define PyLongOrInt_Check(x) PyLong_Check(x)
+#  define PyLongOrInt_AS_LONG PyLong_AS_LONG
+#  define PyInt_Check PyLong_Check
+#  define PyInt_AsLong PyLong_AsLong
+#  define PyInt_AS_LONG PyLong_AS_LONG
+#  define PyLongOrInt_AsSize_t PyLong_AsSize_t
+#else
+#  define PyLongOrInt_Check(x) (PyInt_Check(x) || PyLong_Check(x))
+// PyInt_FromSize_t automatically picks the right type.
+#  define PyLongOrInt_AS_LONG PyInt_AsLong
+
+EXPCL_INTERROGATEDB size_t PyLongOrInt_AsSize_t(PyObject *);
+#endif
+
+// Which character to use in PyArg_ParseTuple et al for a byte string.
+#if PY_MAJOR_VERSION >= 3
+#  define FMTCHAR_BYTES "y"
+#else
+#  define FMTCHAR_BYTES "s"
+#endif
+
+/* Python 3.2 */
+
+#if PY_VERSION_HEX < 0x03020000
+typedef long Py_hash_t;
+#endif
+
+/* Python 3.3 */
+
+#if PY_MAJOR_VERSION >= 3
+// Python 3 versions before 3.3.3 defined this incorrectly.
+#  undef _PyErr_OCCURRED
+#  define _PyErr_OCCURRED() (PyThreadState_GET()->curexc_type)
+
+// Python versions before 3.3 did not define this.
+#  if PY_VERSION_HEX < 0x03030000
+#    define PyUnicode_AsUTF8 _PyUnicode_AsString
+#    define PyUnicode_AsUTF8AndSize _PyUnicode_AsStringAndSize
+#  endif
+#endif
+
+/* Python 3.6 */
+
+// Used to implement _PyObject_CallNoArg
+extern EXPCL_INTERROGATEDB PyTupleObject Dtool_EmptyTuple;
+
+#ifndef _PyObject_CallNoArg
+#  define _PyObject_CallNoArg(func) PyObject_Call((func), (PyObject *)&Dtool_EmptyTuple, nullptr)
+#endif
+
+// Python versions before 3.6 didn't require longlong support to be enabled.
+#ifndef HAVE_LONG_LONG
+#  define PyLong_FromLongLong(x) PyLong_FromLong((long) (x))
+#  define PyLong_FromUnsignedLongLong(x) PyLong_FromUnsignedLong((unsigned long) (x))
+#  define PyLong_AsLongLong(x) PyLong_AsLong(x)
+#  define PyLong_AsUnsignedLongLong(x) PyLong_AsUnsignedLong(x)
+#  define PyLong_AsUnsignedLongLongMask(x) PyLong_AsUnsignedLongMask(x)
+#  define PyLong_AsLongLongAndOverflow(x) PyLong_AsLongAndOverflow(x)
+#endif
+
+/* Other Python implementations */
+
+// _PyErr_OCCURRED is an undocumented macro version of PyErr_Occurred.
+// Some implementations of the CPython API (e.g. PyPy's cpyext) do not define
+// it, so in these cases we just silently fall back to PyErr_Occurred.
+#ifndef _PyErr_OCCURRED
+#  define _PyErr_OCCURRED() PyErr_Occurred()
+#endif
+
+#endif  // HAVE_PYTHON
+
+#endif  // PY_COMPAT_H

+ 3 - 37
dtool/src/interrogatedb/py_panda.cxx

@@ -17,8 +17,6 @@
 
 
 #ifdef HAVE_PYTHON
 #ifdef HAVE_PYTHON
 
 
-PyTupleObject Dtool_EmptyTuple;
-
 PyMemberDef standard_type_members[] = {
 PyMemberDef standard_type_members[] = {
   {(char *)"this", (sizeof(void*) == sizeof(int)) ? T_UINT : T_ULONGLONG, offsetof(Dtool_PyInstDef, _ptr_to_object), READONLY, (char *)"C++ 'this' pointer, if any"},
   {(char *)"this", (sizeof(void*) == sizeof(int)) ? T_UINT : T_ULONGLONG, offsetof(Dtool_PyInstDef, _ptr_to_object), READONLY, (char *)"C++ 'this' pointer, if any"},
   {(char *)"this_ownership", T_BOOL, offsetof(Dtool_PyInstDef, _memory_rules), READONLY, (char *)"C++ 'this' ownership rules"},
   {(char *)"this_ownership", T_BOOL, offsetof(Dtool_PyInstDef, _memory_rules), READONLY, (char *)"C++ 'this' ownership rules"},
@@ -33,39 +31,6 @@ static RuntimeTypeMap runtime_type_map;
 static RuntimeTypeSet runtime_type_set;
 static RuntimeTypeSet runtime_type_set;
 static NamedTypeMap named_type_map;
 static NamedTypeMap named_type_map;
 
 
-#if PY_MAJOR_VERSION < 3
-/**
- * Given a long or int, returns a size_t, or raises an OverflowError if it is
- * out of range.
- */
-size_t PyLongOrInt_AsSize_t(PyObject *vv) {
-  if (PyInt_Check(vv)) {
-    long value = PyInt_AS_LONG(vv);
-    if (value < 0) {
-      PyErr_SetString(PyExc_OverflowError,
-                      "can't convert negative value to size_t");
-      return (size_t)-1;
-    }
-    return (size_t)value;
-  }
-
-  if (!PyLong_Check(vv)) {
-    Dtool_Raise_TypeError("a long or int was expected");
-    return (size_t)-1;
-  }
-
-  size_t bytes;
-  int one = 1;
-  int res = _PyLong_AsByteArray((PyLongObject *)vv, (unsigned char *)&bytes,
-                                SIZEOF_SIZE_T, (int)*(unsigned char*)&one, 0);
-
-  if (res < 0) {
-    return (size_t)res;
-  } else {
-    return bytes;
-  }
-}
-#endif
 
 
 /**
 /**
  * Given a valid (non-NULL) PyObject, does a simple check to see if it might
  * Given a valid (non-NULL) PyObject, does a simple check to see if it might
@@ -646,8 +611,9 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
       return Dtool_Raise_TypeError("PyType_Ready(Dtool_StaticProperty_Type)");
       return Dtool_Raise_TypeError("PyType_Ready(Dtool_StaticProperty_Type)");
     }
     }
 
 
-    // Initialize the "empty tuple".
-    (void)PyObject_INIT_VAR((PyObject *)&Dtool_EmptyTuple, &PyTuple_Type, 0);
+#ifdef Py_TRACE_REFS
+    _Py_AddToAllObjects((PyObject *)&Dtool_EmptyTuple, 0);
+#endif
 
 
     // Initialize the base class of everything.
     // Initialize the base class of everything.
     Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(NULL);
     Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(NULL);

+ 2 - 118
dtool/src/interrogatedb/py_panda.h

@@ -20,131 +20,15 @@
 #define  Py_DEBUG
 #define  Py_DEBUG
 #endif
 #endif
 
 
-#ifndef NO_RUNTIME_TYPES
-
-#include "dtoolbase.h"
-#include "typedObject.h"
-#include "typeRegistry.h"
-
-#endif
-
 #include "pnotify.h"
 #include "pnotify.h"
 #include "vector_uchar.h"
 #include "vector_uchar.h"
 
 
 #if defined(HAVE_PYTHON) && !defined(CPPPARSER)
 #if defined(HAVE_PYTHON) && !defined(CPPPARSER)
 
 
-#ifdef _POSIX_C_SOURCE
-#undef _POSIX_C_SOURCE
-#endif
-
-#ifdef _XOPEN_SOURCE
-#undef _XOPEN_SOURCE
-#endif
-
-#define PY_SSIZE_T_CLEAN 1
-
-#include "Python.h"
+// py_compat.h includes Python.h.
+#include "py_compat.h"
 #include "structmember.h"
 #include "structmember.h"
 
 
-#ifndef HAVE_LONG_LONG
-#define PyLong_FromLongLong(x) PyLong_FromLong((long) (x))
-#define PyLong_FromUnsignedLongLong(x) PyLong_FromUnsignedLong((unsigned long) (x))
-#define PyLong_AsLongLong(x) PyLong_AsLong(x)
-#define PyLong_AsUnsignedLongLong(x) PyLong_AsUnsignedLong(x)
-#define PyLong_AsUnsignedLongLongMask(x) PyLong_AsUnsignedLongMask(x)
-#define PyLong_AsLongLongAndOverflow(x) PyLong_AsLongAndOverflow(x)
-#endif
-
-#if PY_VERSION_HEX < 0x02050000
-
-// Prior to Python 2.5, we didn't have Py_ssize_t.
-typedef int Py_ssize_t;
-#define PyInt_FromSsize_t PyInt_FromLong
-#define PyInt_AsSsize_t PyInt_AsLong
-
-#endif  // PY_VERSION_HEX
-
-// 2.4 macros which aren't available in 2.3
-#ifndef Py_RETURN_NONE
-inline PyObject* doPy_RETURN_NONE()
-{   Py_INCREF(Py_None); return Py_None; }
-#define Py_RETURN_NONE return doPy_RETURN_NONE()
-#endif
-
-#ifndef Py_RETURN_TRUE
-inline PyObject* doPy_RETURN_TRUE()
-{Py_INCREF(Py_True); return Py_True;}
-#define Py_RETURN_TRUE return doPy_RETURN_TRUE()
-#endif
-
-#ifndef Py_RETURN_FALSE
-inline PyObject* doPy_RETURN_FALSE()
-{Py_INCREF(Py_False); return Py_False;}
-#define Py_RETURN_FALSE return doPy_RETURN_FALSE()
-#endif
-
-#ifndef PyVarObject_HEAD_INIT
-#define PyVarObject_HEAD_INIT(type, size) \
-  PyObject_HEAD_INIT(type) size,
-#endif
-
-#ifndef Py_TYPE
-#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
-#endif
-
-#ifndef Py_TPFLAGS_CHECKTYPES
-// Always on in Python 3
-#define Py_TPFLAGS_CHECKTYPES 0
-#endif
-
-#if PY_MAJOR_VERSION >= 3
-// For writing code that will compile in both versions.
-#define nb_nonzero nb_bool
-#define nb_divide nb_true_divide
-#define nb_inplace_divide nb_inplace_true_divide
-
-#define PyLongOrInt_Check(x) PyLong_Check(x)
-#define PyLongOrInt_AS_LONG PyLong_AS_LONG
-#define PyInt_Check PyLong_Check
-#define PyInt_AsLong PyLong_AsLong
-#define PyInt_AS_LONG PyLong_AS_LONG
-#define PyLongOrInt_AsSize_t PyLong_AsSize_t
-#else
-#define PyLongOrInt_Check(x) (PyInt_Check(x) || PyLong_Check(x))
-// PyInt_FromSize_t automatically picks the right type.
-#define PyLongOrInt_AS_LONG PyInt_AsLong
-
-EXPCL_INTERROGATEDB size_t PyLongOrInt_AsSize_t(PyObject *);
-
-// For more portably defining hash functions.
-typedef long Py_hash_t;
-#endif
-
-#if PY_MAJOR_VERSION >= 3
-// Python 3 versions before 3.3.3 defined this incorrectly.
-#undef _PyErr_OCCURRED
-#define _PyErr_OCCURRED() (PyThreadState_GET()->curexc_type)
-
-// Python versions before 3.3 did not define this.
-#if PY_VERSION_HEX < 0x03030000
-#define PyUnicode_AsUTF8 _PyUnicode_AsString
-#define PyUnicode_AsUTF8AndSize _PyUnicode_AsStringAndSize
-#endif
-#endif
-
-// Which character to use in PyArg_ParseTuple et al for a byte string.
-#if PY_MAJOR_VERSION >= 3
-#define FMTCHAR_BYTES "y"
-#else
-#define FMTCHAR_BYTES "s"
-#endif
-
-extern EXPCL_INTERROGATEDB PyTupleObject Dtool_EmptyTuple;
-
-#ifndef _PyObject_CallNoArg
-#define _PyObject_CallNoArg(func) PyObject_Call((func), (PyObject *)&Dtool_EmptyTuple, NULL)
-#endif
-
 using namespace std;
 using namespace std;
 
 
 // this is tempory .. untill this is glued better into the panda build system
 // this is tempory .. untill this is glued better into the panda build system