From b01729f4efccfaa969ce21835df3f178890088a1 Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Wed, 12 Apr 2017 13:57:08 -0700 Subject: [PATCH 1/4] Tighten up allowed types in auto sequence conversions Instead of allowing generic sequences to be convertible to wxPoint, wxSize, and others, explicitly allow only tuples and lists. This is needed because these types also have methods that make them look like sequences, which meant that you could pass a wxSize where a wxPoint is expected, and so on. Even worse is nonsense stuff like: wx.Point(10,20) == wx.Size(10,20) evaluating to True. --- etg/colour.py | 3 ++- etg/gdicmn.py | 2 ++ etgtools/tweaker_tools.py | 8 ++++---- unittests/test_colour.py | 8 ++++++++ unittests/test_gdicmn.py | 8 ++++++++ 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/etg/colour.py b/etg/colour.py index d5be436b..10d0a455 100644 --- a/etg/colour.py +++ b/etg/colour.py @@ -196,7 +196,7 @@ def run(): return 1; if (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy)) return 1; - if (PySequence_Check(sipPy)) { + if (PyTuple_Check(sipPy) || PyList_Check(sipPy)) { size_t len = PySequence_Size(sipPy); if (len != 3 && len != 4) return 0; @@ -212,6 +212,7 @@ def run(): } return 0; } + // otherwise do the conversion // is it None? if (sipPy == Py_None) { diff --git a/etg/gdicmn.py b/etg/gdicmn.py index 48ad903e..00c8e63e 100644 --- a/etg/gdicmn.py +++ b/etg/gdicmn.py @@ -91,8 +91,10 @@ def run(): c.addItem(etgtools.WigCode("""\ wxPoint operator+(const wxPoint& other); + wxPoint operator+(const wxSize& other); wxPoint operator-(); wxPoint operator-(const wxPoint& other); + wxPoint operator-(const wxSize& other); wxPoint operator*(int i); wxPoint operator/(int i); """)) diff --git a/etgtools/tweaker_tools.py b/etgtools/tweaker_tools.py index d4797ab5..ed83f6f9 100644 --- a/etgtools/tweaker_tools.py +++ b/etgtools/tweaker_tools.py @@ -626,7 +626,7 @@ def convertTwoIntegersTemplate(CLASS): if (sipCanConvertToType(sipPy, sipType_{CLASS}, SIP_NO_CONVERTORS)) return 1; - if (PySequence_Check(sipPy) && PySequence_Size(sipPy) == 2) {{ + if ((PyTuple_Check(sipPy) || PyList_Check(sipPy)) && PySequence_Size(sipPy) == 2) {{ int rval = 1; PyObject* o1 = PySequence_ITEM(sipPy, 0); PyObject* o2 = PySequence_ITEM(sipPy, 1); @@ -666,7 +666,7 @@ def convertFourIntegersTemplate(CLASS): if (sipCanConvertToType(sipPy, sipType_{CLASS}, SIP_NO_CONVERTORS)) return 1; - if (PySequence_Check(sipPy) && PySequence_Size(sipPy) == 4) {{ + if ((PyTuple_Check(sipPy) || PyList_Check(sipPy)) && PySequence_Size(sipPy) == 4) {{ int rval = 1; PyObject* o1 = PySequence_ITEM(sipPy, 0); PyObject* o2 = PySequence_ITEM(sipPy, 1); @@ -713,7 +713,7 @@ def convertTwoDoublesTemplate(CLASS): if (sipCanConvertToType(sipPy, sipType_{CLASS}, SIP_NO_CONVERTORS)) return 1; - if (PySequence_Check(sipPy) && PySequence_Size(sipPy) == 2) {{ + if ((PyTuple_Check(sipPy) || PyList_Check(sipPy)) && PySequence_Size(sipPy) == 2) {{ int rval = 1; PyObject* o1 = PySequence_ITEM(sipPy, 0); PyObject* o2 = PySequence_ITEM(sipPy, 1); @@ -753,7 +753,7 @@ def convertFourDoublesTemplate(CLASS): if (sipCanConvertToType(sipPy, sipType_{CLASS}, SIP_NO_CONVERTORS)) return 1; - if (PySequence_Check(sipPy) && PySequence_Size(sipPy) == 4) {{ + if ((PyTuple_Check(sipPy) || PyList_Check(sipPy)) && PySequence_Size(sipPy) == 4) {{ int rval = 1; PyObject* o1 = PySequence_ITEM(sipPy, 0); PyObject* o2 = PySequence_ITEM(sipPy, 1); diff --git a/unittests/test_colour.py b/unittests/test_colour.py index 5ad7bd87..9a7995da 100644 --- a/unittests/test_colour.py +++ b/unittests/test_colour.py @@ -34,6 +34,14 @@ class Colour(wtc.WidgetTestCase): c1 = wx.Colour(1,2,3,4) p = c1.GetPixel() + def test_converters(self): + # Ensure that comparing different types don't accidentally work + # because of making the classes look like sequences + c = wx.Colour(1,2,3,4) + r = wx.Rect(1,2,3,4) + self.assertFalse( c == r ) + self.assertFalse( r == c ) + if hasattr(wx, 'testColourTypeMap'): def test_ColourTypemaps(self): diff --git a/unittests/test_gdicmn.py b/unittests/test_gdicmn.py index 71847797..daa3eaf7 100644 --- a/unittests/test_gdicmn.py +++ b/unittests/test_gdicmn.py @@ -117,6 +117,14 @@ class Point(unittest.TestCase): self.assertEqual(p6, (-4,-6)) + def test_converters(self): + # Ensure that comparing different types don't accidentally work + # because of making the classes look like sequences + p = wx.Point(10,20) + s = wx.Size(10,20) + self.assertFalse( p == s ) + self.assertFalse( s == p ) + #--------------------------------------------------------------------------- From 708e2487dce6dc303d7562b1fe4483d4b64be185 Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Wed, 12 Apr 2017 14:32:50 -0700 Subject: [PATCH 2/4] Since we know it is a Tuple or List we can use PySequence_Fast_GET_ITEM --- etg/colour.py | 19 ++++------- etgtools/tweaker_tools.py | 70 ++++++++++++++------------------------- src/wxpy_api.sip | 1 + 3 files changed, 33 insertions(+), 57 deletions(-) diff --git a/etg/colour.py b/etg/colour.py index 10d0a455..21da8581 100644 --- a/etg/colour.py +++ b/etg/colour.py @@ -202,9 +202,8 @@ def run(): return 0; // ensure all the items in the sequence are numbers for (int idx=0; idx Date: Wed, 12 Apr 2017 16:55:22 -0700 Subject: [PATCH 3/4] =?UTF-8?q?Don=E2=80=99t=20test=20with=20the=20=3D=3D?= =?UTF-8?q?=20operators,=20that=20will=20be=20changing=20in=20a=20differen?= =?UTF-8?q?t=20way=20in=20another=20PR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- unittests/test_colour.py | 11 +++++------ unittests/test_gdicmn.py | 23 +++++++++++++++++------ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/unittests/test_colour.py b/unittests/test_colour.py index 9a7995da..89456e7f 100644 --- a/unittests/test_colour.py +++ b/unittests/test_colour.py @@ -34,13 +34,12 @@ class Colour(wtc.WidgetTestCase): c1 = wx.Colour(1,2,3,4) p = c1.GetPixel() + def test_converters(self): - # Ensure that comparing different types don't accidentally work - # because of making the classes look like sequences - c = wx.Colour(1,2,3,4) - r = wx.Rect(1,2,3,4) - self.assertFalse( c == r ) - self.assertFalse( r == c ) + # Ensure that other types that are sequence-like can't be + # auto-converted, the copy constructor is good-enough for testing this + with self.assertRaises(TypeError): + p = wx.Colour(wx.Rect(1,2,3,4)) if hasattr(wx, 'testColourTypeMap'): diff --git a/unittests/test_gdicmn.py b/unittests/test_gdicmn.py index daa3eaf7..e1838a5b 100644 --- a/unittests/test_gdicmn.py +++ b/unittests/test_gdicmn.py @@ -118,12 +118,10 @@ class Point(unittest.TestCase): def test_converters(self): - # Ensure that comparing different types don't accidentally work - # because of making the classes look like sequences - p = wx.Point(10,20) - s = wx.Size(10,20) - self.assertFalse( p == s ) - self.assertFalse( s == p ) + # Ensure that other types that are sequence-like can't be + # auto-converted, the copy constructor is good-enough for testing this + with self.assertRaises(TypeError): + p = wx.Point(wx.Size(10,20)) #--------------------------------------------------------------------------- @@ -243,6 +241,13 @@ class Size(unittest.TestCase): s[2] + def test_converters(self): + # Ensure that other types that are sequence-like can't be + # auto-converted, the copy constructor is good-enough for testing this + with self.assertRaises(TypeError): + p = wx.Size(wx.Point(10,20)) + + #--------------------------------------------------------------------------- @@ -307,6 +312,12 @@ class Rect(unittest.TestCase): self.assertTrue(r.x == 0 and r.y == 0) + def test_converters(self): + # Ensure that other types that are sequence-like can't be + # auto-converted, the copy constructor is good-enough for testing this + with self.assertRaises(TypeError): + p = wx.Rect(wx.Colour(1,2,3,4)) + # TODO: more tests! From 09223c530fe0484774692d7d8d0521d0482d5417 Mon Sep 17 00:00:00 2001 From: "Christopher H.Barker, PhD" Date: Thu, 13 Apr 2017 11:17:36 -0700 Subject: [PATCH 4/4] added float() calls to get the proper divison when scaling bitmaps In response to a note from Kevin Gregory: "" Sorry to email you directly, I wanted to submit a bugfix for FloatCanvas ScaledBitmap. It changes the bmpWidth and bmpHeight from integers to floats so that the scale is computed correctly. FCObjects.py line 2141 from the wxpython phoenix dev build """ --- wx/lib/floatcanvas/FCObjects.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wx/lib/floatcanvas/FCObjects.py b/wx/lib/floatcanvas/FCObjects.py index ec382e0a..a4cfd97b 100644 --- a/wx/lib/floatcanvas/FCObjects.py +++ b/wx/lib/floatcanvas/FCObjects.py @@ -2138,7 +2138,7 @@ class ScaledBitmap(TextObjectMixin, DrawObject): self.XY = XY self.Height = Height - (self.bmpWidth, self.bmpHeight) = self.Image.GetWidth(), self.Image.GetHeight() + (self.bmpWidth, self.bmpHeight) = float(self.Image.GetWidth()), float(self.Image.GetHeight()) self.Width = self.bmpWidth / self.bmpHeight * Height self.ShiftFun = self.ShiftFunDict[Position] self.CalcBoundingBox() @@ -2225,7 +2225,7 @@ class ScaledBitmap2(TextObjectMixin, DrawObject, ): self.XY = N.array(XY, N.float) self.Height = Height - (self.bmpWidth, self.bmpHeight) = self.Image.GetWidth(), self.Image.GetHeight() + (self.bmpWidth, self.bmpHeight) = float(self.Image.GetWidth()), float(self.Image.GetHeight()) self.bmpWH = N.array((self.bmpWidth, self.bmpHeight), N.int32) ## fixme: this should all accommodate different scales for X and Y if Width is None: