From 360e3e6b2f9f14429a992a47e9a4df93202f9fee Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Fri, 27 Jan 2017 20:44:09 -0800 Subject: [PATCH] Instead of using copy.copy to implement Clone, create the new instance with __new__ --- etg/pyevent.py | 40 ++++++++++----------------------------- unittests/test_pyevent.py | 10 ++++++++++ 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/etg/pyevent.py b/etg/pyevent.py index 3e10b818..5cff050d 100644 --- a/etg/pyevent.py +++ b/etg/pyevent.py @@ -11,6 +11,8 @@ import etgtools import etgtools.tweaker_tools as tools from etgtools.extractors import ClassDef, MethodDef, ParamDef +import copy + PACKAGE = "wx" MODULE = "_core" NAME = "pyevent" # Base name of the file to generate to for this script @@ -73,25 +75,14 @@ def run(): Through the magic of Python this implementation should work for this and all derived classes.""", body="""\ - # Create a new instance - import copy - clone = copy.copy(self) - # and then invoke the C++ copy constructor to copy the C++ bits too. + # Create a new instance of the same type as this instance and + # then invoke the C++ copy constructor to copy the C++ parts and + # any custom attributes. + clone = wx.PyEvent.__new__(self.__class__) wx.PyEvent.__init__(clone, self) return clone """) - cls.addPyMethod("__setstate__", "(self, state)", - doc = """Sets internal state of PyEvent object. This allows PyEvent to be reconstructed as part of the pickling process""", - body = """\ - self.__dict__.update(state) - """) - - cls.addPyMethod("__getstate__", "(self)", - doc = "Returns this object's internal state. This is used as part of the pickling process", - body = """\ - return self.__dict__ - """) module.addItem(cls) cls.addCppCode("IMPLEMENT_DYNAMIC_CLASS(wxPyEvent, wxEvent);") @@ -142,25 +133,14 @@ def run(): Through the magic of Python this implementation should work for this and all derived classes.""", body="""\ - # Create a new instance - import copy - clone = copy.copy(self) - # and then invoke the C++ copy constructor to copy the C++ bits too. + # Create a new instance of the same type as this instance and + # then invoke the C++ copy constructor to copy the C++ parts and + # any custom attributes. + clone = wx.PyCommandEvent.__new__(self.__class__) wx.PyCommandEvent.__init__(clone, self) return clone """) - cls.addPyMethod("__setstate__", "(self, state)", - doc = """Sets internal state of PyEvent object. This allows PyEvent to be reconstructed as part of the pickling process""", - body = """\ - self.__dict__.update(state) - """) - - cls.addPyMethod("__getstate__", "(self)", - doc = "Returns this object's internal state. This is used as part of the pickling process", - body = """\ - return self.__dict__ - """) module.addItem(cls) cls.addCppCode("IMPLEMENT_DYNAMIC_CLASS(wxPyCommandEvent, wxCommandEvent);") diff --git a/unittests/test_pyevent.py b/unittests/test_pyevent.py index ebd5cbe1..d0b2631b 100644 --- a/unittests/test_pyevent.py +++ b/unittests/test_pyevent.py @@ -60,6 +60,16 @@ class PyEvents(unittest.TestCase): self.assertTrue(evt1.attr == evt2.attr) + def test_CppCloneDerived(self): + # test what happens when Clone is called from C++ + if hasattr(wx, 'testCppClone'): + evt1 = MyPyEvent() + evt1.attr = 'testCppClone' + evt2 = wx.testCppClone(evt1) + self.assertTrue(evt1.attr == evt2.attr) + self.assertTrue(isinstance(evt2, MyPyEvent)) + + @unittest.skip('not testing refcounts for now, needs checking...') def test_CppCloneRefCounts(self): # Since we're doing some funky stuff under the covers with Clone, make