diff --git a/contrib/src/sceneeditor/collisionWindow.py b/contrib/src/sceneeditor/collisionWindow.py index 9155db871a..12136039d5 100644 --- a/contrib/src/sceneeditor/collisionWindow.py +++ b/contrib/src/sceneeditor/collisionWindow.py @@ -9,7 +9,6 @@ from seColorEntry import * from direct.tkwidgets import VectorWidgets from direct.tkwidgets import Floater from direct.tkwidgets import Slider -import string, math, types from panda3d.core import * diff --git a/contrib/src/sceneeditor/dataHolder.py b/contrib/src/sceneeditor/dataHolder.py index 4e01ab2fa4..db196dd233 100644 --- a/contrib/src/sceneeditor/dataHolder.py +++ b/contrib/src/sceneeditor/dataHolder.py @@ -2,7 +2,7 @@ # TK and PMW INTERFACE MODULES# ############################### from direct.showbase.TkGlobal import* -import Pmw +import Pmw, sys from direct.tkwidgets import Dial from direct.tkwidgets import Floater @@ -27,7 +27,6 @@ from direct.actor import Actor # Core Python Modules # ############################### import os -import string import sys import seParticleEffect diff --git a/contrib/src/sceneeditor/lightingPanel.py b/contrib/src/sceneeditor/lightingPanel.py index eeb8cafa20..d3eb2a5c0e 100644 --- a/contrib/src/sceneeditor/lightingPanel.py +++ b/contrib/src/sceneeditor/lightingPanel.py @@ -7,7 +7,7 @@ from direct.tkwidgets.AppShell import AppShell from seColorEntry import * from direct.tkwidgets.VectorWidgets import Vector3Entry from direct.tkwidgets.Slider import Slider -import sys, math, types, Pmw +import sys, Pmw from panda3d.core import * if sys.version_info >= (3, 0): diff --git a/contrib/src/sceneeditor/quad.py b/contrib/src/sceneeditor/quad.py index 6f4fcf03d0..a44bbe879e 100644 --- a/contrib/src/sceneeditor/quad.py +++ b/contrib/src/sceneeditor/quad.py @@ -10,7 +10,7 @@ from direct.showbase.ShowBaseGlobal import * from direct.interval.IntervalGlobal import * from direct.showbase.DirectObject import DirectObject from panda3d.core import * -import math +from direct.task import Task class ViewPort: diff --git a/contrib/src/sceneeditor/sceneEditor.py b/contrib/src/sceneeditor/sceneEditor.py index 1565e9eaed..3c4d291bbd 100644 --- a/contrib/src/sceneeditor/sceneEditor.py +++ b/contrib/src/sceneeditor/sceneEditor.py @@ -36,17 +36,12 @@ from seBlendAnimPanel import * from controllerWindow import * from AlignTool import * - - -import os -import string from direct.tkwidgets import Dial from direct.tkwidgets import Floater from direct.tkwidgets import Slider from direct.actor import Actor import seAnimPanel from direct.task import Task -import math ################################################################# # All scene and windows object will be stored in here. diff --git a/contrib/src/sceneeditor/seAnimPanel.py b/contrib/src/sceneeditor/seAnimPanel.py index 2dd3ceee53..ec7f8faf21 100644 --- a/contrib/src/sceneeditor/seAnimPanel.py +++ b/contrib/src/sceneeditor/seAnimPanel.py @@ -5,9 +5,7 @@ # Import Tkinter, Pmw, and the floater code from this directory tree. from direct.tkwidgets.AppShell import * from direct.showbase.TkGlobal import * -import string -import math -import types +import sys from direct.task import Task if sys.version_info >= (3, 0): @@ -407,7 +405,7 @@ class AnimPanel(AppShell): ################################################################# if self.animName in self['animList']: # Convert scale value to float - frame = string.atof(frame) + frame = float(frame) # Now convert t to seconds for offset calculations if self.unitsVar.get() == FRAMES: frame = frame / self.fps diff --git a/contrib/src/sceneeditor/seBlendAnimPanel.py b/contrib/src/sceneeditor/seBlendAnimPanel.py index 2ab28210c5..27b9c30957 100644 --- a/contrib/src/sceneeditor/seBlendAnimPanel.py +++ b/contrib/src/sceneeditor/seBlendAnimPanel.py @@ -5,9 +5,7 @@ # Import Tkinter, Pmw, and the floater code from this directory tree. from direct.tkwidgets.AppShell import * from direct.showbase.TkGlobal import * -import string -import math -import types +import sys from direct.task import Task if sys.version_info >= (3, 0): @@ -431,7 +429,7 @@ class BlendAnimPanel(AppShell): ################################################################# if (self.animNameA in self['animList'])and(self.animNameB in self['animList']): # Convert scale value to float - frame = string.atof(frame) + frame = float(frame) # Now convert t to seconds for offset calculations if self.unitsVar.get() == FRAMES: frame = frame / self.fps diff --git a/contrib/src/sceneeditor/seCameraControl.py b/contrib/src/sceneeditor/seCameraControl.py index 95237db8be..17bcedaf36 100644 --- a/contrib/src/sceneeditor/seCameraControl.py +++ b/contrib/src/sceneeditor/seCameraControl.py @@ -16,6 +16,7 @@ from direct.directtools.DirectUtil import * from seGeometry import * from direct.directtools.DirectGlobals import * from direct.task import Task +import math CAM_MOVE_DURATION = 1.2 COA_MARKER_SF = 0.0075 diff --git a/contrib/src/sceneeditor/seFileSaver.py b/contrib/src/sceneeditor/seFileSaver.py index 9d58fa0580..30c078493b 100644 --- a/contrib/src/sceneeditor/seFileSaver.py +++ b/contrib/src/sceneeditor/seFileSaver.py @@ -8,7 +8,6 @@ from panda3d.core import * from direct.showbase.ShowBaseGlobal import * import os import shutil -import string #################################################################################################################################################### #### These modules are modified versions of Disney's equivalent modules diff --git a/contrib/src/sceneeditor/seGrid.py b/contrib/src/sceneeditor/seGrid.py index b9785df261..cacff7299f 100644 --- a/contrib/src/sceneeditor/seGrid.py +++ b/contrib/src/sceneeditor/seGrid.py @@ -14,6 +14,7 @@ from direct.showbase.DirectObject import * from direct.directtools.DirectUtil import * from seGeometry import * +import math class DirectGrid(NodePath,DirectObject): def __init__(self): diff --git a/contrib/src/sceneeditor/seLights.py b/contrib/src/sceneeditor/seLights.py index 2353512af5..ce2436625e 100644 --- a/contrib/src/sceneeditor/seLights.py +++ b/contrib/src/sceneeditor/seLights.py @@ -5,7 +5,6 @@ from direct.showbase.DirectObject import * from direct.directtools import DirectUtil from panda3d.core import * -import string class seLight(NodePath): diff --git a/contrib/src/sceneeditor/seManipulation.py b/contrib/src/sceneeditor/seManipulation.py index 4d0c781b1e..a20a323749 100644 --- a/contrib/src/sceneeditor/seManipulation.py +++ b/contrib/src/sceneeditor/seManipulation.py @@ -17,6 +17,7 @@ from direct.directtools.DirectGlobals import * from direct.directtools.DirectUtil import * from seGeometry import * from direct.task import Task +import math class DirectManipulationControl(DirectObject): def __init__(self): @@ -601,7 +602,7 @@ class ObjectHandles(NodePath,DirectObject): self.reparentTo(hidden) def enableHandles(self, handles): - if type(handles) == types.ListType: + if type(handles) is list: for handle in handles: self.enableHandle(handle) elif handles == 'x': @@ -642,7 +643,7 @@ class ObjectHandles(NodePath,DirectObject): self.zDiscGroup.reparentTo(self.zHandles) def disableHandles(self, handles): - if type(handles) == types.ListType: + if type(handles) is list: for handle in handles: self.disableHandle(handle) elif handles == 'x': diff --git a/contrib/src/sceneeditor/seMopathRecorder.py b/contrib/src/sceneeditor/seMopathRecorder.py index dc8bbd8d22..65edba3880 100644 --- a/contrib/src/sceneeditor/seMopathRecorder.py +++ b/contrib/src/sceneeditor/seMopathRecorder.py @@ -25,7 +25,8 @@ from direct.tkwidgets.Slider import Slider from direct.tkwidgets.EntryScale import EntryScale from direct.tkwidgets.VectorWidgets import Vector2Entry, Vector3Entry from direct.tkwidgets.VectorWidgets import ColorEntry -import os, string, sys, Pmw +import os, sys, Pmw +import math if sys.version_info >= (3, 0): from tkinter import Button, Frame, Radiobutton, Checkbutton, Label @@ -374,7 +375,7 @@ class MopathRecorder(AppShell, DirectObject): self.speedEntry.bind( '', lambda e = None, s = self: s.setSpeedScale( - string.atof(s.speedVar.get()))) + float(s.speedVar.get()))) self.speedEntry.pack(side = tkinter.LEFT, expand = 0) frame.pack(fill = tkinter.X, expand = 1) diff --git a/contrib/src/sceneeditor/seParticles.py b/contrib/src/sceneeditor/seParticles.py index a4f0d0e5d6..df79e4ff47 100644 --- a/contrib/src/sceneeditor/seParticles.py +++ b/contrib/src/sceneeditor/seParticles.py @@ -3,7 +3,6 @@ from panda3d.physics import * from direct.particles.ParticleManagerGlobal import * from direct.showbase.PhysicsManagerGlobal import * #import OrientedParticleFactory -import string import os from direct.directnotify import DirectNotifyGlobal import sys diff --git a/contrib/src/sceneeditor/seSession.py b/contrib/src/sceneeditor/seSession.py index c8e7a1a20f..2077398070 100644 --- a/contrib/src/sceneeditor/seSession.py +++ b/contrib/src/sceneeditor/seSession.py @@ -20,9 +20,9 @@ from seGeometry import * from direct.tkpanels import Placer from direct.tkwidgets import Slider from direct.gui import OnscreenText -import types -import string +from direct.task import Task from direct.showbase import Loader +import math class SeSession(DirectObject): ### Customized DirectSession diff --git a/contrib/src/sceneeditor/seTree.py b/contrib/src/sceneeditor/seTree.py index 9927c11112..81c108fcf3 100644 --- a/contrib/src/sceneeditor/seTree.py +++ b/contrib/src/sceneeditor/seTree.py @@ -12,7 +12,7 @@ # ################################################################# -import os, sys, string, Pmw +import os, sys, Pmw from direct.showbase.DirectObject import DirectObject from panda3d.core import * @@ -221,7 +221,7 @@ class TreeNode: self.children[key] = child self.kidKeys.append(key) # Remove unused children - for key in self.children.keys(): + for key in list(self.children.keys()): if key not in self.kidKeys: del(self.children[key]) cx = x+20 diff --git a/direct/src/stdpy/pickle.py b/direct/src/stdpy/pickle.py index 03ef1969d0..77390d6853 100644 --- a/direct/src/stdpy/pickle.py +++ b/direct/src/stdpy/pickle.py @@ -30,19 +30,26 @@ from copyreg import dispatch_table # with the local pickle.py. pickle = __import__('pickle') -class Pickler(pickle.Pickler): +BasePickler = pickle._Pickler +BaseUnpickler = pickle._Unpickler + + +class _Pickler(BasePickler): def __init__(self, *args, **kw): self.bamWriter = BamWriter() - pickle.Pickler.__init__(self, *args, **kw) + BasePickler.__init__(self, *args, **kw) # We have to duplicate most of the save() method, so we can add # support for __reduce_persist__(). - def save(self, obj): + def save(self, obj, save_persistent_id=True): + if self.proto >= 4: + self.framer.commit_frame() + # Check for persistent id (defined by a subclass) pid = self.persistent_id(obj) - if pid: + if pid is not None and save_persistent_id: self.save_pers(pid) return @@ -109,11 +116,12 @@ class Pickler(pickle.Pickler): # Save the reduce() output and finally memoize the object self.save_reduce(obj=obj, *rv) -class Unpickler(pickle.Unpickler): + +class Unpickler(BaseUnpickler): def __init__(self, *args, **kw): self.bamReader = BamReader() - pickle.Unpickler.__init__(self, *args, **kw) + BaseUnpickler.__init__(self, *args, **kw) # Duplicate the load_reduce() function, to provide a special case # for the reduction function. @@ -123,9 +131,10 @@ class Unpickler(pickle.Unpickler): args = stack.pop() func = stack[-1] - # If the function name ends with "Persist", then assume the + # If the function name ends with "_persist", then assume the # function wants the Unpickler as the first parameter. - if func.__name__.endswith('Persist'): + func_name = func.__name__ + if func_name.endswith('_persist') or func_name.endswith('Persist'): value = func(self, *args) else: # Otherwise, use the existing pickle convention. @@ -133,9 +142,26 @@ class Unpickler(pickle.Unpickler): stack[-1] = value - #FIXME: how to replace in Python 3? - if sys.version_info < (3, 0): - pickle.Unpickler.dispatch[pickle.REDUCE] = load_reduce + BaseUnpickler.dispatch[pickle.REDUCE[0]] = load_reduce + + +if sys.version_info >= (3, 8): + # In Python 3.8 and up, we can use the C implementation of Pickler, which + # supports a reducer_override method. + class Pickler(pickle.Pickler): + def __init__(self, *args, **kw): + self.bamWriter = BamWriter() + pickle.Pickler.__init__(self, *args, **kw) + + def reducer_override(self, obj): + reduce = getattr(obj, "__reduce_persist__", None) + if reduce: + return reduce(self) + + return NotImplemented +else: + # Otherwise, we have to use our custom version that overrides save(). + Pickler = _Pickler # Shorthands diff --git a/tests/stdpy/test_pickle.py b/tests/stdpy/test_pickle.py new file mode 100644 index 0000000000..303c5559c1 --- /dev/null +++ b/tests/stdpy/test_pickle.py @@ -0,0 +1,11 @@ +from direct.stdpy.pickle import dumps, loads + + +def test_reduce_persist(): + from panda3d.core import NodePath + + parent = NodePath("parent") + child = parent.attach_new_node("child") + + parent2, child2 = loads(dumps([parent, child])) + assert tuple(parent2.children) == (child2,)