From de0b0dd8799837c3dbd36238e987040403603ca4 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 23 Mar 2015 00:32:47 +0100 Subject: [PATCH] Fix various issues with Python 3 support, fix samples to work with Python 3 --- direct/src/filter/CommonFilters.py | 17 ++- direct/src/filter/FilterManager.py | 41 +++--- direct/src/showbase/ShowBase.py | 100 +++++++------- dtool/src/interrogate/functionRemap.cxx | 30 ++++- dtool/src/interrogate/functionRemap.h | 1 + .../interfaceMakerPythonNative.cxx | 127 ++++++++++++------ .../interrogate/interfaceMakerPythonNative.h | 1 - makepanda/makepandacore.py | 2 + samples/asteroids/main.py | 6 +- samples/chessboard/main.py | 4 +- samples/culling/occluder_culling.py | 2 +- samples/culling/portal_culling.py | 2 +- .../solar-system/step6_controllable_system.py | 8 +- 13 files changed, 206 insertions(+), 135 deletions(-) diff --git a/direct/src/filter/CommonFilters.py b/direct/src/filter/CommonFilters.py index a561487e16..42b06d740b 100644 --- a/direct/src/filter/CommonFilters.py +++ b/direct/src/filter/CommonFilters.py @@ -16,11 +16,10 @@ clunky approach. - Josh """ from FilterManager import FilterManager -from pandac.PandaModules import Point3, Vec3, Vec4, Point2 -from pandac.PandaModules import NodePath, PandaNode -from pandac.PandaModules import Filename -from pandac.PandaModules import AuxBitplaneAttrib -from pandac.PandaModules import RenderState, Texture, Shader, ATSNone +from panda3d.core import LVecBase4, LPoint2 +from panda3d.core import Filename +from panda3d.core import AuxBitplaneAttrib +from panda3d.core import RenderState, Texture, Shader, ATSNone import sys,os CARTOON_BODY=""" @@ -348,13 +347,13 @@ class CommonFilters: if (changed == "CartoonInk") or fullrebuild: if ("CartoonInk" in configuration): c = configuration["CartoonInk"] - self.finalQuad.setShaderInput("cartoonseparation", Vec4(c.separation, 0, c.separation, 0)) + self.finalQuad.setShaderInput("cartoonseparation", LVecBase4(c.separation, 0, c.separation, 0)) self.finalQuad.setShaderInput("cartooncolor", c.color) if (changed == "BlurSharpen") or fullrebuild: if ("BlurSharpen" in configuration): blurval = configuration["BlurSharpen"] - self.finalQuad.setShaderInput("blurval", Vec4(blurval, blurval, blurval, blurval)) + self.finalQuad.setShaderInput("blurval", LVecBase4(blurval, blurval, blurval, blurval)) if (changed == "Bloom") or fullrebuild: if ("Bloom" in configuration): @@ -386,9 +385,9 @@ class CommonFilters: if "VolumetricLighting" in self.configuration: caster = self.configuration["VolumetricLighting"].caster - casterpos = Point2() + casterpos = LPoint2() self.manager.camera.node().getLens().project(caster.getPos(self.manager.camera), casterpos) - self.finalQuad.setShaderInput("casterpos", Vec4(casterpos.getX() * 0.5 + 0.5, (casterpos.getY() * 0.5 + 0.5), 0, 0)) + self.finalQuad.setShaderInput("casterpos", LVecBase4(casterpos.getX() * 0.5 + 0.5, (casterpos.getY() * 0.5 + 0.5), 0, 0)) if task != None: return task.cont diff --git a/direct/src/filter/FilterManager.py b/direct/src/filter/FilterManager.py index 6a3fe5ab4e..c03afe4bc0 100644 --- a/direct/src/filter/FilterManager.py +++ b/direct/src/filter/FilterManager.py @@ -14,16 +14,15 @@ Still need to implement: """ -from pandac.PandaModules import Point3, Vec3, Vec4 -from pandac.PandaModules import NodePath, PandaNode -from pandac.PandaModules import RenderState, Texture, Shader -from pandac.PandaModules import CardMaker -from pandac.PandaModules import TextureStage -from pandac.PandaModules import GraphicsPipe, GraphicsOutput -from pandac.PandaModules import WindowProperties, FrameBufferProperties -from pandac.PandaModules import Camera, DisplayRegion -from pandac.PandaModules import OrthographicLens -from pandac.PandaModules import AuxBitplaneAttrib +from panda3d.core import NodePath, PandaNode +from panda3d.core import RenderState, Texture, Shader +from panda3d.core import CardMaker +from panda3d.core import TextureStage +from panda3d.core import GraphicsPipe, GraphicsOutput +from panda3d.core import WindowProperties, FrameBufferProperties +from panda3d.core import Camera, DisplayRegion +from panda3d.core import OrthographicLens +from panda3d.core import AuxBitplaneAttrib from direct.directnotify.DirectNotifyGlobal import * from direct.showbase.DirectObject import DirectObject @@ -111,16 +110,16 @@ class FilterManager(DirectObject): winx = self.forcex winy = self.forcey - if (winx == 0): winx = self.win.getXSize() - if (winy == 0): winy = self.win.getYSize() + if winx == 0: winx = self.win.getXSize() + if winy == 0: winy = self.win.getYSize() - if (div != 1): - winx = ((winx+align-1) / align) * align - winy = ((winy+align-1) / align) * align - winx = winx / div - winy = winy / div + if div != 1: + winx = ((winx+align-1) // align) * align + winy = ((winy+align-1) // align) * align + winx = winx // div + winy = winy // div - if (mul != 1): + if mul != 1: winx = winx * mul winy = winy * mul @@ -198,7 +197,7 @@ class FilterManager(DirectObject): quad.setDepthTest(0) quad.setDepthWrite(0) quad.setTexture(colortex) - quad.setColor(Vec4(1,0.5,0.5,1)) + quad.setColor(1, 0.5, 0.5, 1) cs = NodePath("dummy") cs.setState(self.camstate) @@ -221,7 +220,7 @@ class FilterManager(DirectObject): self.setStackedClears(buffer, self.rclears, self.wclears) if (auxtex0): buffer.setClearActive(GraphicsOutput.RTPAuxRgba0, 1) - buffer.setClearValue(GraphicsOutput.RTPAuxRgba0, Vec4(0.5, 0.5, 1.0, 0.0)) + buffer.setClearValue(GraphicsOutput.RTPAuxRgba0, (0.5, 0.5, 1.0, 0.0)) if (auxtex1): buffer.setClearActive(GraphicsOutput.RTPAuxRgba1, 1) self.region.disableClears() @@ -262,7 +261,7 @@ class FilterManager(DirectObject): quad = NodePath(cm.generate()) quad.setDepthTest(0) quad.setDepthWrite(0) - quad.setColor(Vec4(1,0.5,0.5,1)) + quad.setColor(1, 0.5, 0.5, 1) quadcamnode = Camera("filter-quad-cam") lens = OrthographicLens() diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index 03a0d66a86..35b60ce271 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -11,8 +11,8 @@ from panda3d.core import * from panda3d.direct import get_config_showbase, throw_new_frame, init_app_for_gui # This needs to be available early for DirectGUI imports -import __builtin__ -__builtin__.config = get_config_showbase() +import __builtin__ as builtins +builtins.config = get_config_showbase() from direct.directnotify.DirectNotifyGlobal import directNotify, giveNotify from MessengerGlobal import messenger @@ -44,17 +44,17 @@ if __debug__: import OnScreenDebug import AppRunnerGlobal -__builtin__.FADE_SORT_INDEX = 1000 -__builtin__.NO_FADE_SORT_INDEX = 2000 +builtins.FADE_SORT_INDEX = 1000 +builtins.NO_FADE_SORT_INDEX = 2000 def legacyRun(): - __builtin__.base.notify.warning("run() is deprecated, use base.run() instead") - __builtin__.base.run() + builtins.base.notify.warning("run() is deprecated, use base.run() instead") + builtins.base.run() @atexit.register def exitfunc(): - if getattr(__builtin__, 'base', None) is not None: - __builtin__.base.destroy() + if getattr(builtins, 'base', None) is not None: + builtins.base.destroy() # Now ShowBase is a DirectObject. We need this so ShowBase can hang # hooks on messages, particularly on window-event. This doesn't @@ -65,7 +65,7 @@ class ShowBase(DirectObject.DirectObject): def __init__(self, fStartDirect = True, windowType = None): self.__dev__ = config.GetBool('want-dev', __debug__) - __builtin__.__dev__ = self.__dev__ + builtins.__dev__ = self.__dev__ logStackDump = (config.GetBool('log-stack-dump', False) or config.GetBool('client-log-stack-dump', False)) @@ -327,8 +327,8 @@ class ShowBase(DirectObject.DirectObject): # assigned to a single CPU autoAffinity = self.config.GetBool('auto-single-cpu-affinity', 0) affinity = None - if autoAffinity and ('clientIndex' in __builtin__.__dict__): - affinity = abs(int(__builtin__.clientIndex)) + if autoAffinity and ('clientIndex' in builtins.__dict__): + affinity = abs(int(builtins.clientIndex)) else: affinity = self.config.GetInt('client-cpu-affinity', -1) if (affinity in (None, -1)) and autoAffinity: @@ -338,44 +338,44 @@ class ShowBase(DirectObject.DirectObject): TrueClock.getGlobalPtr().setCpuAffinity(1 << (affinity % 32)) # Make sure we're not making more than one ShowBase. - if 'base' in __builtin__.__dict__: + if 'base' in builtins.__dict__: raise StandardError, "Attempt to spawn multiple ShowBase instances!" # DO NOT ADD TO THIS LIST. We're trying to phase out the use of # built-in variables by ShowBase. Use a Global module if necessary. - __builtin__.base = self - __builtin__.render2d = self.render2d - __builtin__.aspect2d = self.aspect2d - __builtin__.pixel2d = self.pixel2d - __builtin__.render = self.render - __builtin__.hidden = self.hidden - __builtin__.camera = self.camera - __builtin__.loader = self.loader - __builtin__.taskMgr = self.taskMgr - __builtin__.jobMgr = self.jobMgr - __builtin__.eventMgr = self.eventMgr - __builtin__.messenger = self.messenger - __builtin__.bboard = self.bboard + builtins.base = self + builtins.render2d = self.render2d + builtins.aspect2d = self.aspect2d + builtins.pixel2d = self.pixel2d + builtins.render = self.render + builtins.hidden = self.hidden + builtins.camera = self.camera + builtins.loader = self.loader + builtins.taskMgr = self.taskMgr + builtins.jobMgr = self.jobMgr + builtins.eventMgr = self.eventMgr + builtins.messenger = self.messenger + builtins.bboard = self.bboard # Config needs to be defined before ShowBase is constructed - #__builtin__.config = self.config - __builtin__.run = legacyRun - __builtin__.ostream = Notify.out() - __builtin__.directNotify = directNotify - __builtin__.giveNotify = giveNotify - __builtin__.globalClock = globalClock - __builtin__.vfs = vfs - __builtin__.cpMgr = ConfigPageManager.getGlobalPtr() - __builtin__.cvMgr = ConfigVariableManager.getGlobalPtr() - __builtin__.pandaSystem = PandaSystem.getGlobalPtr() - __builtin__.wantUberdog = base.config.GetBool('want-uberdog', 1) + #builtins.config = self.config + builtins.run = legacyRun + builtins.ostream = Notify.out() + builtins.directNotify = directNotify + builtins.giveNotify = giveNotify + builtins.globalClock = globalClock + builtins.vfs = vfs + builtins.cpMgr = ConfigPageManager.getGlobalPtr() + builtins.cvMgr = ConfigVariableManager.getGlobalPtr() + builtins.pandaSystem = PandaSystem.getGlobalPtr() + builtins.wantUberdog = base.config.GetBool('want-uberdog', 1) if __debug__: - __builtin__.deltaProfiler = DeltaProfiler.DeltaProfiler("ShowBase") - __builtin__.onScreenDebug = OnScreenDebug.OnScreenDebug() + builtins.deltaProfiler = DeltaProfiler.DeltaProfiler("ShowBase") + builtins.onScreenDebug = OnScreenDebug.OnScreenDebug() if self.wantRender2dp: - __builtin__.render2dp = self.render2dp - __builtin__.aspect2dp = self.aspect2dp - __builtin__.pixel2dp = self.pixel2dp + builtins.render2dp = self.render2dp + builtins.aspect2dp = self.aspect2dp + builtins.pixel2dp = self.pixel2dp if __dev__: ShowBase.notify.debug('__dev__ == %s' % __dev__) @@ -497,10 +497,10 @@ class ShowBase(DirectObject.DirectObject): cb() # Remove the built-in base reference - if getattr(__builtin__, 'base', None) is self: - del __builtin__.base - del __builtin__.loader - del __builtin__.taskMgr + if getattr(builtins, 'base', None) is self: + del builtins.base + del builtins.loader + del builtins.taskMgr # [gjeon] restore sticky key settings if self.config.GetBool('disable-sticky-keys', 0): @@ -1308,7 +1308,7 @@ class ShowBase(DirectObject.DirectObject): # camera. self.camera = self.render.attachNewNode(ModelNode('camera')) self.camera.node().setPreserveTransform(ModelNode.PTLocal) - __builtin__.camera = self.camera + builtins.camera = self.camera self.mouse2cam.node().setNode(self.camera.node()) @@ -2814,7 +2814,7 @@ class ShowBase(DirectObject.DirectObject): # wx is now the main loop, not us any more. self.run = self.wxRun self.taskMgr.run = self.wxRun - __builtin__.run = self.wxRun + builtins.run = self.wxRun if self.appRunner: self.appRunner.run = self.wxRun @@ -2876,7 +2876,7 @@ class ShowBase(DirectObject.DirectObject): # Create a new Tk root. self.tkRoot = Pmw.initialise() - __builtin__.tkroot = self.tkRoot + builtins.tkroot = self.tkRoot init_app_for_gui() @@ -2893,7 +2893,7 @@ class ShowBase(DirectObject.DirectObject): # wx is now the main loop, not us any more. self.run = self.tkRun self.taskMgr.run = self.tkRun - __builtin__.run = self.tkRun + builtins.run = self.tkRun if self.appRunner: self.appRunner.run = self.tkRun @@ -2938,7 +2938,7 @@ class ShowBase(DirectObject.DirectObject): from direct.directtools import DirectSession base.direct.enable() else: - __builtin__.direct = self.direct = None + builtins.direct = self.direct = None def getRepository(self): return None diff --git a/dtool/src/interrogate/functionRemap.cxx b/dtool/src/interrogate/functionRemap.cxx index ea09c472e7..e1abae2c06 100644 --- a/dtool/src/interrogate/functionRemap.cxx +++ b/dtool/src/interrogate/functionRemap.cxx @@ -743,7 +743,8 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak _args_type = InterfaceMaker::AT_varargs; } - if (_type == T_normal) { + switch (_type) { + case T_normal: if (fname == "operator []" || fname == "__getitem__") { _flags |= F_getitem; if (_has_this && _parameters.size() == 2) { @@ -824,6 +825,13 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak _flags |= F_coerce_constructor; } + } else if (fname == "operator /") { + if (_has_this && _parameters.size() == 2 && + TypeManager::is_float(_parameters[1]._remap->get_new_type())) { + // This division operator takes a single float argument. + _flags |= F_divide_float; + } + } else if (fname == "operator ()" || fname == "__call__") { // Call operators always take keyword arguments. _args_type = InterfaceMaker::AT_keyword_args; @@ -840,8 +848,19 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak _args_type = InterfaceMaker::AT_keyword_args; } } + break; - } else if (_type == T_item_assignment_operator) { + case T_assignment_method: + if (fname == "operator /=") { + if (_has_this && _parameters.size() == 2 && + TypeManager::is_float(_parameters[1]._remap->get_new_type())) { + // This division operator takes a single float argument. + _flags |= F_divide_float; + } + } + break; + + case T_item_assignment_operator: // The concept of "item assignment operator" doesn't really exist in C++, // but it does in scripting languages, and this allows us to wrap cases // where the C++ getitem returns an assignable reference. @@ -853,8 +872,9 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak } } _args_type = InterfaceMaker::AT_varargs; + break; - } else if (_type == T_constructor) { + case T_constructor: if (!_has_this && _parameters.size() == 1 && TypeManager::unwrap(_parameters[0]._remap->get_orig_type()) == TypeManager::unwrap(_return_type->get_orig_type())) { @@ -870,6 +890,10 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak // Constructors always take varargs and keyword args. _args_type = InterfaceMaker::AT_keyword_args; + break; + + default: + break; } return true; diff --git a/dtool/src/interrogate/functionRemap.h b/dtool/src/interrogate/functionRemap.h index c9d4f3bb94..7d2f88fd6b 100644 --- a/dtool/src/interrogate/functionRemap.h +++ b/dtool/src/interrogate/functionRemap.h @@ -98,6 +98,7 @@ public: F_releasebuffer = 0x1000, F_compare_to = 0x2000, F_coerce_constructor = 0x4000, + F_divide_float = 0x8000, }; typedef vector Parameters; diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index 971a5ef24d..bd48703e64 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -311,7 +311,6 @@ get_slotted_function_def(Object *obj, Function *func, FunctionRemap *remap, return false; } - def._func = func; def._answer_location = string(); def._wrapper_type = WT_none; def._min_version = 0; @@ -344,8 +343,6 @@ get_slotted_function_def(Object *obj, Function *func, FunctionRemap *remap, } if (method_name == "operator /") { - // Note: nb_divide does not exist in Python 3. We will probably need some - // smart mechanism for dispatching to either floor_divide or true_divide. def._answer_location = "nb_divide"; def._wrapper_type = WT_binary_operator; return true; @@ -620,7 +617,6 @@ write_function_slot(ostream &out, int indent_level, const SlottedFunctions &slot } const SlottedFunctionDef &def = rfi->second; - Function *func = def._func; // Add an #ifdef if there is a specific version requirement on this function. if (def._min_version > 0) { @@ -1469,6 +1465,29 @@ write_module_class(ostream &out, Object *obj) { slots[key] = slotted_def; slots[key]._remaps.insert(remap); } + + // Python 3 doesn't support nb_divide. It has nb_true_divide and also + // nb_floor_divide, but they have different semantics than in C++. Ugh. + // Make special slots to store the nb_divide members that take a float. + // We'll use this to build up nb_true_divide, so that we can still properly + // divide float vector types. + if (remap->_flags & FunctionRemap::F_divide_float) { + string true_key; + if (key == "nb_inplace_divide") { + true_key = "nb_inplace_true_divide"; + } else { + true_key = "nb_true_divide"; + } + if (slots.count(true_key) == 0) { + SlottedFunctionDef def; + def._answer_location = true_key; + def._wrapper_type = slotted_def._wrapper_type; + def._min_version = 0x03000000; + def._wrapper_name = func->_name + "_" + true_key; + slots[true_key] = def; + } + slots[true_key]._remaps.insert(remap); + } } else { has_nonslotted = true; } @@ -1565,12 +1584,21 @@ write_module_class(ostream &out, Object *obj) { } { - Function *getitem_func; - SlottedFunctions::iterator rfi; for (rfi = slots.begin(); rfi != slots.end(); rfi++) { const SlottedFunctionDef &def = rfi->second; - Function *func = def._func; + + // This is just for reporting. There might be remaps from multiple + // functions with different names mapped to the same slot. + string fname; + if (def._remaps.size() > 0) { + const FunctionRemap *first_remap = *def._remaps.begin(); + fname = first_remap->_cppfunc->get_simple_name(); + } + + if (def._min_version > 0) { + out << "#if PY_VERSION_HEX >= 0x" << hex << def._min_version << dec << "\n"; + } switch (rfi->second._wrapper_type) { case WT_no_params: @@ -1578,8 +1606,8 @@ write_module_class(ostream &out, Object *obj) { // PyObject *func(PyObject *self) { out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; + out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; + out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; out << "//////////////////\n"; out << "static PyObject *" << def._wrapper_name << "(PyObject *self) {\n"; out << " " << cClassName << " *local_this = NULL;\n"; @@ -1613,8 +1641,8 @@ write_module_class(ostream &out, Object *obj) { return_flags |= RF_pyobject; } out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; + out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; + out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; out << "//////////////////\n"; out << "static PyObject *" << def._wrapper_name << "(PyObject *self, PyObject *arg) {\n"; out << " " << cClassName << " *local_this = NULL;\n"; @@ -1656,8 +1684,8 @@ write_module_class(ostream &out, Object *obj) { // int func(PyObject *self, PyObject *one, PyObject *two = NULL) { out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; + out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; + out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; out << "//////////////////\n"; out << "static int " << def._wrapper_name << "(PyObject *self, PyObject *arg, PyObject *arg2) {\n"; out << " " << cClassName << " *local_this = NULL;\n"; @@ -1735,8 +1763,8 @@ write_module_class(ostream &out, Object *obj) { // If one wants to override this completely, one should define __getattribute__ instead. { out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; + out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; + out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; out << "//////////////////\n"; out << "static PyObject *" << def._wrapper_name << "(PyObject *self, PyObject *arg) {\n"; out << " PyObject *res = PyObject_GenericGetAttr(self, arg);\n"; @@ -1768,8 +1796,8 @@ write_module_class(ostream &out, Object *obj) { // PyObject *func(PyObject *self, Py_ssize_t index) { out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; + out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; + out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; out << "//////////////////\n"; out << "static PyObject *" << def._wrapper_name << "(PyObject *self, Py_ssize_t index) {\n"; out << " " << cClassName << " *local_this = NULL;\n"; @@ -1797,8 +1825,6 @@ write_module_class(ostream &out, Object *obj) { out << " }\n"; out << " return NULL;\n"; out << "}\n\n"; - - getitem_func = func; } break; @@ -1806,8 +1832,8 @@ write_module_class(ostream &out, Object *obj) { // int_t func(PyObject *self, Py_ssize_t index, PyObject *value) { out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; + out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; + out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; out << "//////////////////\n"; out << "static int " << def._wrapper_name << "(PyObject *self, Py_ssize_t index, PyObject *arg) {\n"; out << " " << cClassName << " *local_this = NULL;\n"; @@ -1860,8 +1886,8 @@ write_module_class(ostream &out, Object *obj) { // Py_ssize_t func(PyObject *self) { out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; + out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; + out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; out << "//////////////////\n"; out << "static Py_ssize_t " << def._wrapper_name << "(PyObject *self) {\n"; out << " " << cClassName << " *local_this = NULL;\n"; @@ -1870,7 +1896,7 @@ write_module_class(ostream &out, Object *obj) { out << " }\n\n"; // This is a cheap cheat around all of the overhead of calling the wrapper function. - out << " return (Py_ssize_t) local_this->" << func->_ifunc.get_name() << "();\n"; + out << " return (Py_ssize_t) local_this->" << fname << "();\n"; out << "}\n\n"; } break; @@ -1879,8 +1905,8 @@ write_module_class(ostream &out, Object *obj) { // int func(PyObject *self, PyObject *one, PyObject *two) { out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; + out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; + out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; out << "//////////////////\n"; out << "static int " << def._wrapper_name << "(PyObject *self, PyObject *arg, PyObject *arg2) {\n"; out << " " << cClassName << " *local_this = NULL;\n"; @@ -1930,8 +1956,8 @@ write_module_class(ostream &out, Object *obj) { // int func(PyObject *self) { out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; + out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; + out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; out << "//////////////////\n"; out << "static int " << def._wrapper_name << "(PyObject *self) {\n"; out << " " << cClassName << " *local_this = NULL;\n"; @@ -1956,8 +1982,8 @@ write_module_class(ostream &out, Object *obj) { has_local_getbuffer = true; out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; + out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; + out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; out << "//////////////////\n"; out << "static int " << def._wrapper_name << "(PyObject *self, Py_buffer *buffer, int flags) {\n"; out << " " << cClassName << " *local_this = NULL;\n"; @@ -2023,8 +2049,8 @@ write_module_class(ostream &out, Object *obj) { // Same story as __getbuffer__ above. { out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; + out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; + out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; out << "//////////////////\n"; out << "static void " << def._wrapper_name << "(PyObject *self, Py_buffer *buffer) {\n"; out << " " << cClassName << " *local_this = NULL;\n"; @@ -2105,8 +2131,8 @@ write_module_class(ostream &out, Object *obj) { return_flags |= RF_pyobject; } out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; + out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; + out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; out << "//////////////////\n"; out << "static PyObject *" << def._wrapper_name << "(PyObject *self, PyObject *arg, PyObject *arg2) {\n"; out << " " << cClassName << " *local_this = NULL;\n"; @@ -2162,8 +2188,8 @@ write_module_class(ostream &out, Object *obj) { // This is a low-level function. Overloads are not supported. { out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; + out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; + out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; out << "//////////////////\n"; out << "static int " << def._wrapper_name << "(PyObject *self, visitproc visit, void *arg) {\n"; out << " " << cClassName << " *local_this = NULL;\n"; @@ -2174,7 +2200,7 @@ write_module_class(ostream &out, Object *obj) { out << " }\n\n"; // Find the remap. There should be only one. - FunctionRemap *remap = func->_remaps.front(); + FunctionRemap *remap = *def._remaps.begin(); vector_string params(1); if (remap->_flags & FunctionRemap::F_explicit_self) { @@ -2191,10 +2217,17 @@ write_module_class(ostream &out, Object *obj) { case WT_none: // Nothing special about the wrapper function: just write it normally. string fname = "static PyObject *" + def._wrapper_name + "(PyObject *self, PyObject *args, PyObject *kwds)\n"; + + vector remaps; + remaps.insert(remaps.end(), def._remaps.begin(), def._remaps.end()); string expected_params; - write_function_for_name(out, obj, func->_remaps, fname, expected_params, true, AT_keyword_args, RF_pyobject | RF_err_null); + write_function_for_name(out, obj, remaps, fname, expected_params, true, AT_keyword_args, RF_pyobject | RF_err_null); break; } + + if (def._min_version > 0) { + out << "#endif // PY_VERSION_HEX >= 0x" << hex << def._min_version << dec << "\n"; + } } string get_key = HasAGetKeyFunction(obj->_itype); @@ -2352,7 +2385,13 @@ write_module_class(ostream &out, Object *obj) { if (compare_to_func != NULL) { out << "#if PY_MAJOR_VERSION >= 3\n"; out << " // All is not lost; we still have the compare_to function to fall back onto.\n"; - out << " PyObject *result = " << compare_to_func->_name << "(self, arg);\n"; + if (compare_to_func->_args_type == AT_single_arg) { + out << " PyObject *result = " << compare_to_func->_name << "(self, arg);\n"; + } else { + out << " PyObject *args = PyTuple_Pack(1, arg);\n"; + out << " PyObject *result = " << compare_to_func->_name << "(self, args);\n"; + out << " Py_DECREF(args);\n"; + } out << " if (result != NULL) {\n"; out << " if (PyLong_Check(result)) {;\n"; out << " long cmpval = PyLong_AS_LONG(result);\n"; @@ -2466,7 +2505,9 @@ write_module_class(ostream &out, Object *obj) { write_function_slot(out, 2, slots, "nb_and"); write_function_slot(out, 2, slots, "nb_xor"); write_function_slot(out, 2, slots, "nb_or"); + out << "#if PY_MAJOR_VERSION < 3\n"; write_function_slot(out, 2, slots, "nb_coerce"); + out << "#endif\n"; write_function_slot(out, 2, slots, "nb_int"); out << " 0, // nb_long\n"; // removed in Python 3 write_function_slot(out, 2, slots, "nb_float"); @@ -2637,7 +2678,7 @@ write_module_class(ostream &out, Object *obj) { // long tp_flags; if (has_local_getbuffer) { - out << "#if PY_VERSION_HEX >= 0x02060000\n"; + out << "#if PY_VERSION_HEX >= 0x02060000 && PY_VERSION_HEX < 0x03000000\n"; out << " Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_HAVE_NEWBUFFER" << gcflag << ",\n"; out << "#else\n"; out << " Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES" << gcflag << ",\n"; @@ -2991,7 +3032,9 @@ write_function_for_top(ostream &out, InterfaceMaker::Object *obj, InterfaceMaker SlottedFunctionDef slotted_def; if (!get_slotted_function_def(obj, func, remap, slotted_def)) { + // It has a non-slotted remap, so we should write it. has_remaps = true; + break; } } @@ -4567,7 +4610,11 @@ write_function_instance(ostream &out, FunctionRemap *remap, only_pyobjects = false; } else if (TypeManager::is_wchar(type)) { + indent(out, indent_level) << "#if PY_VERSION_HEX >= 0x03020000\n"; + indent(out, indent_level) << "PyObject *" << param_name << ";\n"; + indent(out, indent_level) << "#else\n"; indent(out, indent_level) << "PyUnicodeObject *" << param_name << ";\n"; + indent(out, indent_level) << "#endif\n"; format_specifiers += "U"; parameter_list += ", &" + param_name; diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.h b/dtool/src/interrogate/interfaceMakerPythonNative.h index 7288f8ce57..7db5800336 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.h +++ b/dtool/src/interrogate/interfaceMakerPythonNative.h @@ -112,7 +112,6 @@ private: string _answer_location; WrapperType _wrapper_type; int _min_version; - Function *_func; string _wrapper_name; set _remaps; }; diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index 74d448ada3..064a7edd79 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -2275,6 +2275,8 @@ def SetupBuildEnvironment(compiler): handle = subprocess.Popen(cmd, stdout=null, stderr=subprocess.PIPE, shell=True) scanning = False for line in handle.communicate()[1].splitlines(): + line = line.decode('utf-8', 'replace') + # Start looking at a line that says: #include "..." search starts here if not scanning: if line.startswith('#include'): diff --git a/samples/asteroids/main.py b/samples/asteroids/main.py index 297ccf91e6..bf7e7a68c5 100755 --- a/samples/asteroids/main.py +++ b/samples/asteroids/main.py @@ -180,9 +180,9 @@ class AsteroidsDemo(ShowBase): # ... 20) and chooses a value from it. Since the player starts at 0 # and this list doesn't contain anything from -4 to 4, it won't be # close to the player. - asteroid.setX(choice(range(-SCREEN_X, -5) + range(5, SCREEN_X))) - # Same thing for Y, but from -15 to 15 - asteroid.setZ(choice(range(-SCREEN_Y, -5) + range(5, SCREEN_Y))) + asteroid.setX(choice(tuple(range(-SCREEN_X, -5)) + tuple(range(5, SCREEN_X)))) + # Same thing for Y + asteroid.setZ(choice(tuple(range(-SCREEN_Y, -5)) + tuple(range(5, SCREEN_Y)))) # Heading is a random angle in radians heading = random() * 2 * pi diff --git a/samples/chessboard/main.py b/samples/chessboard/main.py index 38b4664c41..7da1d97a14 100755 --- a/samples/chessboard/main.py +++ b/samples/chessboard/main.py @@ -39,12 +39,12 @@ def PointAtZ(z, point, vec): # A handy little function for getting the proper position for a given square1 def SquarePos(i): - return LPoint3((i % 8) - 3.5, int(i / 8) - 3.5, 0) + return LPoint3((i % 8) - 3.5, int(i // 8) - 3.5, 0) # Helper function for determining wheter a square should be white or black # The modulo operations (%) generate the every-other pattern of a chess-board def SquareColor(i): - if (i + ((i / 8) % 2)) % 2: + if (i + ((i // 8) % 2)) % 2: return BLACK else: return WHITE diff --git a/samples/culling/occluder_culling.py b/samples/culling/occluder_culling.py index 9743c159c0..80d1687d43 100755 --- a/samples/culling/occluder_culling.py +++ b/samples/culling/occluder_culling.py @@ -102,7 +102,7 @@ class Game(ShowBase): self.models = [] box_model = self.loader.loadModel('box') - for dummy in xrange(0, 500): + for dummy in range(0, 500): pos = LPoint3((random.random() - 0.5) * 9, (random.random() - 0.5) * 9, random.random() * 8) diff --git a/samples/culling/portal_culling.py b/samples/culling/portal_culling.py index 26ae074dd8..6f8d8aaf6f 100755 --- a/samples/culling/portal_culling.py +++ b/samples/culling/portal_culling.py @@ -108,7 +108,7 @@ class Game(ShowBase): # Randomly spawn some models to test the portals self.models = [] - for dummy in xrange(0, 500): + for dummy in range(0, 500): pos = LPoint3((random.random() - 0.5) * 6, (random.random() - 0.5) * 6, random.random() * 7) diff --git a/samples/solar-system/step6_controllable_system.py b/samples/solar-system/step6_controllable_system.py index 8758fb0509..554d0f12d0 100755 --- a/samples/solar-system/step6_controllable_system.py +++ b/samples/solar-system/step6_controllable_system.py @@ -117,7 +117,7 @@ class World(DirectObject): # When the mouse is clicked, if the simulation is running pause all the # planets and sun, otherwise resume it if self.simRunning: - print "Pausing Simulation" + print("Pausing Simulation") # changing the text to reflect the change from "RUNNING" to # "PAUSED" self.mouse1EventText.setText( @@ -146,7 +146,7 @@ class World(DirectObject): self.orbit_period_mars, self.mkeyEventText) else: #"The simulation is paused, so resume it - print "Resuming Simulation" + print("Resuming Simulation") self.mouse1EventText.setText( "Mouse Button 1: Toggle entire Solar System [RUNNING]") # the not operator does the reverse of the previous code @@ -179,10 +179,10 @@ class World(DirectObject): # Text is the OnscreenText object that needs to be updated def togglePlanet(self, planet, day, orbit=None, text=None): if day.isPlaying(): - print "Pausing " + planet + print("Pausing " + planet) state = " [PAUSED]" else: - print "Resuming " + planet + print("Resuming " + planet) state = " [RUNNING]" # Update the onscreen text if it is given as an argument