Browse Source

Experimental Python 3 support to the C++ code including interrogate. Also adds support for rich comparison in interrogate.

rdb 13 years ago
parent
commit
192d10b937

+ 8 - 0
direct/src/dcparser/dcClass.cxx

@@ -997,7 +997,11 @@ client_format_generate_CMU(PyObject *distobj, DOID_TYPE do_id,
 
   for (int i = 0; i < num_optional_fields; i++) {
     PyObject *py_field_name = PySequence_GetItem(optional_fields, i);
+#if PY_MAJOR_VERSION >= 3
+    string field_name = PyUnicode_AsUTF8(py_field_name);
+#else
     string field_name = PyString_AsString(py_field_name);
+#endif
     Py_XDECREF(py_field_name);
     
     DCField *field = get_field_by_name(field_name);
@@ -1082,7 +1086,11 @@ ai_format_generate(PyObject *distobj, DOID_TYPE do_id,
 
     for (int i = 0; i < num_optional_fields; ++i) {
       PyObject *py_field_name = PySequence_GetItem(optional_fields, i);
+#if PY_MAJOR_VERSION >= 3
+      string field_name = PyUnicode_AsUTF8(py_field_name);
+#else
       string field_name = PyString_AsString(py_field_name);
+#endif
       Py_XDECREF(py_field_name);
 
       DCField *field = get_field_by_name(field_name);

+ 14 - 2
direct/src/dcparser/dcField.cxx

@@ -269,7 +269,7 @@ pack_args(DCPacker &packer, PyObject *sequence) const {
 
   if (!Notify::ptr()->has_assert_failed()) {
     ostringstream strm;
-    PyObject *exc_type = PyExc_StandardError;
+    PyObject *exc_type = PyExc_Exception;
 
     if (as_parameter() != (DCParameter *)NULL) {
       // If it's a parameter-type field, the value may or may not be a
@@ -345,7 +345,7 @@ unpack_args(DCPacker &packer) const {
 
   if (!Notify::ptr()->has_assert_failed()) {
     ostringstream strm;
-    PyObject *exc_type = PyExc_StandardError;
+    PyObject *exc_type = PyExc_Exception;
 
     if (packer.had_pack_error()) {
       strm << "Data error unpacking field ";
@@ -585,14 +585,22 @@ get_pystr(PyObject *value) {
 
   PyObject *str = PyObject_Str(value);
   if (str != NULL) {
+#if PY_MAJOR_VERSION >= 3
+    string result = PyUnicode_AsUTF8(str);
+#else
     string result = PyString_AsString(str);
+#endif
     Py_DECREF(str);
     return result;
   }
 
   PyObject *repr = PyObject_Repr(value);
   if (repr != NULL) {
+#if PY_MAJOR_VERSION >= 3
+    string result = PyUnicode_AsUTF8(repr);
+#else
     string result = PyString_AsString(repr);
+#endif
     Py_DECREF(repr);
     return result;
   }
@@ -600,7 +608,11 @@ get_pystr(PyObject *value) {
   if (value->ob_type != NULL) {
     PyObject *typestr = PyObject_Str((PyObject *)(value->ob_type));
     if (typestr != NULL) {
+#if PY_MAJOR_VERSION >= 3
+      string result = PyUnicode_AsUTF8(typestr);
+#else
       string result = PyString_AsString(typestr);
+#endif
       Py_DECREF(typestr);
       return result;
     }

+ 51 - 6
direct/src/dcparser/dcPacker.cxx

@@ -695,11 +695,13 @@ pack_object(PyObject *object) {
             pack_int64(PyLong_AsLongLong(object));
             return;
       }
+#if PY_MAJOR_VERSION < 3
       else if (PyInt_Check(object))
       {
             pack_int64(PyInt_AsLong(object));
             return;
       }
+#endif
       break;
   case PT_uint64:
       if(PyLong_Check(object))
@@ -707,6 +709,7 @@ pack_object(PyObject *object) {
             pack_uint64(PyLong_AsUnsignedLongLong(object));
             return;
       }
+#if PY_MAJOR_VERSION < 3
       else if(PyInt_Check(object))
       {
             PyObject  *obj1 = PyNumber_Long(object);
@@ -714,6 +717,7 @@ pack_object(PyObject *object) {
             Py_DECREF(obj1);
             return;
       }
+#endif
       break;
   case PT_int:
       if(PyLong_Check(object))
@@ -721,11 +725,13 @@ pack_object(PyObject *object) {
             pack_int(PyLong_AsLong(object));
             return;
       }
+#if PY_MAJOR_VERSION < 3
       else if (PyInt_Check(object))
       {
             pack_int(PyInt_AsLong(object));
             return;
       }
+#endif
       break;
   case PT_uint:
       if(PyLong_Check(object))
@@ -733,29 +739,45 @@ pack_object(PyObject *object) {
             pack_uint(PyLong_AsUnsignedLong(object));
             return;
       }
+#if PY_MAJOR_VERSION < 3
       else if (PyInt_Check(object))
       {
-            PyObject  *obj1 = PyNumber_Long(object);
+            PyObject *obj1 = PyNumber_Long(object);
             pack_uint(PyLong_AsUnsignedLong(obj1));
             Py_DECREF(obj1);
             return;
       }
+#endif
       break;
   default:
       break;
   }
-  #ifdef USE_PYTHON_2_2_OR_EARLIER
-  if (PyInt_Check(object)) {
-  #else
   if (PyLong_Check(object)) {
     pack_int(PyLong_AsLong(object));
+#if PY_MAJOR_VERSION < 3
   } else if (PyInt_Check(object)) {
-  #endif
     pack_int(PyInt_AS_LONG(object));
+#endif
   } else if (PyFloat_Check(object)) {
     pack_double(PyFloat_AS_DOUBLE(object));
   } else if (PyLong_Check(object)) {
     pack_int64(PyLong_AsLongLong(object));
+#if PY_MAJOR_VERSION >= 3
+  } else if (PyUnicode_Check(object)) {
+    char *buffer;
+    Py_ssize_t length;
+    buffer = PyUnicode_AsUTF8AndSize(object, &length);
+    if (buffer) {
+      pack_string(string(buffer, length));
+    }
+  } else if (PyBytes_Check(object)) {
+    char *buffer;
+    Py_ssize_t length;
+    PyBytes_AsStringAndSize(object, &buffer, &length);
+    if (buffer) {
+      pack_string(string(buffer, length));
+    }
+#else
   } else if (PyString_Check(object) || PyUnicode_Check(object)) {
     char *buffer;
     Py_ssize_t length;
@@ -763,6 +785,7 @@ pack_object(PyObject *object) {
     if (buffer) {
       pack_string(string(buffer, length));
     }
+#endif
   } else {
     // For some reason, PySequence_Check() is incorrectly reporting
     // that a class instance is a sequence, even if it doesn't provide
@@ -871,18 +894,26 @@ unpack_object() {
   case PT_int:
     {
       int value = unpack_int();
+#if PY_MAJOR_VERSION >= 3
+      object = PyLong_FromLong(value);
+#else
       object = PyInt_FromLong(value);
+#endif
     }
     break;
       
   case PT_uint:
     {
       unsigned int value = unpack_uint();
+#if PY_MAJOR_VERSION >= 3
+      object = PyLong_FromLong(value);
+#else
       if (value & 0x80000000) {
         object = PyLong_FromUnsignedLong(value);
       } else {
         object = PyInt_FromLong(value);
       }
+#endif
     }
     break;
       
@@ -900,12 +931,26 @@ unpack_object() {
     }
     break;
 
-  case PT_string:
   case PT_blob:
+#if PY_MAJOR_VERSION >= 3
+    {
+      string str;
+      unpack_string(str);
+      object = PyBytes_FromStringAndSize(str.data(), str.size());
+    }
+    break;
+#endif
+    // On Python 2, fall through to below.
+
+  case PT_string:
     {
       string str;
       unpack_string(str);
+#if PY_MAJOR_VERSION >= 3
+      object = PyUnicode_FromStringAndSize(str.data(), str.size());
+#else
       object = PyString_FromStringAndSize(str.data(), str.size());
+#endif
     }
     break;
 

+ 52 - 7
direct/src/directbase/ppython.cxx

@@ -8,6 +8,9 @@
 ///////////////////////////////////////////////////////////////////////
 
 #include <Python.h>
+#if PY_MAJOR_VERSION >= 3
+#include <wchar.h>
+#endif
 
 #ifndef IMPORT_MODULE
 #error IMPORT_MODULE must be defined when compiling ppython.cxx !
@@ -17,14 +20,54 @@
 #define STRINGIFY(s) _STRINGIFY(s)
 #define IMPORT_MODULE_STR STRINGIFY(IMPORT_MODULE)
 
-int main(int argc, char **argv) {
-  int sts = 0;
+#if defined(_WIN32) && PY_MAJOR_VERSION >= 3
+// As Py_SetProgramName expects a wchar_t*,
+// it's easiest to just use the wmain entry point.
+int wmain(int argc, wchar_t *argv[]) {
+  Py_SetProgramName(argv[0]);
+
+#elif PY_MAJOR_VERSION >= 3
+// Convert from UTF-8 to wchar_t*.
+int main(int argc, char *mb_argv[]) {
+  wchar_t **argv = new wchar_t*[argc + 1];
+  for (int i = 0; i < argc; ++i) {
+    size_t len = mbstowcs(NULL, mb_argv[i], 0);
+    argv[i] = new wchar_t[len + 1];
+    mbstowcs(argv[i], mb_argv[i], len);
+    argv[i][len] = NULL;
+  }
+  // Just for good measure
+  argv[argc] = NULL;
 
   Py_SetProgramName(argv[0]);
-  
-  // On windows, we need to set pythonhome correctly. We'll try to
+
+#else
+// Python 2.
+int main(int argc, char *argv[]) {
+  Py_SetProgramName(argv[0]);
+#endif
+
+  // On Windows, we need to set pythonhome correctly. We'll try to
   // find ppython.exe on the path and set pythonhome to its location.
 #ifdef _WIN32
+#if PY_MAJOR_VERSION >= 3
+  // Py_SetPythonHome expects a wchar_t in Python 3.
+  wchar_t *path = _wgetenv(L"PATH");
+  wchar_t *result = wcstok(path, L";");
+  while (result != NULL) {
+    struct _stat st;
+    wchar_t *ppython = (wchar_t*) malloc(wcslen(result) * 2 + 26);
+    wcscpy(ppython, result);
+    wcscat(ppython, L"\\python.exe");
+    if (_wstat(ppython, &st) == 0) {
+      Py_SetPythonHome(result);
+      free(ppython);
+      break;
+    }
+    result = wcstok(NULL, L";");
+    free(ppython);
+  }
+#else
   char *path = getenv("PATH");
   char *result = strtok(path, ";");
   while (result != NULL) {
@@ -33,13 +76,14 @@ int main(int argc, char **argv) {
     strcpy(ppython, result);
     strcat(ppython, "\\ppython.exe");
     if (stat(ppython, &st) == 0) {
-        Py_SetPythonHome(result);
-        free(ppython);
-        break;
+      Py_SetPythonHome(result);
+      free(ppython);
+      break;
     }                                
     result = strtok(NULL, ";");
     free(ppython);
   }
+#endif
 #endif
   
   Py_Initialize();
@@ -50,6 +94,7 @@ int main(int argc, char **argv) {
 
   PySys_SetArgv(argc, argv);
 
+  int sts = 0;
   PyObject* m = PyImport_ImportModule(IMPORT_MODULE_STR);
   if (m <= 0) {
     PyErr_Print();

+ 14 - 6
direct/src/distributed/cConnectionRepository.cxx

@@ -769,7 +769,7 @@ handle_update_field() {
       Py_DECREF(dclass_obj);
       nassertr(dclass_this != NULL, false);
 
-      DCClass *dclass = (DCClass *)PyInt_AsLong(dclass_this);
+      DCClass *dclass = (DCClass *)PyLong_AsLong(dclass_this);
       Py_DECREF(dclass_this);
 
       // If in quiet zone mode, throw update away unless distobj
@@ -778,7 +778,7 @@ handle_update_field() {
         PyObject *neverDisable = PyObject_GetAttrString(distobj, "neverDisable");
         nassertr(neverDisable != NULL, false);
 
-        unsigned int cNeverDisable = PyInt_AsLong(neverDisable);
+        unsigned int cNeverDisable = PyLong_AsLong(neverDisable);
         if (!cNeverDisable) {
           // in quiet zone and distobj is disable-able
           // drop update on the floor
@@ -863,7 +863,7 @@ handle_update_field_owner() {
       Py_DECREF(dclass_obj);
       nassertr(dclass_this != NULL, false);
 
-      DCClass *dclass = (DCClass *)PyInt_AsLong(dclass_this);
+      DCClass *dclass = (DCClass *)PyLong_AsLong(dclass_this);
       Py_DECREF(dclass_this);
 
       // check if we should forward this update to the owner view
@@ -905,7 +905,7 @@ handle_update_field_owner() {
       Py_DECREF(dclass_obj);
       nassertr(dclass_this != NULL, false);
 
-      DCClass *dclass = (DCClass *)PyInt_AsLong(dclass_this);
+      DCClass *dclass = (DCClass *)PyLong_AsLong(dclass_this);
       Py_DECREF(dclass_this);
 
       // check if we should forward this update to the owner view
@@ -982,14 +982,22 @@ describe_message(ostream &out, const string &prefix,
     if (_python_repository != (PyObject *)NULL) {
       PyObject *msgId = PyLong_FromLong(msg_type);
       nassertv(msgId != NULL);
+#if PY_MAJOR_VERSION >= 3
+      PyObject *methodName = PyUnicode_FromString("_getMsgName");
+#else
       PyObject *methodName = PyString_FromString("_getMsgName");
+#endif
       nassertv(methodName != NULL);
 
       PyObject *result = PyObject_CallMethodObjArgs(_python_repository, methodName,
                                                     msgId, NULL);
       nassertv(result != NULL);
 
+#if PY_MAJOR_VERSION >= 3
+      msgName += string(PyUnicode_AsUTF8(result));
+#else
       msgName += string(PyString_AsString(result));
+#endif
 
       Py_DECREF(methodName);
       Py_DECREF(msgId);
@@ -1032,8 +1040,8 @@ describe_message(ostream &out, const string &prefix,
         PyObject *dclass_this = PyObject_GetAttrString(dclass_obj, "this");
         Py_DECREF(dclass_obj);
         nassertv(dclass_this != NULL);
-        
-        dclass = (DCClass *)PyInt_AsLong(dclass_this);
+
+        dclass = (DCClass *)PyLong_AsLong(dclass_this);
         Py_DECREF(dclass_this);
       }
     }

+ 7 - 7
direct/src/ffi/DoGenPyCode.py

@@ -103,17 +103,17 @@ def doGetopts():
     # Extract the args the user passed in
     try:
         opts, pargs = getopt.getopt(sys.argv[1:], 'hvdOC:H:x:Ni:e:p:rns')
-    except Exception, e:
+    except e:
         # User passed in a bad option, print the error and the help, then exit
-        print e
-        print helpString
+        print(e)
+        print(helpString)
         sys.exit()
 
     # Store the option values into our variables
     for opt in opts:
         flag, value = opt
         if (flag == '-h'):
-            print helpString
+            print(helpString)
             sys.exit()
         elif (flag == '-v'):
             if not FFIConstants.notify.getInfo():
@@ -254,7 +254,7 @@ def generateNativeWrappers():
     # Generate a series of "libpandaModules.py" etc. files, one for
     # each named module.
     for moduleName in FFIConstants.CodeModuleNameList:
-        print 'Importing code library: ' + moduleName
+        print('Importing code library: ' + moduleName)
         Dtool_PreloadDLL(moduleName)
         exec('import %s as module' % moduleName)
 
@@ -264,7 +264,7 @@ def generateNativeWrappers():
         # not necessarily downloaded.
         pandaModules.write('try:\n  from %sModules import *\nexcept ImportError, err:\n  if "DLL loader cannot find" not in str(err):\n    raise\n' % (moduleName))
         # Not sure if this message is helpful or annoying.
-        #pandaModules.write('  print "Failed to import %s"\n' % (moduleName))
+        #pandaModules.write('  print("Failed to import %s")\n' % (moduleName))
         pandaModules.write('\n')
 
         moduleModulesFilename = os.path.join(outputCodeDir, '%sModules.py' % (moduleName))
@@ -279,7 +279,7 @@ def generateNativeWrappers():
             if type(classDef) == types.TypeType:
                 extensionFilename = os.path.join(extensionsDir, '%s_extensions.py' % (className))
                 if os.path.exists(extensionFilename):
-                    print '  Found extensions for class: %s' % (className)
+                    print('  Found extensions for class: %s' % (className))
                     extension = open(extensionFilename, 'r')
                     moduleModules.write(extension.read())
                     moduleModules.write('\n')

+ 6 - 6
direct/src/ffi/FFIRename.py

@@ -6,14 +6,14 @@ pythonKeywords = ['and','del','for','is','raise','assert','elif','from','lambda'
 
 
 methodRenameDictionary = {
-    'operator==':  'eq',
-    'operator!=':  'ne',
+    'operator==':  '__eq__',
+    'operator!=':  '__ne__',
     'operator<<':  '__lshift__',
     'operator>>':  '__rshift__',
-    'operator<':   'lessThan',
-    'operator>':   'greaterThan',
-    'operator<=':  'lessThanOrEqual',
-    'operator>=':  'greaterThanOrEqual',
+    'operator<':   '__lt__',
+    'operator>':   '__gt__',
+    'operator<=':  '__le__',
+    'operator>=':  '__ge__',
     'operator=':   'assign',
     'operator()':  '__call__',
     'operator[]':  '__getitem__',

+ 2 - 1
direct/src/showbase/PythonUtil.py

@@ -2479,7 +2479,8 @@ def _getDtoolSuperBase():
     global dtoolSuperBase
     from pandac.PandaModules import PandaNode
     dtoolSuperBase = PandaNode('').__class__.__bases__[0].__bases__[0].__bases__[0]
-    assert repr(dtoolSuperBase) == "<type 'libdtoolconfig.DTOOL_SUPPER_BASE111'>"
+    assert repr(dtoolSuperBase) == "<type 'libdtoolconfig.DTOOL_SUPER_BASE111'>" \
+        or repr(dtoolSuperBase) == "<type 'libdtoolconfig.DTOOL_SUPPER_BASE111'>"
     
 safeReprNotify = None
 

File diff suppressed because it is too large
+ 275 - 31
dtool/metalibs/dtoolconfig/pydtool.cxx


File diff suppressed because it is too large
+ 326 - 315
dtool/src/interrogate/interfaceMakerPythonNative.cxx


+ 12 - 11
dtool/src/interrogate/interfaceMakerPythonNative.h

@@ -95,21 +95,21 @@ private:
                                bool is_inplace, bool coercion_possible);
   
   void write_function_forset(ostream &out, Object *obj, Function *func,
-                             std::set< FunctionRemap *> &remaps, string &expected_params, int indent_level , ostream &forwarddecl,const std::string &functionname, bool inplace) ;
+                             std::set<FunctionRemap*> &remaps, string &expected_params, int indent_level, ostream &forwarddecl, bool inplace);
   
   void pack_return_value(ostream &out, int indent_level,
-                         FunctionRemap *remap, std::string return_expr ,  ostream &forwarddecl, bool in_place);
+                         FunctionRemap *remap, std::string return_expr, ostream &forwarddecl, bool in_place);
   
   void write_make_seq(ostream &out, Object *obj, const std::string &ClassName,
                       MakeSeq *make_seq);
   
   void write_class_prototypes(ostream &out) ;
-  void write_ClasseDeclarations(ostream &out ,  ostream *out_h,Object * obj);
-  void write_ClasseDetails(ostream &out, Object * obj);
+  void write_class_declarations(ostream &out, ostream *out_h, Object *obj);
+  void write_class_details(ostream &out, Object *obj);
   
   void do_assert_init(ostream &out, int &indent_level, bool constructor) const;
 public:
-  bool isRemapLegal( FunctionRemap &remap);
+  bool isRemapLegal(FunctionRemap &remap);
   bool isFunctionLegal( Function *func);
   bool isCppTypeLegal(CPPType *ctype);
   bool isExportThisRun(CPPType *ctype);
@@ -126,19 +126,20 @@ public:
     bool            _is_legal_py_class;
   };
   
-  void   GetValideChildClasses( std::map< std::string ,CastDetails > &answer, CPPStructType * inclass,  const std::string &up_cast_seed = "", bool downcastposible = true);
-  bool   DoesInheritFromIsClass( const CPPStructType * inclass, const std::string &name);
-  bool   IsPandaTypedObject(CPPStructType * inclass) { return DoesInheritFromIsClass(inclass,"TypedObject"); };
+  void GetValideChildClasses( std::map< std::string ,CastDetails > &answer, CPPStructType * inclass,  const std::string &up_cast_seed = "", bool downcastposible = true);
+  bool DoesInheritFromIsClass( const CPPStructType * inclass, const std::string &name);
+  bool IsPandaTypedObject(CPPStructType * inclass) { return DoesInheritFromIsClass(inclass,"TypedObject"); };
   void WriteReturnInstance(ostream &out, int indent_level, std::string &return_expr, std::string &ows_memory_flag,const std::string &class_name, CPPType *ctype, bool inplace, const std::string &const_flag);
   string HasAGetKeyFunction(const InterrogateType &itype_class);
   bool HasAGetClassTypeFunction(const InterrogateType &itype_class);
   int NeedsAStrFunction(const InterrogateType &itype_class);
   int NeedsAReprFunction(const InterrogateType &itype_class);
-  
+  bool NeedsARichCompareFunction(const InterrogateType &itype_class);
+
   void output_quoted(ostream &out, int indent_level, const std::string &str);
   
-  // stash the forwad declarations for this compile pass..
-  std::set< std::string >     _external_imports;    
+  // stash the forward declarations for this compile pass..
+  std::set<std::string>     _external_imports;    
 };
 
 #endif

+ 51 - 9
dtool/src/interrogate/interfaceMakerPythonObj.cxx

@@ -119,15 +119,33 @@ write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def) {
   out << "  { NULL, NULL }\n"
       << "};\n\n"
 
+      << "#if PY_MAJOR_VERSION >= 3\n"
+      << "static struct PyModuleDef python_obj_module = {\n"
+      << "  PyModuleDef_HEAD_INIT,\n"
+      << "  \"" << def->library_name << "\",\n"
+      << "  NULL,\n"
+      << "  -1,\n"
+      << "  python_obj_funcs,\n"
+      << "  NULL, NULL, NULL, NULL\n"
+      << "};\n\n"
+
+      << "#define INIT_FUNC PyObject *PyInit_" << def->library_name << "\n"
+      << "#else\n"
+      << "#define INIT_FUNC void init" << def->library_name << "\n"
+      << "#endif\n\n"
+
       << "#ifdef _WIN32\n"
-      << "extern \"C\" __declspec(dllexport) void init" << def->library_name << "();\n"
+      << "extern \"C\" __declspec(dllexport) INIT_FUNC();\n"
       << "#else\n"
-      << "extern \"C\" void init" << def->library_name << "();\n"
+      << "extern \"C\" INIT_FUNC();\n"
       << "#endif\n\n"
-    
-      << "void init" << def->library_name << "() {\n"
-      << "  Py_InitModule(\"" << def->library_name
-      << "\", python_obj_funcs);\n"
+
+      << "INIT_FUNC() {\n"
+      << "#if PY_MAJOR_VERSION >= 3\n"
+      << "  return PyModule_Create(&python_obj_module);\n"
+      << "#else\n"
+      << "  Py_InitModule(\"" << def->library_name << "\", python_obj_funcs);\n"
+      << "#endif\n"
       << "}\n\n";
 }
 
@@ -225,8 +243,11 @@ write_class_wrapper(ostream &out, InterfaceMaker::Object *object) {
       << "    int i;\n"
       << "    PyObject *bases = PyTuple_New(0);\n"
       << "    PyObject *dict = PyDict_New();\n"
-      << "    PyObject *name = PyString_FromString(\""
-      << python_name << "\");\n"
+      << "#if PY_MAJOR_VERSION >= 3\n"
+      << "    PyObject *name = PyUnicode_FromString(\"" << python_name << "\");\n"
+      << "#else\n"
+      << "    PyObject *name = PyString_FromString(\"" << python_name << "\");\n"
+      << "#endif\n"
       << "    wrapper = PyClass_New(bases, dict, name);\n"
       << "    for (i = 0; i < methods_size; ++i) {\n"
       << "      PyObject *function, *method;\n"
@@ -553,13 +574,24 @@ pack_return_value(ostream &out, int indent_level,
 
   if (remap->_return_type->new_type_is_atomic_string()) {
     if (TypeManager::is_char_pointer(orig_type)) {
+      out << "#if PY_MAJOR_VERSION >= 3\n";
+      indent(out, indent_level)
+        << "return PyUnicode_FromString(" << return_expr << ");\n";
+      out << "#else\n";
       indent(out, indent_level)
         << "return PyString_FromString(" << return_expr << ");\n";
+      out << "#endif\n";
 
     } else {
+      out << "#if PY_MAJOR_VERSION >= 3\n";
+      indent(out, indent_level)
+        << "return PyUnicode_FromStringAndSize("
+        << return_expr << ".data(), (Py_ssize_t)" << return_expr << ".length());\n";
+      out << "#else\n";
       indent(out, indent_level)
         << "return PyString_FromStringAndSize("
-        << return_expr << ".data(), " << return_expr << ".length());\n";
+        << return_expr << ".data(), (Py_ssize_t)" << return_expr << ".length());\n";
+      out << "#endif\n";
     }
 
   } else if (TypeManager::is_bool(type)) {
@@ -579,16 +611,26 @@ pack_return_value(ostream &out, int indent_level,
       << "return PyLong_FromUnsignedLong(" << return_expr << ");\n";
 
   } else if (TypeManager::is_integer(type)) {
+    out << "#if PY_MAJOR_VERSION >= 3\n";
+    indent(out, indent_level)
+      << "return PyLong_FromLong(" << return_expr << ");\n";
+    out << "#else\n";
     indent(out, indent_level)
       << "return PyInt_FromLong(" << return_expr << ");\n";
+    out << "#endif\n";
 
   } else if (TypeManager::is_float(type)) {
     indent(out, indent_level)
       << "return PyFloat_FromDouble(" << return_expr << ");\n";
 
   } else if (TypeManager::is_char_pointer(type)) {
+    out << "#if PY_MAJOR_VERSION >= 3\n";
+    indent(out, indent_level)
+      << "return PyUnicode_FromString(" << return_expr << ");\n";
+    out << "#else\n";
     indent(out, indent_level)
       << "return PyString_FromString(" << return_expr << ");\n";
+    out << "#endif\n";
 
   } else if (TypeManager::is_pointer(type)) {
     bool caller_manages = remap->_return_value_needs_management;

+ 48 - 9
dtool/src/interrogate/interfaceMakerPythonSimple.cxx

@@ -99,22 +99,40 @@ write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def) {
     Function::Remaps::const_iterator ri;
     for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
       FunctionRemap *remap = (*ri);
-      out << "  { \"" << remap->_reported_name << "\", &" 
+      out << "  { \"" << remap->_reported_name << "\", &"
           << remap->_wrapper_name << ", METH_VARARGS },\n";
     }
-  }  
+  }
   out << "  { NULL, NULL }\n"
       << "};\n\n"
 
+      << "#if PY_MAJOR_VERSION >= 3\n"
+      << "static struct PyModuleDef python_simple_module = {\n"
+      << "  PyModuleDef_HEAD_INIT,\n"
+      << "  \"" << def->library_name << "\",\n"
+      << "  NULL,\n"
+      << "  -1,\n"
+      << "  python_simple_funcs,\n"
+      << "  NULL, NULL, NULL, NULL\n"
+      << "};\n\n"
+
+      << "#define INIT_FUNC PyObject *PyInit_" << def->library_name << "\n"
+      << "#else\n"
+      << "#define INIT_FUNC void init" << def->library_name << "\n"
+      << "#endif\n\n"
+
       << "#ifdef _WIN32\n"
-      << "extern \"C\" __declspec(dllexport) void init" << def->library_name << "();\n"
+      << "extern \"C\" __declspec(dllexport) INIT_FUNC();\n"
       << "#else\n"
-      << "extern \"C\" void init" << def->library_name << "();\n"
+      << "extern \"C\" INIT_FUNC();\n"
       << "#endif\n\n"
-    
-      << "void init" << def->library_name << "() {\n"
-      << "  Py_InitModule(\"" << def->library_name
-      << "\", python_simple_funcs);\n"
+
+      << "INIT_FUNC() {\n"
+      << "#if PY_MAJOR_VERSION >= 3\n"
+      << "  return PyModule_Create(&python_simple_module);\n"
+      << "#else\n"
+      << "  Py_InitModule(\"" << def->library_name << "\", python_simple_funcs);\n"
+      << "#endif\n"
       << "}\n\n";
 }
 
@@ -452,8 +470,13 @@ pack_return_value(ostream &out, int indent_level,
   if (remap->_return_type->new_type_is_atomic_string()) 
   {
     if (TypeManager::is_char_pointer(orig_type)) {
+      out << "#if PY_MAJOR_VERSION >= 3\n";
+      indent(out, indent_level)
+        << "return PyUnicode_FromString(" << return_expr << ");\n";
+      out << "#else\n";
       indent(out, indent_level)
         << "return PyString_FromString(" << return_expr << ");\n";
+      out << "#endif\n";
 
     } else if (TypeManager::is_wstring(orig_type)) {
       indent(out, indent_level)
@@ -461,9 +484,15 @@ pack_return_value(ostream &out, int indent_level,
         << return_expr << ".data(), (int)" << return_expr << ".length());\n";
 
     } else {
+      out << "#if PY_MAJOR_VERSION >= 3\n";
+      indent(out, indent_level)
+        << "return PyUnicode_FromStringAndSize("
+        << return_expr << ".data(), (Py_ssize_t)" << return_expr << ".length());\n";
+      out << "#else\n";
       indent(out, indent_level)
         << "return PyString_FromStringAndSize("
-        << return_expr << ".data(), " << return_expr << ".length());\n";
+        << return_expr << ".data(), (Py_ssize_t)" << return_expr << ".length());\n";
+      out << "#endif\n";
     }
 
   } else if (TypeManager::is_bool(type)) {
@@ -485,16 +514,26 @@ pack_return_value(ostream &out, int indent_level,
       << "return PyLong_FromUnsignedLong(" << return_expr << ");\n";
 
   } else if (TypeManager::is_integer(type)) {
+    out << "#if PY_MAJOR_VERSION >= 3\n";
+    indent(out, indent_level)
+      << "return PyLong_FromLong(" << return_expr << ");\n";
+    out << "#else\n";
     indent(out, indent_level)
       << "return PyInt_FromLong(" << return_expr << ");\n";
+    out << "#endif\n";
 
   } else if (TypeManager::is_float(type)) {
     indent(out, indent_level)
       << "return PyFloat_FromDouble(" << return_expr << ");\n";
 
   } else if (TypeManager::is_char_pointer(type)) {
+    out << "#if PY_MAJOR_VERSION >= 3\n";
+    indent(out, indent_level)
+      << "return PyUnicode_FromString(" << return_expr << ");\n";
+    out << "#else\n";
     indent(out, indent_level)
       << "return PyString_FromString(" << return_expr << ");\n";
+    out << "#endif\n";
 
   } else if (TypeManager::is_pointer_to_PyObject(type)) {
     indent(out, indent_level)

+ 10 - 13
dtool/src/interrogate/interrogateBuilder.cxx

@@ -51,8 +51,8 @@
 #include <algorithm>
 
 InterrogateBuilder builder;
-std::string     EXPORT_IMPORT_PREFEX;
-bool            inside_python_native = false;
+std::string EXPORT_IMPORT_PREFIX;
+bool inside_python_native = false;
 
 ////////////////////////////////////////////////////////////////////
 //     Function: InterrogateBuilder::add_source_file
@@ -332,16 +332,15 @@ void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, Int
     makers.push_back(maker);
   }
 
-  if (build_python_native  ) {
+  if (build_python_native) {
     InterfaceMakerPythonNative *maker = new InterfaceMakerPythonNative(def);
     makers.push_back(maker);
   }
 
-
-  EXPORT_IMPORT_PREFEX = std::string("EXPCL_") + def->module_name;
-  for (size_t i=0; i<EXPORT_IMPORT_PREFEX.size(); i++)
-      EXPORT_IMPORT_PREFEX[i] = toupper(EXPORT_IMPORT_PREFEX[i]);
-
+  EXPORT_IMPORT_PREFIX = std::string("EXPCL_") + def->module_name;
+  for (size_t i = 0; i < EXPORT_IMPORT_PREFIX.size(); i++) {
+    EXPORT_IMPORT_PREFIX[i] = toupper(EXPORT_IMPORT_PREFIX[i]);
+  }
 
   InterfaceMakers::iterator mi;
   // First, make all the wrappers.
@@ -359,12 +358,10 @@ void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, Int
   }
 
   // Now, begin the actual output.  Start with the #include lines.
-
-  if (!no_database) 
-  {
+  if (!no_database) {
     out_code << "#include \"dtoolbase.h\"\n"
-        << "#include \"interrogate_request.h\"\n"
-        << "#include \"dconfig.h\"\n";
+             << "#include \"interrogate_request.h\"\n"
+             << "#include \"dconfig.h\"\n";
   }
 
 

+ 27 - 6
dtool/src/interrogate/interrogate_module.cxx

@@ -110,7 +110,7 @@ int write_python_table_native(ostream &out) {
   pset<std::string >::iterator ii;
   for(ii = Libraries.begin(); ii != Libraries.end(); ii++) {
       printf("Referencing Library %s\n",(*ii).c_str());
-      out << "extern LibrayDef "<< *ii << "_moddef ;\n";
+      out << "extern LibraryDef "<< *ii << "_moddef ;\n";
   }
 
   out << "#ifdef _WIN32\n"
@@ -124,7 +124,7 @@ int write_python_table_native(ostream &out) {
     out << "    in_interpreter = 1;\n";
   }
 
-  out << "  LibrayDef   *defs[] = {";
+  out << "  LibraryDef   *defs[] = {";
   for(ii = Libraries.begin(); ii != Libraries.end(); ii++)
     out << "&"<< *ii << "_moddef,";
 
@@ -217,17 +217,38 @@ int write_python_table(ostream &out) {
   out << "  { NULL, NULL }\n"
       << "};\n\n"
 
+      << "#if PY_MAJOR_VERSION >= 3\n"
+      << "static struct PyModuleDef python_module = {\n"
+      << "  PyModuleDef_HEAD_INIT,\n"
+      << "  \"" << library_name << "\",\n"
+      << "  NULL,\n"
+      << "  -1,\n"
+      << "  python_methods,\n"
+      << "  NULL, NULL, NULL, NULL\n"
+      << "};\n\n"
+
+      << "#define INIT_FUNC PyObject *PyInit_" << library_name << "\n"
+      << "#else\n"
+      << "#define INIT_FUNC void init" << library_name << "\n"
+      << "#endif\n\n"
+
       << "#ifdef _WIN32\n"
-      << "extern \"C\" __declspec(dllexport) void init" << library_name << "();\n"
+      << "extern \"C\" __declspec(dllexport) INIT_FUNC();\n"
       << "#else\n"
-      << "extern \"C\" void init" << library_name << "();\n"
+      << "extern \"C\" INIT_FUNC();\n"
       << "#endif\n\n"
 
-      << "void init" << library_name << "() {\n";
+      << "INIT_FUNC() {\n";
+
   if (track_interpreter) {
     out << "  in_interpreter = 1;\n";
   }
-  out << "  Py_InitModule(\"" << library_name << "\", python_methods);\n"
+
+  out << "#if PY_MAJOR_VERSION >= 3\n"
+      << "  return PyModule_Create(&python_module);\n"
+      << "#else\n"
+      << "  Py_InitModule(\"" << library_name << "\", python_methods);\n"
+      << "#endif\n"
       << "}\n\n";
 
   return count;

+ 48 - 57
dtool/src/interrogatedb/dtool_super_base.cxx

@@ -16,80 +16,71 @@
 
 #ifdef HAVE_PYTHON
   
-class EmptyClass
-{
+class EmptyClass {
 };
-Define_Module_Class_Private(dtoolconfig,DTOOL_SUPPER_BASE,EmptyClass,DTOOL_SUPPER_BASE111);
+Define_Module_Class_Private(dtoolconfig, DTOOL_SUPER_BASE, EmptyClass, DTOOL_SUPER_BASE111);
 
-static PyObject * GetSupperBase(PyObject * self)
-{
-    Py_INCREF(&(Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject())); // order is important .. this is used for static functions
-    return  (PyObject *)&Dtool_DTOOL_SUPPER_BASE;
+static PyObject *GetSuperBase(PyObject *self) {
+  Py_INCREF(&(Dtool_DTOOL_SUPER_BASE.As_PyTypeObject())); // order is important .. this is used for static functions
+  return (PyObject *) &Dtool_DTOOL_SUPER_BASE;
 };
 
-
-PyMethodDef Dtool_Methods_DTOOL_SUPPER_BASE[]= {
-  { "DtoolGetSupperBase",(PyCFunction ) &GetSupperBase, METH_NOARGS,"Will Return SUPPERbase Class"},
+PyMethodDef Dtool_Methods_DTOOL_SUPER_BASE[] = {
+  { "DtoolGetSuperBase", (PyCFunction) &GetSuperBase, METH_NOARGS, "Will Return SUPERbase Class"},
   { NULL, NULL }
 };
 
-static long  DTool_HashKey_Methods_DTOOL_SUPPER_BASE(PyObject * self)
-{
-    void * local_this =DTOOL_Call_GetPointerThis(self);
-    if(local_this == NULL)
-    {
-       return -1;
-    };
-    return (long)local_this;
+static Py_hash_t DTool_HashKey_Methods_DTOOL_SUPER_BASE(PyObject *self) {
+  void *local_this = DTOOL_Call_GetPointerThis(self);
+  if (local_this == NULL) {
+    return -1;
+  }
+  return (Py_hash_t) local_this;
 };
 
-
-inline void Dtool_PyModuleClassInit_DTOOL_SUPPER_BASE(PyObject *module)
-{
-    static bool initdone = false;
-    if(!initdone)
-    {
-
-        initdone = true;
-        Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject().tp_dict = PyDict_New();
-        PyDict_SetItemString(Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject().tp_dict,"DtoolClassDict",Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject().tp_dict);
-
-        // __hash__
-        Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject().tp_hash = &DTool_HashKey_Methods_DTOOL_SUPPER_BASE;
-        Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject().tp_compare = &DTOOL_PyObject_Compare;
-
-        if(PyType_Ready(&Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject()) < 0)
-        {
-             PyErr_SetString(PyExc_TypeError, "PyType_Ready(Dtool_DTOOL_SUPPER_BASE)");
-             return;
-        }
-        Py_INCREF(&Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject());
-
-        PyDict_SetItemString(Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject().tp_dict,"DtoolGetSupperBase",PyCFunction_New(&Dtool_Methods_DTOOL_SUPPER_BASE[0],&Dtool_DTOOL_SUPPER_BASE.As_PyObject()));
-
+inline void Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(PyObject *module) {
+  static bool initdone = false;
+  if (!initdone) {
+
+    initdone = true;
+    Dtool_DTOOL_SUPER_BASE.As_PyTypeObject().tp_dict = PyDict_New();
+    PyDict_SetItemString(Dtool_DTOOL_SUPER_BASE.As_PyTypeObject().tp_dict, "DtoolClassDict", Dtool_DTOOL_SUPER_BASE.As_PyTypeObject().tp_dict);
+
+    // __hash__
+    Dtool_DTOOL_SUPER_BASE.As_PyTypeObject().tp_hash = &DTool_HashKey_Methods_DTOOL_SUPER_BASE;
+#if PY_MAJOR_VERSION >= 3
+    // Python 3 removed the regular tp_compare function - there is only tp_richcompare.
+    Dtool_DTOOL_SUPER_BASE.As_PyTypeObject().tp_richcompare = &DTOOL_PyObject_RichCompare;
+#else
+    Dtool_DTOOL_SUPER_BASE.As_PyTypeObject().tp_compare = &DTOOL_PyObject_Compare;
+#endif
+
+    if (PyType_Ready(&Dtool_DTOOL_SUPER_BASE.As_PyTypeObject()) < 0) {
+      PyErr_SetString(PyExc_TypeError, "PyType_Ready(Dtool_DTOOL_SUPER_BASE)");
+      return;
     }
+    Py_INCREF(&Dtool_DTOOL_SUPER_BASE.As_PyTypeObject());
 
-    if(module != NULL)
-    {
-        Py_INCREF(&Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject());
-        PyModule_AddObject(module, "DTOOL_SUPPER_BASE",(PyObject *)&Dtool_DTOOL_SUPPER_BASE.As_PyTypeObject());
-    }
+    PyDict_SetItemString(Dtool_DTOOL_SUPER_BASE.As_PyTypeObject().tp_dict, "DtoolGetSuperBase", PyCFunction_New(&Dtool_Methods_DTOOL_SUPER_BASE[0], &Dtool_DTOOL_SUPER_BASE.As_PyObject()));
+  }
+
+  if (module != NULL) {
+    Py_INCREF(&Dtool_DTOOL_SUPER_BASE.As_PyTypeObject());
+    PyModule_AddObject(module, "DTOOL_SUPER_BASE", (PyObject *)&Dtool_DTOOL_SUPER_BASE.As_PyTypeObject());
+  }
 }
 
-inline void  * Dtool_DowncastInterface_DTOOL_SUPPER_BASE(void *from_this, Dtool_PyTypedObject *from_type)
-{
-    return (void *) NULL;
+inline void *Dtool_DowncastInterface_DTOOL_SUPER_BASE(void *from_this, Dtool_PyTypedObject *from_type) {
+  return (void *) NULL;
 }
 
-inline void  * Dtool_UpcastInterface_DTOOL_SUPPER_BASE(PyObject *self, Dtool_PyTypedObject *requested_type)
-{
-    return NULL;
+inline void *Dtool_UpcastInterface_DTOOL_SUPER_BASE(PyObject *self, Dtool_PyTypedObject *requested_type) {
+  return NULL;
 }
 
-int  Dtool_Init_DTOOL_SUPPER_BASE(PyObject *self, PyObject *args, PyObject *kwds)
-{
-       PyErr_SetString(PyExc_TypeError, "Error Can Not Init SUPPER BASE");
-       return -1;
+int Dtool_Init_DTOOL_SUPER_BASE(PyObject *self, PyObject *args, PyObject *kwds) {
+  PyErr_SetString(PyExc_TypeError, "cannot init super base");
+  return -1;
 }
 
 #endif  // HAVE_PYTHON

+ 319 - 321
dtool/src/interrogatedb/py_panda.cxx

@@ -26,21 +26,20 @@ PyMemberDef standard_type_members[] = {
   {NULL}  /* Sentinel */
 };
 
-
 ////////////////////////////////////////////////////////////////////////
 /// Simple Recognition Functions..
 ////////////////////////////////////////////////////////////////////////
-bool DtoolCanThisBeAPandaInstance(PyObject *self)
-{
-    // simple sanity check for the class type..size.. will stop basic foobars..
-    if(self->ob_type->tp_basicsize >= (int)sizeof(Dtool_PyInstDef))
-    {
-        Dtool_PyInstDef * pyself = (Dtool_PyInstDef *) self;
-        if(pyself->_signature == PY_PANDA_SIGNATURE)
-            return true;
+bool DtoolCanThisBeAPandaInstance(PyObject *self) {
+  // simple sanity check for the class type..size.. will stop basic foobars..
+  if (Py_TYPE(self)->tp_basicsize >= (int)sizeof(Dtool_PyInstDef)) {
+    Dtool_PyInstDef *pyself = (Dtool_PyInstDef *) self;
+    if (pyself->_signature == PY_PANDA_SIGNATURE) {
+      return true;
     }
-    return false;
+  }
+  return false;
 }
+
 ////////////////////////////////////////////////////////////////////////
 //  Function : DTOOL_Call_ExtractThisPointerForType
 //
@@ -48,13 +47,13 @@ bool DtoolCanThisBeAPandaInstance(PyObject *self)
 //      needed by the Dtool py interface.. Be very careful if you muck with these
 //      as the generated code depends on how this is set up..
 ////////////////////////////////////////////////////////////////////////
-void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject * classdef, void ** answer)
-{
-    if(DtoolCanThisBeAPandaInstance(self))
-        *answer = ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self,classdef);
-    else
-        answer = NULL;
-};
+void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject *classdef, void **answer) {
+  if (DtoolCanThisBeAPandaInstance(self)) {
+    *answer = ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self,classdef);
+  } else {
+    *answer = NULL;
+  }
+}
 
 ////////////////////////////////////////////////////////////////////
 //     Function: attempt_coercion
@@ -192,15 +191,23 @@ DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
           
           PyObject *fname = PyObject_GetAttrString((PyObject *)classdef, "__name__");
           if (fname != (PyObject *)NULL) {
+#if PY_MAJOR_VERSION >= 3
+            str << PyUnicode_AsUTF8(fname);
+#else
             str << PyString_AsString(fname);
+#endif
             Py_DECREF(fname);
           } else {
             str << classdef->_name;
           }
           
-          PyObject *tname = PyObject_GetAttrString((PyObject *)self->ob_type, "__name__");
+          PyObject *tname = PyObject_GetAttrString((PyObject *)Py_TYPE(self), "__name__");
           if (tname != (PyObject *)NULL) {
+#if PY_MAJOR_VERSION >= 3
+            str << ", not " << PyUnicode_AsUTF8(tname);
+#else
             str << ", not " << PyString_AsString(tname);
+#endif
             Py_DECREF(tname);
           } else {
             str << ", not " << my_type->_name;
@@ -226,15 +233,23 @@ DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
         
         PyObject *fname = PyObject_GetAttrString((PyObject *)classdef, "__name__");
         if (fname != (PyObject *)NULL) {
+#if PY_MAJOR_VERSION >= 3
+          str << PyUnicode_AsUTF8(fname);
+#else
           str << PyString_AsString(fname);
+#endif
           Py_DECREF(fname);
         } else {
           str << classdef->_name;
         }
         
-        PyObject *tname = PyObject_GetAttrString((PyObject *)self->ob_type, "__name__");
+        PyObject *tname = PyObject_GetAttrString((PyObject *)Py_TYPE(self), "__name__");
         if (tname != (PyObject *)NULL) {
+#if PY_MAJOR_VERSION >= 3
+          str << ", not " << PyUnicode_AsUTF8(tname);
+#else
           str << ", not " << PyString_AsString(tname);
+#endif
           Py_DECREF(tname);
         }
         
@@ -244,26 +259,23 @@ DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
     }
   } else {
     if (report_errors) {
-      PyErr_SetString(PyExc_TypeError, "Self Is Null"); 
+      PyErr_SetString(PyExc_TypeError, "self is NULL"); 
     }
   }
 
   return NULL;
 }
 
-void * DTOOL_Call_GetPointerThis(PyObject *self)
-{
-  if(self != NULL)
-  {
-      if(DtoolCanThisBeAPandaInstance(self))
-      {
-        Dtool_PyInstDef * pyself = (Dtool_PyInstDef *) self;
-        return pyself->_ptr_to_object;
-      }
+void *DTOOL_Call_GetPointerThis(PyObject *self) {
+  if (self != NULL) {
+    if (DtoolCanThisBeAPandaInstance(self)) {
+      Dtool_PyInstDef * pyself = (Dtool_PyInstDef *) self;
+      return pyself->_ptr_to_object;
+    }
   }
 
   return NULL;
-};
+}
 
 ////////////////////////////////////////////////////////////////////////
 //  Function : DTool_CreatePyInstanceTyped
@@ -271,128 +283,113 @@ void * DTOOL_Call_GetPointerThis(PyObject *self)
 // this function relies on the behavior of typed objects in the panda system. 
 //
 ////////////////////////////////////////////////////////////////////////
-PyObject * DTool_CreatePyInstanceTyped(void * local_this_in, Dtool_PyTypedObject & known_class_type, bool memory_rules, bool is_const, int RunTimeType)
-{     
-    if(local_this_in == NULL )
-    {
-        // Lets don't be stupid..
-        PyErr_SetString(PyExc_TypeError, "C Function Return Null 'this'");
-        return NULL;
-    }
-   /////////////////////////////////////////////////////
-   // IF the calss is posibly a run time typed object
-   /////////////////////////////////////////////////////
-    if(RunTimeType > 0)
-    {
-       /////////////////////////////////////////////////////
-       // get best fit class...
-       /////////////////////////////////////////////////////
-        Dtool_PyTypedObject * target_class = Dtool_RuntimeTypeDtoolType(RunTimeType);
-        if(target_class != NULL)
-        {
-           /////////////////////////////////////////////////////
-           // cast to the type...
-           //////////////////////////////////////////////////////
-            void * new_local_this = target_class->_Dtool_DowncastInterface(local_this_in,&known_class_type);
-            if(new_local_this != NULL)
-            {
-                /////////////////////////////////////////////
-                // ask class to allocate a instance..
-                /////////////////////////////////////////////
-                Dtool_PyInstDef * self = (Dtool_PyInstDef *) target_class->As_PyTypeObject().tp_new(&target_class->As_PyTypeObject(), NULL,NULL);
-                if(self != NULL)
-                {
-                    self->_ptr_to_object = new_local_this;
-                    self->_memory_rules = memory_rules;
-                    self->_is_const = is_const;
-                    self->_signature = PY_PANDA_SIGNATURE;
-                    self->_My_Type = target_class;    
-                    return (PyObject *)self;
-                }             
-            }
-        }
-    }
+PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject & known_class_type, bool memory_rules, bool is_const, int RunTimeType) {     
+  if (local_this_in == NULL) {
+    // Let's not be stupid..
+    PyErr_SetString(PyExc_TypeError, "C Function Return Null 'this'");
+    return NULL;
+  }
 
+  /////////////////////////////////////////////////////
+  // IF the class is possibly a run time typed object
+  /////////////////////////////////////////////////////
+  if (RunTimeType > 0) {
     /////////////////////////////////////////////////////
-    // if we get this far .. just wrap the thing in the known type ??
-    //    better than aborting...I guess....
+    // get best fit class...
     /////////////////////////////////////////////////////
-    Dtool_PyInstDef * self = (Dtool_PyInstDef *) known_class_type.As_PyTypeObject().tp_new(&known_class_type.As_PyTypeObject(), NULL,NULL);
-    if(self != NULL)
-    {
-        self->_ptr_to_object = local_this_in;
-        self->_memory_rules = memory_rules;
-        self->_is_const = is_const;
-        self->_signature = PY_PANDA_SIGNATURE;
-        self->_My_Type = &known_class_type;    
+    Dtool_PyTypedObject *target_class = Dtool_RuntimeTypeDtoolType(RunTimeType);
+    if (target_class != NULL) {
+      /////////////////////////////////////////////////////
+      // cast to the type...
+      //////////////////////////////////////////////////////
+      void *new_local_this = target_class->_Dtool_DowncastInterface(local_this_in, &known_class_type);
+      if (new_local_this != NULL) {
+        /////////////////////////////////////////////
+        // ask class to allocate an instance..
+        /////////////////////////////////////////////
+        Dtool_PyInstDef *self = (Dtool_PyInstDef *) target_class->As_PyTypeObject().tp_new(&target_class->As_PyTypeObject(), NULL, NULL);
+        if (self != NULL) {
+          self->_ptr_to_object = new_local_this;
+          self->_memory_rules = memory_rules;
+          self->_is_const = is_const;
+          self->_signature = PY_PANDA_SIGNATURE;
+          self->_My_Type = target_class;
+          return (PyObject *)self;
+        }             
+      }
     }
-    return (PyObject *)self;
-};
+  }
+
+  /////////////////////////////////////////////////////
+  // if we get this far .. just wrap the thing in the known type ??
+  //    better than aborting...I guess....
+  /////////////////////////////////////////////////////
+  Dtool_PyInstDef * self = (Dtool_PyInstDef *) known_class_type.As_PyTypeObject().tp_new(&known_class_type.As_PyTypeObject(), NULL, NULL);
+  if (self != NULL) {
+    self->_ptr_to_object = local_this_in;
+    self->_memory_rules = memory_rules;
+    self->_is_const = is_const;
+    self->_signature = PY_PANDA_SIGNATURE;
+    self->_My_Type = &known_class_type;    
+  }
+  return (PyObject *)self;
+}
 
 ////////////////////////////////////////////////////////////////////////
 // DTool_CreatePyInstance .. wrapper function to finalize the existance of a general 
 //    dtool py instance..
 ////////////////////////////////////////////////////////////////////////
-PyObject * DTool_CreatePyInstance(void * local_this, Dtool_PyTypedObject & in_classdef, bool memory_rules, bool is_const)
-{    
-    if(local_this == NULL)
-    {
-        PyErr_SetString(PyExc_TypeError, "C Function Return Null 'this' ");
-        return NULL;
-    }
+PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyTypedObject &in_classdef, bool memory_rules, bool is_const) {
+  if (local_this == NULL) {
+    PyErr_SetString(PyExc_TypeError, "C Function Return Null 'this'");
+    return NULL;
+  }
 
-    Dtool_PyTypedObject * classdef = &in_classdef;
-    Dtool_PyInstDef * self = (Dtool_PyInstDef *) classdef->As_PyTypeObject().tp_new(&classdef->As_PyTypeObject(), NULL,NULL);
-    if(self != NULL)
-    {
-        self->_ptr_to_object = local_this;
-        self->_memory_rules = memory_rules;
-        self->_is_const = is_const;
-        self->_My_Type = classdef;    
-    } 
-    return (PyObject *)self;
-};
+  Dtool_PyTypedObject *classdef = &in_classdef;
+  Dtool_PyInstDef *self = (Dtool_PyInstDef *) classdef->As_PyTypeObject().tp_new(&classdef->As_PyTypeObject(), NULL, NULL);
+  if (self != NULL) {
+    self->_ptr_to_object = local_this;
+    self->_memory_rules = memory_rules;
+    self->_is_const = is_const;
+    self->_My_Type = classdef;    
+  } 
+  return (PyObject *)self;
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 /// Th Finalizer for simple instances..
 ///////////////////////////////////////////////////////////////////////////////
-int  DTool_PyInit_Finalize(PyObject * self, void * This, Dtool_PyTypedObject *type, bool memory_rules, bool is_const)
-{
-    // lets put some code in here that checks to see the memory is properly configured..
-    // prior to my call ..
-
-    ((Dtool_PyInstDef *)self)->_My_Type = type;
-    ((Dtool_PyInstDef *)self)->_ptr_to_object = This;
-    ((Dtool_PyInstDef *)self)->_memory_rules = memory_rules;
-    ((Dtool_PyInstDef *)self)->_is_const = is_const;
-    return 0;
+int DTool_PyInit_Finalize(PyObject *self, void *local_this, Dtool_PyTypedObject *type, bool memory_rules, bool is_const) {
+  // lets put some code in here that checks to see the memory is properly configured..
+  // prior to my call ..
+
+  ((Dtool_PyInstDef *)self)->_My_Type = type;
+  ((Dtool_PyInstDef *)self)->_ptr_to_object = local_this;
+  ((Dtool_PyInstDef *)self)->_memory_rules = memory_rules;
+  ((Dtool_PyInstDef *)self)->_is_const = is_const;
+  return 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// A heler function to glu methed definition together .. that can not be done at 
-// code generation time becouse of multiple generation passes in interigate..
+// A helper function to glue method definition together .. that can not be done
+// at code generation time because of multiple generation passes in interrogate..
 //
 ///////////////////////////////////////////////////////////////////////////////
-
-void Dtool_Accum_MethDefs(PyMethodDef  in[], MethodDefmap &themap)
-{
-    for(; in->ml_name != NULL; in++)
-    {
-        if(themap.find(in->ml_name) == themap.end())
-        {
-            themap[in->ml_name] = in;
-        }
+void Dtool_Accum_MethDefs(PyMethodDef  in[], MethodDefmap &themap) {
+  for (; in->ml_name != NULL; in++) {
+    if (themap.find(in->ml_name) == themap.end()) {
+      themap[in->ml_name] = in;
     }
+  }
 }   
 
 ///////////////////////////////////////////////////////////////////////////////
-//  ** HACK ** allert..
+//  ** HACK ** alert..
 //
 //      Need to keep a runtime type dictionary ... that is forward declared of typed object.
 //        We rely on the fact that typed objects are uniquly defined by an integer.
 //
 ///////////////////////////////////////////////////////////////////////////////
-
 void
 RegisterRuntimeClass(Dtool_PyTypedObject * otype, int class_id) {
   if (class_id == 0) {
@@ -417,113 +414,126 @@ RegisterRuntimeClass(Dtool_PyTypedObject * otype, int class_id) {
       otype->_Dtool_IsRunTimeCapable = true;
     }
   }
-};
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
-Dtool_PyTypedObject *  Dtool_RuntimeTypeDtoolType(int type)
-{
-    RunTimeTypeDictionary::iterator di = GetRunTimeDictionary().find(type);
-    if(di != GetRunTimeDictionary().end())
-        return di->second;
-    else
-    {
-        int  type2 = get_best_parent_from_Set(type,GetRunTimeTypeList());
-        di = GetRunTimeDictionary().find(type2);
-        if(di != GetRunTimeDictionary().end())
-            return di->second;
+Dtool_PyTypedObject *Dtool_RuntimeTypeDtoolType(int type) {
+  RunTimeTypeDictionary::iterator di = GetRunTimeDictionary().find(type);
+  if (di != GetRunTimeDictionary().end()) {
+      return di->second;
+  } else {
+    int type2 = get_best_parent_from_Set(type, GetRunTimeTypeList());
+    di = GetRunTimeDictionary().find(type2);
+    if (di != GetRunTimeDictionary().end()) {
+      return di->second;
     }
-    return NULL;    
-};
+  }
+  return NULL;    
+}
 
 ///////////////////////////////////////////////////////////////////////////////
-void Dtool_PyModuleInitHelper( LibrayDef   *defs[], const char *  modulename)
-{
-    // the module level function inits....
-    MethodDefmap  functions;
-    for(int xx = 0; defs[xx] != NULL; xx++)
-        Dtool_Accum_MethDefs(defs[xx]->_methods,functions);
-
-    PyMethodDef  *newdef = new PyMethodDef[functions.size()+1];
-    MethodDefmap::iterator mi;
-    int     offset = 0;
-    for(mi = functions.begin(); mi != functions.end(); mi++, offset++)
-        newdef[offset] = *mi->second;
-    newdef[offset].ml_doc = NULL;
-    newdef[offset].ml_name = NULL;
-    newdef[offset].ml_meth = NULL;
-    newdef[offset].ml_flags = 0;
-
-    PyObject * module = Py_InitModule((char *)modulename,newdef);   
-
-    if(module == NULL)
-    {
-         PyErr_SetString(PyExc_TypeError, "Py_InitModule Returned NULL ???"); 
-         return;
-    }
+PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
+  // the module level function inits....
+  MethodDefmap functions;
+  for (int xx = 0; defs[xx] != NULL; xx++) {
+    Dtool_Accum_MethDefs(defs[xx]->_methods, functions);
+  }
+
+  PyMethodDef *newdef = new PyMethodDef[functions.size() + 1];
+  MethodDefmap::iterator mi;
+  int offset = 0;
+  for (mi = functions.begin(); mi != functions.end(); mi++, offset++) {
+    newdef[offset] = *mi->second;
+  }
+  newdef[offset].ml_doc = NULL;
+  newdef[offset].ml_name = NULL;
+  newdef[offset].ml_meth = NULL;
+  newdef[offset].ml_flags = 0;
+
+#if PY_MAJOR_VERSION >= 3
+  struct PyModuleDef moduledef = {
+    PyModuleDef_HEAD_INIT,
+    modulename,
+    NULL,
+    -1,
+    newdef,
+    NULL, NULL, NULL, NULL
+  };
+  PyObject *module = PyModule_Create(&moduledef);
+#else
+  PyObject *module = Py_InitModule((char *)modulename, newdef); 
+#endif  
+
+  if (module == NULL) {
+#if PY_MAJOR_VERSION >= 3
+    PyErr_SetString(PyExc_TypeError, "PyModule_Create returned NULL");
+#else
+    PyErr_SetString(PyExc_TypeError, "Py_InitModule returned NULL");
+#endif
+    return NULL;
+  }
 
 
-    // the constant inits... enums, classes ...
-    for(int y = 0; defs[y] != NULL; y++)
-        defs[y]->_constants(module);
+  // the constant inits... enums, classes ...
+  for (int y = 0; defs[y] != NULL; y++) {
+    defs[y]->_constants(module);
+  }
+
+  PyModule_AddIntConstant(module, "Dtool_PyNativeInterface", 1);
 
-    PyModule_AddIntConstant(module,"Dtool_PyNativeInterface",1);
+  return module;
 }
+
 ///////////////////////////////////////////////////////////////////////////////
-///  HACK.... Be carefull 
+///  HACK.... Be careful
 //
 //  Dtool_BorrowThisReference
 //      This function can be used to grab the "THIS" pointer from an object and use it
 //      Required to support historical inheritance in the form of "is this instance of"..
 //
 ///////////////////////////////////////////////////////////////////////////////
-PyObject * Dtool_BorrowThisReference(PyObject * self, PyObject * args )
-{
-    PyObject *from_in = NULL;
-    PyObject *to_in = NULL;
-    if(PyArg_ParseTuple(args, "OO", &to_in, &from_in)) 
-    {
-
-        if(DtoolCanThisBeAPandaInstance(from_in) && DtoolCanThisBeAPandaInstance(to_in))
-        {
-            Dtool_PyInstDef * from = (Dtool_PyInstDef *) from_in;
-            Dtool_PyInstDef * to = (Dtool_PyInstDef *) to_in;
-            if(from->_My_Type == to->_My_Type)
-            {
-                to->_memory_rules = false;
-                to->_is_const = from->_is_const;
-                to->_ptr_to_object = from->_ptr_to_object;
-                return Py_BuildValue("");
-            }
-            PyErr_SetString(PyExc_TypeError, "Must Be Same Type??"); 
-        }
-        else
-            PyErr_SetString(PyExc_TypeError, "One of these does not appear to be DTOOL Instance ??"); 
+PyObject *Dtool_BorrowThisReference(PyObject *self, PyObject *args) {
+  PyObject *from_in = NULL;
+  PyObject *to_in = NULL;
+  if (PyArg_ParseTuple(args, "OO", &to_in, &from_in)) {
+
+    if (DtoolCanThisBeAPandaInstance(from_in) && DtoolCanThisBeAPandaInstance(to_in)) {
+      Dtool_PyInstDef * from = (Dtool_PyInstDef *) from_in;
+      Dtool_PyInstDef * to = (Dtool_PyInstDef *) to_in;
+      if (from->_My_Type == to->_My_Type) {
+        to->_memory_rules = false;
+        to->_is_const = from->_is_const;
+        to->_ptr_to_object = from->_ptr_to_object;
+        return Py_BuildValue("");
+      }
+      PyErr_SetString(PyExc_TypeError, "Must Be Same Type??");
+    } else {
+      PyErr_SetString(PyExc_TypeError, "One of these does not appear to be DTOOL Instance ??");
     }
-    return (PyObject *) NULL;
+  }
+  return (PyObject *) NULL;
 }
+
 //////////////////////////////////////////////////////////////////////////////////////////////
 // We do expose a dictionay for dtool classes .. this should be removed at some point..
 //////////////////////////////////////////////////////////////////////////////////////////////
-PyObject * Dtool_AddToDictionary(PyObject * self1, PyObject * args )
-{
-
-    PyObject  *     self;
-    PyObject  *     subject;
-    PyObject  *     key;
-    if(PyArg_ParseTuple(args, "OSO", &self, &key, &subject))
-    {
-        PyObject * dict = ((PyTypeObject *)self)->tp_dict;
-        if(dict == NULL && !PyDict_Check(dict))
-            PyErr_SetString(PyExc_TypeError, "No dictionary On Object");
-        else
-            PyDict_SetItem(dict,key,subject);
-
-    }   
-    if(PyErr_Occurred())
-        return (PyObject *)NULL;
-    return Py_BuildValue("");
-
+PyObject *Dtool_AddToDictionary(PyObject *self1, PyObject *args) {
+  PyObject *self;
+  PyObject *subject;
+  PyObject *key;
+  if (PyArg_ParseTuple(args, "OSO", &self, &key, &subject)) {
+    PyObject *dict = ((PyTypeObject *)self)->tp_dict;
+    if (dict == NULL && !PyDict_Check(dict)) {
+      PyErr_SetString(PyExc_TypeError, "No dictionary On Object");
+    } else {
+      PyDict_SetItem(dict,key,subject);
+    }
+  }   
+  if (PyErr_Occurred()) {
+    return (PyObject *)NULL;
+  }
+  return Py_BuildValue("");
 }
 ///////////////////////////////////////////////////////////////////////////////////
 /*
@@ -533,8 +543,8 @@ inline long  DTool_HashKey(PyObject * inst)
     PyObject * func = PyObject_GetAttrString(inst, "__hash__");
     if (func == NULL) 
     {
-        if(DtoolCanThisBeAPandaInstance(inst))
-            if(((Dtool_PyInstDef *)inst)->_ptr_to_object != NULL)
+        if (DtoolCanThisBeAPandaInstance(inst))
+            if (((Dtool_PyInstDef *)inst)->_ptr_to_object != NULL)
                 outcome =  (long)((Dtool_PyInstDef *)inst)->_ptr_to_object;
     }
     else
@@ -569,123 +579,98 @@ inline long  DTool_HashKey(PyObject * inst)
    XXX of error.
 */
 
-int DTOOL_PyObject_Compare_old(PyObject *v1, PyObject *v2)
-{
-    // if we are related..
-    if(PyType_IsSubtype(v1->ob_type, v2->ob_type)) 
-    {
-        void * v1_this = DTOOL_Call_GetPointerThis(v1);
-        void * v2_this = DTOOL_Call_GetPointerThis(v2);
-        if(v1_this != NULL && v2_this != NULL) // both are our types...
-        {
-            PyObject * func = PyObject_GetAttrString(v1, "compareTo");
-            if (func == NULL)
-            {
-                PyErr_Clear();
-            }
-            else
-            {
-                PyObject * res = NULL;
-                PyObject * args = Py_BuildValue("(O)", v2);
-                if (args != NULL)
-                {
-                    res = PyObject_Call(func, args, NULL);
-                    Py_DECREF(args);
-                }
-                Py_DECREF(func);
-                PyErr_Clear(); // just in case the function threw an error
-                // only use if the function  return an INT... hmm
-                if(res != NULL && PyInt_Check(res))
-                {
-                    int answer = PyInt_AsLong(res);
-                    Py_DECREF(res);
-                    return  answer;
-                }
-                if(res != NULL)
-                    Py_DECREF(res);
-
-            };
-            // CompareTo Failed some how :(
-            // do a this compare  .. if Possible...
-            if(v1_this < v2_this)
-                return -1;
-
-            if(v1_this > v2_this)
-                return 1;
-            return 0;
-        }
-        // ok drop to a basic object compare hmmmmmm
+int DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2) {
+  // First try compareTo function..
+  PyObject * func = PyObject_GetAttrString(v1, "compareTo");
+  if (func == NULL) {
+    PyErr_Clear();
+  } else {
+    PyObject *res = NULL;
+    PyObject *args = Py_BuildValue("(O)", v2);
+    if (args != NULL) {
+      res = PyObject_Call(func, args, NULL);
+      Py_DECREF(args);
     }
-    if(v1 < v2)
-        return  -1;
-    if(v1 > v2)
-        return  1;
-    return 0;   
-}
-
-
-
+    Py_DECREF(func);
+    PyErr_Clear(); // just in case the function threw an error
+    // only use if the function returns an INT... hmm
+    if (res != NULL) {
+      if (PyLong_Check(res)) {
+        long answer = PyLong_AsLong(res);
+        Py_DECREF(res);
 
-int DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2)
-{
-    //  First try compare to function..
-    PyObject * func = PyObject_GetAttrString(v1, "compareTo");
-    if (func == NULL)
-    {
-        PyErr_Clear();
-    }
-    else
-    {
-        PyObject * res = NULL;
-        PyObject * args = Py_BuildValue("(O)", v2);
-        if (args != NULL)
-        {
-            res = PyObject_Call(func, args, NULL);
-            Py_DECREF(args);
-        }
-        Py_DECREF(func);
-        PyErr_Clear(); // just in case the function threw an error
-        // only use if the function  return an INT... hmm
-        if(res != NULL && PyInt_Check(res))
-        {
-            int answer = PyInt_AsLong(res);
-            Py_DECREF(res);
-
-            // Python really wants us to return strictly -1, 0, or 1.
-            if (answer < 0) {
-              return -1;
-            } else if (answer > 0) {
-              return 1;
-            } else {
-              return 0;
-            }
+        // Python really wants us to return strictly -1, 0, or 1.
+        if (answer < 0) {
+          return -1;
+        } else if (answer > 0) {
+          return 1;
+        } else {
+          return 0;
         }
-        if(res != NULL)
-            Py_DECREF(res);
+      }
+#if PY_MAJOR_VERSION < 3
+      else if (PyInt_Check(res)) {
+        long answer = PyInt_AsLong(res);
+        Py_DECREF(res);
 
-    };
+        // Python really wants us to return strictly -1, 0, or 1.
+        if (answer < 0) {
+          return -1;
+        } else if (answer > 0) {
+          return 1;
+        } else {
+          return 0;
+        }
+      }
+#endif
+      Py_DECREF(res);
+    }
+  };
 
-    // try this compare
-    void * v1_this = DTOOL_Call_GetPointerThis(v1);
-    void * v2_this = DTOOL_Call_GetPointerThis(v2);
-    if(v1_this != NULL && v2_this != NULL) // both are our types...
-    {
-        if(v1_this < v2_this)
-            return -1;
+  // try this compare
+  void *v1_this = DTOOL_Call_GetPointerThis(v1);
+  void *v2_this = DTOOL_Call_GetPointerThis(v2);
+  if (v1_this != NULL && v2_this != NULL) { // both are our types...
+    if (v1_this < v2_this)
+      return -1;
 
-        if(v1_this > v2_this)
-            return 1;
-        return 0;
-    }
+    if (v1_this > v2_this)
+      return 1;
+    return 0;
+  }
 
-    // ok self compare...
-    if(v1 < v2)
-        return  -1;
-    if(v1 > v2)
-        return  1;
-    return 0;   
+  // ok self compare...
+  if (v1 < v2)
+    return  -1;
+  if (v1 > v2)
+    return  1;
+  return 0;   
 }
 
+PyObject *DTOOL_PyObject_RichCompare(PyObject *v1, PyObject *v2, int op) {
+  int cmpval = DTOOL_PyObject_Compare(v1, v2);
+  bool result;
+  switch (op) {
+  case Py_LT:
+    result = (cmpval < 0);
+    break;
+  case Py_LE:
+    result = (cmpval <= 0);
+    break;
+  case Py_EQ:
+    result = (cmpval == 0);
+    break;
+  case Py_NE:
+    result = (cmpval != 0);
+    break;
+  case Py_GT:
+    result = (cmpval > 0);
+    break;
+  case Py_GE:
+    result = (cmpval >= 0);
+  }
+  return PyBool_FromLong(result);
+}
 
 PyObject *make_list_for_item(PyObject *self, const char *num_name,
                              const char *element_name) {
@@ -693,7 +678,16 @@ PyObject *make_list_for_item(PyObject *self, const char *num_name,
   if (num_result == NULL) {
     return NULL;
   }
-  Py_ssize_t num_elements = PyInt_AsSsize_t(num_result);
+
+#if PY_MAJOR_VERSION >= 3
+  Py_ssize_t num_elements = PyLong_AsSsize_t(num_result);
+#else
+  if (PyLong_Check(num_result)) {
+    Py_ssize_t num_elements = PyLong_AsSsize_t(num_result);
+  } else {
+    Py_ssize_t num_elements = PyInt_AsSsize_t(num_result);
+  }
+#endif
   Py_DECREF(num_result);
   
   PyObject *list = PyList_New(num_elements);
@@ -752,12 +746,16 @@ PyObject *map_deepcopy_to_copy(PyObject *self, PyObject *args) {
 ////////////////////////////////////////////////////////////////////
 EXPCL_DTOOLCONFIG PyObject *
 PyLongOrInt_FromUnsignedLong(unsigned long value) {
+#if PY_MAJOR_VERSION >= 3
+  // Python 3 only has longs.
+  return PyLong_FromUnsignedLong(value);
+#else
   if ((long)value < 0) {
     return PyLong_FromUnsignedLong(value);
   } else {
     return PyInt_FromLong((long)value);
   }
+#endif
 }
 
-
 #endif  // HAVE_PYTHON

+ 175 - 95
dtool/src/interrogatedb/py_panda.h

@@ -83,38 +83,62 @@ inline PyObject* doPy_RETURN_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 more portably defining hash functions.
+typedef long Py_hash_t;
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+#define nb_nonzero nb_bool
+#define nb_divide nb_true_divide
+#define nb_inplace_divide nb_inplace_true_divide
+#endif
+
 using namespace std;
 
-#define PY_PANDA_SMALLER_FOOTPRINT  1
+#define PY_PANDA_SMALLER_FOOTPRINT 1
 
 ///////////////////////////////////////////////////////////////////////////////////
 // this is tempory .. untill this is glued better into the panda build system
 ///////////////////////////////////////////////////////////////////////////////////
 
 #if defined(_WIN32) && !defined(LINK_ALL_STATIC)
-#define EXPORT_THIS  __declspec(dllexport) 
-#define IMPORT_THIS  extern __declspec(dllimport) 
+#define EXPORT_THIS __declspec(dllexport)
+#define IMPORT_THIS extern __declspec(dllimport)
 #else
-#define EXPORT_THIS 
-#define IMPORT_THIS     extern
+#define EXPORT_THIS
+#define IMPORT_THIS extern
 #endif
 ///////////////////////////////////////////////////////////////////////////////////
 
-struct          Dtool_PyTypedObject;
-typedef std::map< int , Dtool_PyTypedObject *>   RunTimeTypeDictionary;
-typedef std::set<int >                           RunTimeTypeList;
-
-EXPCL_DTOOLCONFIG   RunTimeTypeDictionary & GetRunTimeDictionary();
-EXPCL_DTOOLCONFIG   RunTimeTypeList & GetRunTimeTypeList();
+struct Dtool_PyTypedObject;
+typedef std::map<int, Dtool_PyTypedObject *>   RunTimeTypeDictionary;
+typedef std::set<int>                           RunTimeTypeList;
 
+EXPCL_DTOOLCONFIG RunTimeTypeDictionary &GetRunTimeDictionary();
+EXPCL_DTOOLCONFIG RunTimeTypeList &GetRunTimeTypeList();
 
 //////////////////////////////////////////////////////////
 // used to stamp dtool instance.. 
 #define PY_PANDA_SIGNATURE 0xbeaf
-typedef  void * ( * ConvertFunctionType  )(PyObject *,Dtool_PyTypedObject * );
-typedef  void * ( * ConvertFunctionType1  )(void *, Dtool_PyTypedObject *);
-typedef  void   ( *FreeFunction  )(PyObject *);
-typedef  void   ( *PyModuleClassInit)(PyObject *module);
+typedef void * ( * ConvertFunctionType  )(PyObject *,Dtool_PyTypedObject * );
+typedef void * ( * ConvertFunctionType1  )(void *, Dtool_PyTypedObject *);
+typedef void   ( *FreeFunction  )(PyObject *);
+typedef void   ( *PyModuleClassInit)(PyObject *module);
 //inline          Dtool_PyTypedObject *  Dtool_RuntimeTypeDtoolType(int type);
 inline void     Dtool_Deallocate_General(PyObject * self);
 //inline int      DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2);
@@ -124,8 +148,7 @@ inline void     Dtool_Deallocate_General(PyObject * self);
 ////////////////////////////////////////////////////////////////////////
 #ifdef  PY_PANDA_SMALLER_FOOTPRINT
 // this should save   8 bytes per object ....
-struct Dtool_PyInstDef 
-{
+struct Dtool_PyInstDef {
   PyObject_HEAD
   void *_ptr_to_object;
   struct Dtool_PyTypedObject *_My_Type;
@@ -134,8 +157,6 @@ struct Dtool_PyInstDef
   int _is_const     : 1;       // true if this is a "const" pointer.
 };
 
-
-
 #else
 struct Dtool_PyInstDef {
   PyObject_HEAD
@@ -159,7 +180,7 @@ struct Dtool_PyTypedObject {
   // Standard Python Features..
   PyTypeObject _PyType;
 
-  //                  My Class Level Features..
+  // My Class Level Features..
   const char *_name;                             // cpp name for the object
   bool _Dtool_IsRunTimeCapable;                  // derived from TypedObject
   ConvertFunctionType _Dtool_UpcastInterface;    // The Upcast Function By Slot
@@ -172,10 +193,123 @@ struct Dtool_PyTypedObject {
   inline PyObject &As_PyObject() { return (PyObject &)_PyType; };
 };
 
-
 ////////////////////////////////////////////////////////////////////////
 // Macros from Hell..  May want to just add this to the code generator..
 ////////////////////////////////////////////////////////////////////////
+#define Define_Dtool_PyTypedObject(MODULE_NAME, CLASS_NAME, PUBLIC_NAME) \
+  EXPORT_THIS Dtool_PyTypedObject Dtool_##CLASS_NAME =                  \
+    {                                                                   \
+      {                                                                 \
+        PyVarObject_HEAD_INIT(NULL, 0)                                  \
+        "lib" #MODULE_NAME "." #PUBLIC_NAME, /*type name with module */ \
+        sizeof(Dtool_PyInstDef),                /* tp_basicsize */      \
+        0,                                      /* tp_itemsize */       \
+        &Dtool_Deallocate_General,              /* tp_dealloc */        \
+        0,                                      /* tp_print */          \
+        0,                                      /* tp_getattr */        \
+        0,                                      /* tp_setattr */        \
+        0,                                      /* tp_compare */        \
+        0,                                      /* tp_repr */           \
+        &Dtool_PyNumberMethods_##CLASS_NAME,    /* tp_as_number */      \
+        &Dtool_PySequenceMethods_##CLASS_NAME,  /* tp_as_sequence */    \
+        &Dtool_PyMappingMethods_##CLASS_NAME,   /* tp_as_mapping */     \
+        0,                                      /* tp_hash */           \
+        0,                                      /* tp_call */           \
+        0,                                      /* tp_str */            \
+        PyObject_GenericGetAttr,                /* tp_getattro */       \
+        PyObject_GenericSetAttr,                /* tp_setattro */       \
+        0,                                      /* tp_as_buffer */      \
+        (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES), /* tp_flags */ \
+        0,                                      /* tp_doc */            \
+        0,                                      /* tp_traverse */       \
+        0,                                      /* tp_clear */          \
+        0,                                      /* tp_richcompare */    \
+        0,                                      /* tp_weaklistoffset */ \
+        0,                                      /* tp_iter */           \
+        0,                                      /* tp_iternext */       \
+        Dtool_Methods_##CLASS_NAME,             /* tp_methods */        \
+        standard_type_members,                  /* tp_members */        \
+        0,                                      /* tp_getset */         \
+        0,                                      /* tp_base */           \
+        0,                                      /* tp_dict */           \
+        0,                                      /* tp_descr_get */      \
+        0,                                      /* tp_descr_set */      \
+        0,                                      /* tp_dictoffset */     \
+        Dtool_Init_##CLASS_NAME,                /* tp_init */           \
+        PyType_GenericAlloc,                    /* tp_alloc */          \
+        Dtool_new_##CLASS_NAME,                 /* tp_new */            \
+        PyObject_Del,                           /* tp_free */           \
+      },                                                                \
+      #CLASS_NAME,                                                      \
+      false,                                                            \
+      Dtool_UpcastInterface_##CLASS_NAME,                               \
+      Dtool_DowncastInterface_##CLASS_NAME,                             \
+      Dtool_FreeInstance_##CLASS_NAME,                                  \
+      Dtool_PyModuleClassInit_##CLASS_NAME                              \
+    };
+
+#if PY_MAJOR_VERSION >= 3
+#define Define_Dtool_Class(MODULE_NAME, CLASS_NAME, PUBLIC_NAME)        \
+  static PyNumberMethods Dtool_PyNumberMethods_##CLASS_NAME =           \
+    {                                                                   \
+      0,/*binaryfunc nb_add*/                                           \
+      0,/*binaryfunc nb_subtract*/                                      \
+      0,/*binaryfunc nb_multiply*/                                      \
+      0,/*binaryfunc nb_remainder*/                                     \
+      0,/*binaryfunc nb_divmod*/                                        \
+      0,/*ternaryfunc nb_power*/                                        \
+      0,/*unaryfunc nb_negative*/                                       \
+      0,/*unaryfunc nb_positive*/                                       \
+      0,/*unaryfunc nb_absolute*/                                       \
+      0,/*inquiry nb_bool*/                                             \
+      0,/*unaryfunc nb_invert*/                                         \
+      0,/*binaryfunc nb_lshift*/                                        \
+      0,/*binaryfunc nb_rshift*/                                        \
+      0,/*binaryfunc nb_and*/                                           \
+      0,/*binaryfunc nb_xor*/                                           \
+      0,/*binaryfunc nb_or*/                                            \
+      0,/*unaryfunc nb_int*/                                            \
+      0,/*void *nb_reserved*/                                           \
+      0,/*unaryfunc nb_float*/                                          \
+      0,/*binaryfunc nb_inplace_add*/                                   \
+      0,/*binaryfunc nb_inplace_subtract*/                              \
+      0,/*binaryfunc nb_inplace_multiply*/                              \
+      0,/*binaryfunc nb_inplace_remainder*/                             \
+      0,/*ternaryfunc nb_inplace_power*/                                \
+      0,/*binaryfunc nb_inplace_lshift*/                                \
+      0,/*binaryfunc nb_inplace_rshift*/                                \
+      0,/*binaryfunc nb_inplace_and*/                                   \
+      0,/*binaryfunc nb_inplace_xor*/                                   \
+      0,/*binaryfunc nb_inplace_or*/                                    \
+      0,/*binaryfunc nb_floor_divide*/                                  \
+      0,/*binaryfunc nb_true_divide*/                                   \
+      0,/*binaryfunc nb_inplace_floor_divide*/                          \
+      0,/*binaryfunc nb_inplace_true_divide*/                           \
+      0,/*unaryfunc nb_index*/                                          \
+    };                                                                  \
+  static PySequenceMethods Dtool_PySequenceMethods_##CLASS_NAME =       \
+    {                                                                   \
+      0,/*lenfunc sq_length */                                          \
+      0,/*binaryfunc sq_concat */                                       \
+      0,/*ssizeargfunc sq_repeat */                                     \
+      0,/*ssizeargfunc sq_item */                                       \
+      0,/*void *was_sq_slice */                                         \
+      0,/*ssizeargfunc sq_ass_item */                                   \
+      0,/*void *was_sq_ass_slice */                                     \
+      0,/*objobjproc sq_contains */                                     \
+      0,/*binaryfunc sq_inplace_concat */                               \
+      0,/*ssizeargfunc sq_inplace_repeat */                             \
+    };                                                                  \
+  static PyMappingMethods Dtool_PyMappingMethods_##CLASS_NAME =         \
+    {                                                                   \
+      0,/*inquiry mp_length */                                          \
+      0,/*binaryfunc mp_subscript */                                    \
+      0,/*objobjargproc mp_ass_subscript */                             \
+    };                                                                  \
+  Define_Dtool_PyTypedObject(MODULE_NAME, CLASS_NAME, PUBLIC_NAME)
+
+#else // Python 2:
+
 #define Define_Dtool_Class(MODULE_NAME, CLASS_NAME, PUBLIC_NAME)        \
   static PyNumberMethods Dtool_PyNumberMethods_##CLASS_NAME =           \
     {                                                                   \
@@ -235,65 +369,15 @@ struct Dtool_PyTypedObject {
       0,/*binaryfunc mp_subscript */                                    \
       0,/*objobjargproc mp_ass_subscript */                             \
     };                                                                  \
-  EXPORT_THIS Dtool_PyTypedObject Dtool_##CLASS_NAME =                  \
-    {                                                                   \
-      {                                                                 \
-        PyObject_HEAD_INIT(NULL)                                        \
-        0,                                                              \
-        "lib" #MODULE_NAME "." #PUBLIC_NAME, /*type name with module */ \
-        sizeof(Dtool_PyInstDef),                /* tp_basicsize */      \
-        0,                                      /* tp_itemsize */       \
-        &Dtool_Deallocate_General,              /* tp_dealloc */        \
-        0,                                      /* tp_print */          \
-        0,                                      /* tp_getattr */        \
-        0,                                      /* tp_setattr */        \
-        0,                                      /* tp_compare */        \
-        0,                                      /* tp_repr */           \
-        &Dtool_PyNumberMethods_##CLASS_NAME,    /* tp_as_number */      \
-        &Dtool_PySequenceMethods_##CLASS_NAME,  /* tp_as_sequence */    \
-        &Dtool_PyMappingMethods_##CLASS_NAME,   /* tp_as_mapping */     \
-        0,                                      /* tp_hash */           \
-        0,                                      /* tp_call */           \
-        0,                                      /* tp_str */            \
-        PyObject_GenericGetAttr,                /* tp_getattro */       \
-        PyObject_GenericSetAttr,                /* tp_setattro */       \
-        0,                                      /* tp_as_buffer */      \
-        (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES), /* tp_flags */ \
-        0,                                      /* tp_doc */            \
-        0,                                      /* tp_traverse */       \
-        0,                                      /* tp_clear */          \
-        0,                                      /* tp_richcompare */    \
-        0,                                      /* tp_weaklistoffset */ \
-        0,                                      /* tp_iter */           \
-        0,                                      /* tp_iternext */       \
-        Dtool_Methods_##CLASS_NAME,             /* tp_methods */        \
-        standard_type_members,                  /* tp_members */        \
-        0,                                      /* tp_getset */         \
-        0,                                      /* tp_base */           \
-        0,                                      /* tp_dict */           \
-        0,                                      /* tp_descr_get */      \
-        0,                                      /* tp_descr_set */      \
-        0,                                      /* tp_dictoffset */     \
-        Dtool_Init_##CLASS_NAME,                /* tp_init */           \
-        PyType_GenericAlloc,                    /* tp_alloc */          \
-        Dtool_new_##CLASS_NAME,                 /* tp_new */            \
-        _PyObject_Del,                          /* tp_free */           \
-      },                                                                \
-      #CLASS_NAME,                                                      \
-      false,                                                            \
-      Dtool_UpcastInterface_##CLASS_NAME,                               \
-      Dtool_DowncastInterface_##CLASS_NAME,                             \
-      Dtool_FreeInstance_##CLASS_NAME,                                  \
-      Dtool_PyModuleClassInit_##CLASS_NAME                              \
-    }; 
-
+  Define_Dtool_PyTypedObject(MODULE_NAME, CLASS_NAME, PUBLIC_NAME)
+#endif
 
 ////////////////////////////////////////////////////////////////////////
 // The Fast Deallocator.. for Our instances..
 ////////////////////////////////////////////////////////////////////////
 inline void Dtool_Deallocate_General(PyObject * self) {
   ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_FreeInstance(self);
-  self->ob_type->tp_free(self);
+  Py_TYPE(self)->tp_free(self);
 }
 
 ////////////////////////////////////////////////////////////////////////
@@ -367,12 +451,11 @@ EXPCL_DTOOLCONFIG bool DtoolCanThisBeAPandaInstance(PyObject *self);
 ////////////////////////////////////////////////////////////////////////
 EXPCL_DTOOLCONFIG void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject * classdef, void ** answer);
 
+EXPCL_DTOOLCONFIG void *DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, int param, const string &function_name, bool const_ok, PyObject **coerced, bool report_errors);
 
-EXPCL_DTOOLCONFIG void * DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject  *classdef, int param, const string &function_name, bool const_ok, PyObject **coerced, bool report_errors);
-
-EXPCL_DTOOLCONFIG void * DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject  *classdef, int param, const string &function_name, bool const_ok, PyObject **coerced);
+EXPCL_DTOOLCONFIG void *DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, int param, const string &function_name, bool const_ok, PyObject **coerced);
 
-EXPCL_DTOOLCONFIG void * DTOOL_Call_GetPointerThis(PyObject *self);
+EXPCL_DTOOLCONFIG void *DTOOL_Call_GetPointerThis(PyObject *self);
 
 ////////////////////////////////////////////////////////////////////////
 //  Function : DTool_CreatePyInstanceTyped
@@ -396,7 +479,7 @@ EXPCL_DTOOLCONFIG PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyTyp
 //struct Dtool_PyTypedObject Dtool_##CLASS_NAME;
 
 #define Define_Module_Class_Internal(MODULE_NAME,CLASS_NAME,CNAME)\
-extern EXPORT_THIS   Dtool_PyTypedObject Dtool_##CLASS_NAME;  \
+extern EXPORT_THIS   Dtool_PyTypedObject Dtool_##CLASS_NAME;\
 extern struct        PyMethodDef Dtool_Methods_##CLASS_NAME[];\
 int         Dtool_Init_##CLASS_NAME(PyObject *self, PyObject *args, PyObject *kwds);\
 PyObject *  Dtool_new_##CLASS_NAME(PyTypeObject *type, PyObject *args, PyObject *kwds);\
@@ -443,9 +526,9 @@ EXPCL_DTOOLCONFIG int DTool_PyInit_Finalize(PyObject *self, void *This, Dtool_Py
 // code generation time becouse of multiple generation passes in interigate..
 //
 ///////////////////////////////////////////////////////////////////////////////
-typedef std::map<std::string, PyMethodDef *  > MethodDefmap;
+typedef std::map<std::string, PyMethodDef *> MethodDefmap;
 
-EXPCL_DTOOLCONFIG void Dtool_Accum_MethDefs(PyMethodDef  in[], MethodDefmap &themap);
+EXPCL_DTOOLCONFIG void Dtool_Accum_MethDefs(PyMethodDef in[], MethodDefmap &themap);
 
 ///////////////////////////////////////////////////////////////////////////////
 //  ** HACK ** allert..
@@ -459,22 +542,21 @@ EXPCL_DTOOLCONFIG void RegisterRuntimeClass(Dtool_PyTypedObject * otype, int cla
 
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
-EXPCL_DTOOLCONFIG Dtool_PyTypedObject *  Dtool_RuntimeTypeDtoolType(int type);
+EXPCL_DTOOLCONFIG Dtool_PyTypedObject *Dtool_RuntimeTypeDtoolType(int type);
 
 ///////////////////////////////////////////////////////////////////////////////
 //// We need a way to runtime merge compile units into a python "Module" .. this is done with the 
 /// fallowing structors and code.. along with the support of interigate_module 
 ///////////////////////////////////////////////////////////////////////////////
-struct LibrayDef
-{
-    typedef  void   ( *ConstantFunction  )(PyObject *);
+struct LibraryDef {
+  typedef void (*ConstantFunction)(PyObject *);
 
-    PyMethodDef *           _methods;
-    ConstantFunction        _constants;
+  PyMethodDef *_methods;
+  ConstantFunction _constants;
 };
 ///////////////////////////////////////////////////////////////////////////////
 
-EXPCL_DTOOLCONFIG void Dtool_PyModuleInitHelper( LibrayDef   *defs[], const char *  modulename);
+EXPCL_DTOOLCONFIG PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename);
 
 ///////////////////////////////////////////////////////////////////////////////
 ///  HACK.... Be carefull 
@@ -484,12 +566,12 @@ EXPCL_DTOOLCONFIG void Dtool_PyModuleInitHelper( LibrayDef   *defs[], const char
 //      Required to support fom historical inharatence in the for of "is this instance of"..
 //
 ///////////////////////////////////////////////////////////////////////////////
-EXPCL_DTOOLCONFIG PyObject * Dtool_BorrowThisReference(PyObject * self, PyObject * args );
+EXPCL_DTOOLCONFIG PyObject *Dtool_BorrowThisReference(PyObject *self, PyObject *args);
 
 //////////////////////////////////////////////////////////////////////////////////////////////
 // We do expose a dictionay for dtool classes .. this should be removed at some point..
 //////////////////////////////////////////////////////////////////////////////////////////////
-EXPCL_DTOOLCONFIG PyObject * Dtool_AddToDictionary(PyObject * self1, PyObject * args );
+EXPCL_DTOOLCONFIG PyObject *Dtool_AddToDictionary(PyObject *self1, PyObject *args);
 
 ///////////////////////////////////////////////////////////////////////////////////
 /*
@@ -535,10 +617,10 @@ EXPCL_DTOOLCONFIG long  DTool_HashKey(PyObject * inst)
    XXX of error.
 */
 
-EXPCL_DTOOLCONFIG int DTOOL_PyObject_Compare_old(PyObject *v1, PyObject *v2);
-
 EXPCL_DTOOLCONFIG int DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2);
 
+EXPCL_DTOOLCONFIG PyObject *DTOOL_PyObject_RichCompare(PyObject *v1, PyObject *v2, int op);
+
 EXPCL_DTOOLCONFIG PyObject *
 make_list_for_item(PyObject *self, const char *num_name,
                    const char *element_name);
@@ -555,10 +637,8 @@ map_deepcopy_to_copy(PyObject *self, PyObject *args);
 EXPCL_DTOOLCONFIG PyObject *
 PyLongOrInt_FromUnsignedLong(unsigned long value);
 
-EXPCL_DTOOLCONFIG extern struct   Dtool_PyTypedObject Dtool_DTOOL_SUPPER_BASE;
+EXPCL_DTOOLCONFIG extern struct Dtool_PyTypedObject Dtool_DTOOL_SUPER_BASE;
 
 #endif  // HAVE_PYTHON && !CPPPARSER
 
-
 #endif // PY_PANDA_H_ 
-

+ 9 - 3
panda/src/display/graphicsWindow.cxx

@@ -917,13 +917,19 @@ void GraphicsWindow::
 remove_python_event_handler(PyObject* name){
   list<PythonGraphicsWindowProc*> toRemove;
   PythonWinProcClasses::iterator iter;
-  for(iter = _python_window_proc_classes.begin(); iter != _python_window_proc_classes.end(); ++iter){
+  for (iter = _python_window_proc_classes.begin(); iter != _python_window_proc_classes.end(); ++iter) {
     PythonGraphicsWindowProc* pgwp = *iter;
-    if(PyObject_Compare(pgwp->get_name(), name) == 0)
+    if (PyObject_RichCompareBool(pgwp->get_name(), name, Py_EQ) == 1) {
       toRemove.push_back(pgwp);
+    }
+#if PY_MAJOR_VERSION < 3
+    else if (PyObject_Compare(pgwp->get_name(), name) == 0) {
+      toRemove.push_back(pgwp);
+    }
+#endif
   }
   list<PythonGraphicsWindowProc*>::iterator iter2;
-  for(iter2 = toRemove.begin(); iter2 != toRemove.end(); ++iter2){
+  for (iter2 = toRemove.begin(); iter2 != toRemove.end(); ++iter2) {
     PythonGraphicsWindowProc* pgwp = *iter2;
     remove_window_proc(pgwp);
     _python_window_proc_classes.erase(pgwp);

+ 58 - 6
panda/src/event/pythonTask.cxx

@@ -248,7 +248,11 @@ __setattr__(const string &attr_name, PyObject *v) {
     PyObject *str = PyObject_Repr(v);
     task_cat.debug() 
       << *this << ": task." << attr_name << " = "
-      << PyString_AsString(str) << "\n";
+#if PY_MAJOR_VERSION >= 3
+      << PyUnicode_AsUTF8(str) << "\n";
+#else
+      << PyString_AsString(str) << "\n"; 
+#endif
     Py_DECREF(str);
   }
 
@@ -263,7 +267,11 @@ __setattr__(const string &attr_name, PyObject *v) {
     }
 
   } else if (attr_name == "name") {
+#if PY_MAJOR_VERSION >= 3
+    char *name = PyUnicode_AsUTF8(v);
+#else
     char *name = PyString_AsString(v);
+#endif
     if (name != (char *)NULL) {
       set_name(name);
     }
@@ -307,19 +315,37 @@ PyObject *PythonTask::
 __getattr__(const string &attr_name) const {
   if (attr_name == "time") {
     return PyFloat_FromDouble(get_elapsed_time());
+
   } else if (attr_name == "name") {
+#if PY_MAJOR_VERSION >= 3
+    return PyUnicode_FromString(get_name().c_str());
+#else
     return PyString_FromString(get_name().c_str());
+#endif
+
   } else if (attr_name == "wakeTime") {
     return PyFloat_FromDouble(get_wake_time());
+
   } else if (attr_name == "delayTime") {
     if (!has_delay()) {
       Py_RETURN_NONE;
     }
     return PyFloat_FromDouble(get_delay());
+
   } else if (attr_name == "frame") {
+#if PY_MAJOR_VERSION >= 3
+    return PyLong_FromLong(get_elapsed_frames());
+#else
     return PyInt_FromLong(get_elapsed_frames());
+#endif
+
   } else if (attr_name == "id") {
+#if PY_MAJOR_VERSION >= 3
+    return PyLong_FromLong(_task_id);
+#else
     return PyInt_FromLong(_task_id);
+#endif
+
   } else {
     return PyMapping_GetItemString(_dict, (char *)attr_name.c_str());
   }
@@ -389,10 +415,17 @@ do_python_task() {
       // henceforth, instead of calling the function from the top
       // again.
       if (task_cat.is_debug()) {
+#if PY_MAJOR_VERSION >= 3
+        PyObject *str = PyObject_ASCII(_function);
+        task_cat.debug()
+          << PyUnicode_AsUTF8(str) << " in " << *this
+          << " yielded a generator.\n";
+#else
         PyObject *str = PyObject_Repr(_function);
-        task_cat.debug() 
+        task_cat.debug()
           << PyString_AsString(str) << " in " << *this
           << " yielded a generator.\n";
+#endif
         Py_DECREF(str);
       }
       _generator = result;
@@ -439,8 +472,14 @@ do_python_task() {
     return DS_done;
   }
 
+#if PY_MAJOR_VERSION >= 3
+  if (PyLong_Check(result)) {
+    long retval = PyLong_AS_LONG(result);
+#else
   if (PyInt_Check(result)) {
-    int retval = PyInt_AS_LONG(result);
+    long retval = PyInt_AS_LONG(result);
+#endif
+
     switch (retval) {
     case DS_again:
       Py_XDECREF(_generator);
@@ -454,7 +493,7 @@ do_python_task() {
     case DS_pause:
       // Legitimate value.
       Py_DECREF(result);
-      return (DoneStatus)retval;
+      return (DoneStatus) retval;
 
     case -1:
       // Legacy value.
@@ -467,10 +506,16 @@ do_python_task() {
     }
   }
 
-  PyObject *str = PyObject_Repr(result);
   ostringstream strm;
+#if PY_MAJOR_VERSION >= 3
+  PyObject *str = PyObject_ASCII(result);
+  strm
+    << *this << " returned " << PyUnicode_AsUTF8(str);
+#else
+  PyObject *str = PyObject_Repr(result);
   strm
     << *this << " returned " << PyString_AsString(str);
+#endif
   Py_DECREF(str);
   Py_DECREF(result);
   string message = strm.str();
@@ -590,10 +635,17 @@ call_owner_method(const char *method_name) {
   if (_owner != Py_None) {
     PyObject *func = PyObject_GetAttrString(_owner, (char *)method_name);
     if (func == (PyObject *)NULL) {
+#if PY_MAJOR_VERSION >= 3
+      PyObject *str = PyObject_ASCII(_owner);
+      task_cat.error()
+        << "Owner object " << PyUnicode_AsUTF8(str) << " added to "
+        << *this << " has no method " << method_name << "().\n";
+#else
       PyObject *str = PyObject_Repr(_owner);
-      task_cat.error() 
+      task_cat.error()
         << "Owner object " << PyString_AsString(str) << " added to "
         << *this << " has no method " << method_name << "().\n";
+#endif
       Py_DECREF(str);
 
     } else {

+ 29 - 4
panda/src/express/pointerToArray.I

@@ -82,7 +82,8 @@ PointerToArray(const PointerToArray<Element> &copy) :
 //     Function: PointerToArray::Constructor
 //       Access: Published
 //  Description: This special constructor accepts a Python list of
-//               elements, or a Python string.
+//               elements, or a Python string (or a bytes object,
+//               in Python 3).
 ////////////////////////////////////////////////////////////////////
 template<class Element>
 PointerToArray<Element>::
@@ -100,10 +101,33 @@ PointerToArray(PyObject *self, PyObject *sequence) :
     return;
   }
 
+  // If we were passed a Python string, then instead of storing it
+  // character-at-a-time, just load the whole string as a data
+  // buffer.
+#if PY_MAJOR_VERSION >= 3
+  if (PyBytes_Check(sequence)) {
+    int size = PyBytes_Size(sequence);
+    if (size % sizeof(Element) != 0) {
+      ostringstream stream;
+      stream << "Buffer not a multiple of " << sizeof(Element) << " bytes";
+      string str = stream.str();
+      PyErr_SetString(PyExc_ValueError, str.c_str());
+      return;
+    }
+      
+    int num_elements = size / sizeof(Element);
+    insert(begin(), num_elements, Element());
+
+    // Hope there aren't any constructors or destructors involved
+    // here.
+    if (size != 0) {
+      const char *data = PyBytes_AsString(sequence);
+      memcpy(p(), data, size);
+    }
+    return;
+  }
+#else
   if (PyString_CheckExact(sequence)) {
-    // If we were passed a Python string, then instead of storing it
-    // character-at-a-time, just load the whole string as a data
-    // buffer.
     int size = PyString_Size(sequence);
     if (size % sizeof(Element) != 0) {
       ostringstream stream;
@@ -124,6 +148,7 @@ PointerToArray(PyObject *self, PyObject *sequence) :
     }
     return;
   }
+#endif
 
   // Now construct the internal list by copying the elements
   // one-at-a-time from Python.

+ 17 - 1
panda/src/express/virtualFileSystem.cxx

@@ -925,7 +925,8 @@ get_global_ptr() {
 //     Function: VirtualFileSystem::__py__read_file
 //       Access: Published
 //  Description: Convenience function; returns the entire contents of
-//               the indicated file as a string.
+//               the indicated file as a string (or as a bytes object,
+//               in Python 3).
 //
 //               This variant on read_file() is implemented directly
 //               for Python, as a small optimization, to avoid the
@@ -938,11 +939,19 @@ __py__read_file(const Filename &filename, bool auto_unwrap) const {
   bool okflag = read_file(filename, pv, auto_unwrap);
   nassertr(okflag, NULL);
 
+#if PY_MAJOR_VERSION >= 3
+  if (pv.empty()) {
+    return PyBytes_FromStringAndSize("", 0);
+  } else {
+    return PyBytes_FromStringAndSize((const char *)&pv[0], pv.size());
+  }
+#else
   if (pv.empty()) {
     return PyString_FromStringAndSize("", 0);
   } else {
     return PyString_FromStringAndSize((const char *)&pv[0], pv.size());
   }
+#endif
 }
 #endif  // HAVE_PYTHON
 
@@ -1014,9 +1023,16 @@ PyObject *VirtualFileSystem::
 __py__write_file(const Filename &filename, PyObject *data, bool auto_wrap) {
   char *buffer;
   Py_ssize_t length;
+
+#if PY_MAJOR_VERSION >= 3
+  if (PyBytes_AsStringAndSize(data, &buffer, &length) == -1) {
+    return NULL;
+  }
+#else
   if (PyString_AsStringAndSize(data, &buffer, &length) == -1) {
     return NULL;
   }
+#endif
    
   bool result = write_file(filename, (const unsigned char *)buffer, length, auto_wrap);
   return PyBool_FromLong(result);

+ 1 - 1
panda/src/nativenet/buffered_datagramconnection.h

@@ -243,7 +243,7 @@ inline bool  Buffered_DatagramConnection::SendMessage(const Datagram &msg)
         nativenet_cat.warning() << "Buffered_DatagramConnection::SendMessage->Error On Write--Out Buffer = " << _Writer.AmountBuffered() << "\n";
         #ifdef HAVE_PYTHON
         ostringstream s;
-        PyObject *exc_type = PyExc_StandardError;
+        PyObject *exc_type = PyExc_ConnectionError;
         
         s << endl << "Error sending message: " << endl;
         msg.dump_hex(s);

+ 18 - 0
panda/src/pgraph/pandaNode.cxx

@@ -1780,7 +1780,11 @@ get_tag_keys() const {
   PyObject *result = PyList_New(keys.size());
   for (size_t i = 0; i < keys.size(); ++i) {
     const string &tag_name = keys[i];
+#if PY_MAJOR_VERSION >= 3
+    PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size());
+#else
     PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size());
+#endif
     PyList_SET_ITEM(result, i, str);
   }
 
@@ -1801,7 +1805,11 @@ get_python_tag_keys() const {
   PyObject *result = PyList_New(keys.size());
   for (size_t i = 0; i < keys.size(); ++i) {
     const string &tag_name = keys[i];
+#if PY_MAJOR_VERSION >= 3
+    PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size());
+#else
     PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size());
+#endif
     PyList_SET_ITEM(result, i, str);
   }
 
@@ -1861,7 +1869,17 @@ compare_tags(const PandaNode *other) const {
       return cmp;
     }
 
+#if PY_MAJOR_VERSION >= 3
+    if (PyObject_RichCompareBool((*api).second, (*bpi).second, Py_LT) == 1) {
+      return -1;
+    } else if (PyObject_RichCompareBool((*api).second, (*bpi).second, Py_GT) == 1) {
+      return 1;
+    } else if (PyObject_RichCompareBool((*api).second, (*bpi).second, Py_EQ) == 1) {
+      cmp = 0;
+    } else {
+#else
     if (PyObject_Cmp((*api).second, (*bpi).second, &cmp) == -1) {
+#endif
       // Unable to compare objects; just compare pointers.
       if ((*api).second != (*bpi).second) {
         cmp = (*api).second < (*bpi).second ? -1 : 1;

Some files were not shown because too many files changed in this diff