mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2026-01-09 05:20:08 +01:00
Also allow numpy arrays for sequence conversions to value types
This commit is contained in:
@@ -198,17 +198,7 @@ def run():
|
||||
return 1;
|
||||
if (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy))
|
||||
return 1;
|
||||
if (PyTuple_Check(sipPy) || PyList_Check(sipPy)) {
|
||||
size_t len = PySequence_Size(sipPy);
|
||||
if (len != 3 && len != 4)
|
||||
return 0;
|
||||
// ensure all the items in the sequence are numbers
|
||||
for (int idx=0; idx<len; idx+=1) {
|
||||
PyObject* o = PySequence_Fast_GET_ITEM(sipPy, idx);
|
||||
bool isNum = PyNumber_Check(o);
|
||||
if (!isNum)
|
||||
return 0;
|
||||
}
|
||||
if (wxPyNumberSequenceCheck(sipPy, 4) || wxPyNumberSequenceCheck(sipPy, 3)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -255,20 +245,24 @@ def run():
|
||||
return sipGetState(sipTransferObj);
|
||||
}
|
||||
}
|
||||
// Is it a 3 or 4 element sequence?
|
||||
else if (PyTuple_Check(sipPy) || PyList_Check(sipPy)) {
|
||||
// Is it a sequence? (if so then length was checked above)
|
||||
else if (wxPyNumberSequenceCheck(sipPy)) {
|
||||
size_t len = PySequence_Size(sipPy);
|
||||
|
||||
PyObject* o1 = PySequence_Fast_GET_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_Fast_GET_ITEM(sipPy, 1);
|
||||
PyObject* o3 = PySequence_Fast_GET_ITEM(sipPy, 2);
|
||||
PyObject* o1 = PySequence_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_ITEM(sipPy, 1);
|
||||
PyObject* o3 = PySequence_ITEM(sipPy, 2);
|
||||
if (len == 3)
|
||||
*sipCppPtr = new wxColour(wxPyInt_AsLong(o1), wxPyInt_AsLong(o2), wxPyInt_AsLong(o3));
|
||||
else {
|
||||
PyObject* o4 = PySequence_Fast_GET_ITEM(sipPy, 3);
|
||||
PyObject* o4 = PySequence_ITEM(sipPy, 3);
|
||||
*sipCppPtr = new wxColour(wxPyInt_AsLong(o1), wxPyInt_AsLong(o2), wxPyInt_AsLong(o3),
|
||||
wxPyInt_AsLong(o4));
|
||||
Py_DECREF(o4);
|
||||
}
|
||||
Py_DECREF(o1);
|
||||
Py_DECREF(o2);
|
||||
Py_DECREF(o3);
|
||||
return sipGetState(sipTransferObj);
|
||||
}
|
||||
|
||||
|
||||
@@ -653,13 +653,8 @@ def convertTwoIntegersTemplate(CLASS):
|
||||
if (sipCanConvertToType(sipPy, sipType_{CLASS}, SIP_NO_CONVERTORS))
|
||||
return 1;
|
||||
|
||||
if ((PyTuple_Check(sipPy) || PyList_Check(sipPy)) && PySequence_Size(sipPy) == 2) {{
|
||||
int rval = 1;
|
||||
PyObject* o1 = PySequence_Fast_GET_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_Fast_GET_ITEM(sipPy, 1);
|
||||
if (!PyNumber_Check(o1) || !PyNumber_Check(o2))
|
||||
rval = 0;
|
||||
return rval;
|
||||
if (wxPyNumberSequenceCheck(sipPy, 2)) {{
|
||||
return 1;
|
||||
}}
|
||||
return 0;
|
||||
}}
|
||||
@@ -673,9 +668,11 @@ def convertTwoIntegersTemplate(CLASS):
|
||||
}}
|
||||
|
||||
// or create a new instance
|
||||
PyObject* o1 = PySequence_Fast_GET_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_Fast_GET_ITEM(sipPy, 1);
|
||||
PyObject* o1 = PySequence_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_ITEM(sipPy, 1);
|
||||
*sipCppPtr = new {CLASS}(wxPyInt_AsLong(o1), wxPyInt_AsLong(o2));
|
||||
Py_DECREF(o1);
|
||||
Py_DECREF(o2);
|
||||
return SIP_TEMPORARY;
|
||||
""".format(**locals())
|
||||
|
||||
@@ -689,15 +686,8 @@ def convertFourIntegersTemplate(CLASS):
|
||||
if (sipCanConvertToType(sipPy, sipType_{CLASS}, SIP_NO_CONVERTORS))
|
||||
return 1;
|
||||
|
||||
if ((PyTuple_Check(sipPy) || PyList_Check(sipPy)) && PySequence_Size(sipPy) == 4) {{
|
||||
int rval = 1;
|
||||
PyObject* o1 = PySequence_Fast_GET_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_Fast_GET_ITEM(sipPy, 1);
|
||||
PyObject* o3 = PySequence_Fast_GET_ITEM(sipPy, 2);
|
||||
PyObject* o4 = PySequence_Fast_GET_ITEM(sipPy, 3);
|
||||
if (!PyNumber_Check(o1) || !PyNumber_Check(o2) || !PyNumber_Check(o3) || !PyNumber_Check(o4))
|
||||
rval = 0;
|
||||
return rval;
|
||||
if (wxPyNumberSequenceCheck(sipPy, 4)) {{
|
||||
return 1;
|
||||
}}
|
||||
return 0;
|
||||
}}
|
||||
@@ -710,12 +700,16 @@ def convertFourIntegersTemplate(CLASS):
|
||||
return 0; // not a new instance
|
||||
}}
|
||||
// or create a new instance
|
||||
PyObject* o1 = PySequence_Fast_GET_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_Fast_GET_ITEM(sipPy, 1);
|
||||
PyObject* o3 = PySequence_Fast_GET_ITEM(sipPy, 2);
|
||||
PyObject* o4 = PySequence_Fast_GET_ITEM(sipPy, 3);
|
||||
PyObject* o1 = PySequence_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_ITEM(sipPy, 1);
|
||||
PyObject* o3 = PySequence_ITEM(sipPy, 2);
|
||||
PyObject* o4 = PySequence_ITEM(sipPy, 3);
|
||||
*sipCppPtr = new {CLASS}(wxPyInt_AsLong(o1), wxPyInt_AsLong(o2),
|
||||
wxPyInt_AsLong(o3), wxPyInt_AsLong(o4));
|
||||
Py_DECREF(o1);
|
||||
Py_DECREF(o2);
|
||||
Py_DECREF(o3);
|
||||
Py_DECREF(o4);
|
||||
return SIP_TEMPORARY;
|
||||
""".format(**locals())
|
||||
|
||||
@@ -730,14 +724,9 @@ def convertTwoDoublesTemplate(CLASS):
|
||||
if (sipCanConvertToType(sipPy, sipType_{CLASS}, SIP_NO_CONVERTORS))
|
||||
return 1;
|
||||
|
||||
if ((PyTuple_Check(sipPy) || PyList_Check(sipPy)) && PySequence_Size(sipPy) == 2) {{
|
||||
int rval = 1;
|
||||
PyObject* o1 = PySequence_Fast_GET_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_Fast_GET_ITEM(sipPy, 1);
|
||||
if (!PyNumber_Check(o1) || !PyNumber_Check(o2))
|
||||
rval = 0;
|
||||
return rval;
|
||||
}}
|
||||
if (wxPyNumberSequenceCheck(sipPy, 2)) {{
|
||||
return 1;
|
||||
}}
|
||||
return 0;
|
||||
}}
|
||||
|
||||
@@ -750,9 +739,11 @@ def convertTwoDoublesTemplate(CLASS):
|
||||
}}
|
||||
|
||||
// or create a new instance
|
||||
PyObject* o1 = PySequence_Fast_GET_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_Fast_GET_ITEM(sipPy, 1);
|
||||
PyObject* o1 = PySequence_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_ITEM(sipPy, 1);
|
||||
*sipCppPtr = new {CLASS}(PyFloat_AsDouble(o1), PyFloat_AsDouble(o2));
|
||||
Py_DECREF(o1);
|
||||
Py_DECREF(o2);
|
||||
return SIP_TEMPORARY;
|
||||
""".format(**locals())
|
||||
|
||||
@@ -766,15 +757,8 @@ def convertFourDoublesTemplate(CLASS):
|
||||
if (sipCanConvertToType(sipPy, sipType_{CLASS}, SIP_NO_CONVERTORS))
|
||||
return 1;
|
||||
|
||||
if ((PyTuple_Check(sipPy) || PyList_Check(sipPy)) && PySequence_Size(sipPy) == 4) {{
|
||||
int rval = 1;
|
||||
PyObject* o1 = PySequence_Fast_GET_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_Fast_GET_ITEM(sipPy, 1);
|
||||
PyObject* o3 = PySequence_Fast_GET_ITEM(sipPy, 2);
|
||||
PyObject* o4 = PySequence_Fast_GET_ITEM(sipPy, 3);
|
||||
if (!PyNumber_Check(o1) || !PyNumber_Check(o2) || !PyNumber_Check(o3) || !PyNumber_Check(o4))
|
||||
rval = 0;
|
||||
return rval;
|
||||
if (wxPyNumberSequenceCheck(sipPy, 4)) {{
|
||||
return 1;
|
||||
}}
|
||||
return 0;
|
||||
}}
|
||||
@@ -788,12 +772,16 @@ def convertFourDoublesTemplate(CLASS):
|
||||
}}
|
||||
|
||||
// or create a new instance
|
||||
PyObject* o1 = PySequence_Fast_GET_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_Fast_GET_ITEM(sipPy, 1);
|
||||
PyObject* o3 = PySequence_Fast_GET_ITEM(sipPy, 2);
|
||||
PyObject* o4 = PySequence_Fast_GET_ITEM(sipPy, 3);
|
||||
PyObject* o1 = PySequence_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_ITEM(sipPy, 1);
|
||||
PyObject* o3 = PySequence_ITEM(sipPy, 2);
|
||||
PyObject* o4 = PySequence_ITEM(sipPy, 3);
|
||||
*sipCppPtr = new {CLASS}(PyFloat_AsDouble(o1), PyFloat_AsDouble(o2),
|
||||
PyFloat_AsDouble(o3), PyFloat_AsDouble(o4));
|
||||
Py_DECREF(o1);
|
||||
Py_DECREF(o2);
|
||||
Py_DECREF(o3);
|
||||
Py_DECREF(o4);
|
||||
return SIP_TEMPORARY;
|
||||
""".format(**locals())
|
||||
|
||||
|
||||
@@ -150,6 +150,48 @@ Py_ssize_t wxPyUnicode_AsWideChar(PyObject* unicode, wchar_t* w, Py_ssize_t size
|
||||
}
|
||||
|
||||
|
||||
inline bool wxPyNumberSequenceCheck(PyObject* obj, int reqLength=-1) {
|
||||
// Used in the various places where a sequence of numbers can be converted
|
||||
// to a wx type, like wxPoint, wxSize, wxColour, etc. Returns true if the
|
||||
// object is a Tuple, List or numpy Array of the proper length.
|
||||
|
||||
// tuples or lists are easy
|
||||
bool isFast = (PyTuple_Check(obj) || PyList_Check(obj));
|
||||
|
||||
if (!isFast ) {
|
||||
// If it's not one of those, then check for an array.
|
||||
// It's probably not a good idea to do it this way, but this allows us
|
||||
// to check if the object is a numpy array without requiring that
|
||||
// numpy be imported even for those applications tha are not using it.
|
||||
if (strcmp(obj->ob_type->tp_name, "numpy.ndarray") != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bail out here if the length isn't given
|
||||
if (reqLength == -1)
|
||||
return true;
|
||||
|
||||
// Now check that the length matches the expected length
|
||||
if (PySequence_Length(obj) != reqLength)
|
||||
return false;
|
||||
|
||||
// Check that each item is a number
|
||||
for (int i=0; i<reqLength; i+=1) {
|
||||
PyObject* item;
|
||||
if (isFast)
|
||||
item = PySequence_Fast_GET_ITEM(obj, i);
|
||||
else
|
||||
item = PySequence_ITEM(obj, i);
|
||||
bool isNum = PyNumber_Check(item);
|
||||
if (!isFast)
|
||||
Py_DECREF(item);
|
||||
if (!isNum)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// These are the API items whose implementation can not or should not be
|
||||
// inline functions or macros. The implementations will instead be accessed
|
||||
|
||||
@@ -30,6 +30,23 @@ class Colour(wtc.WidgetTestCase):
|
||||
self.assertTrue(c1.Get() == c2.Get())
|
||||
|
||||
|
||||
def test_seq_ctor1(self):
|
||||
c = wx.Colour( [1,2,3,4] )
|
||||
self.assertTrue(c.Get() == (1,2,3,4))
|
||||
|
||||
|
||||
def test_seq_ctor2(self):
|
||||
c = wx.Colour( [1,2,3] )
|
||||
self.assertTrue(c.Get(False) == (1,2,3))
|
||||
|
||||
|
||||
def test_numpy_ctor(self):
|
||||
import numpy
|
||||
a = numpy.array( [1,2,3,4] )
|
||||
c = wx.Colour(a)
|
||||
self.assertTrue(c.Get() == (1,2,3,4))
|
||||
|
||||
|
||||
def test_GetPixel(self):
|
||||
c1 = wx.Colour(1,2,3,4)
|
||||
p = c1.GetPixel()
|
||||
|
||||
@@ -31,6 +31,15 @@ class Point(unittest.TestCase):
|
||||
with self.assertRaises(TypeError):
|
||||
p = wx.Point(1,2,3)
|
||||
|
||||
def test_seq_ctor(self):
|
||||
p = wx.Point( [123,456] )
|
||||
|
||||
def test_numpy_ctor(self):
|
||||
import numpy
|
||||
a = numpy.array([123,456])
|
||||
p = wx.Point(a)
|
||||
|
||||
|
||||
def test_DefaultPosition(self):
|
||||
wx.DefaultPosition
|
||||
self.assertTrue(wx.DefaultPosition == (-1,-1))
|
||||
@@ -331,20 +340,31 @@ class Rect(unittest.TestCase):
|
||||
self.assertTrue(r == wx.Rect(pos=(10,10), size=(100,100)))
|
||||
|
||||
def test_tlbr_ctor(self):
|
||||
# TODO: we have to use keyword args here since wx.Point has sequence
|
||||
# protocol methods then it can also match the typemap for wxSize and
|
||||
# the other ctor is found first. Check if there is a way to fix or
|
||||
# work around this.
|
||||
r = wx.Rect(topLeft=wx.Point(10,10), bottomRight=wx.Point(100,100))
|
||||
self.assertTrue(r.width == 91 and r.height == 91)
|
||||
self.assertTrue(r.bottomRight == wx.Point(100,100))
|
||||
self.assertTrue(r.topLeft == wx.Point(10,10))
|
||||
|
||||
def test_tlbr_ctor2(self):
|
||||
r = wx.Rect(wx.Point(10,10), wx.Point(100,100))
|
||||
self.assertTrue(r.width == 91 and r.height == 91)
|
||||
self.assertTrue(r.bottomRight == wx.Point(100,100))
|
||||
self.assertTrue(r.topLeft == wx.Point(10,10))
|
||||
|
||||
def test_size_ctor(self):
|
||||
r = wx.Rect(wx.Size(50,100))
|
||||
self.assertTrue(r.width == 50 and r.height == 100)
|
||||
self.assertTrue(r.x == 0 and r.y == 0)
|
||||
|
||||
def test_seq_ctor(self):
|
||||
r1 = wx.Rect( [1,2,3,4] )
|
||||
self.assertTrue(r1 == (1,2,3,4))
|
||||
|
||||
def test_numpy_ctor(self):
|
||||
import numpy
|
||||
r1 = wx.Rect( numpy.array([1,2,3,4]) )
|
||||
self.assertTrue(r1 == (1,2,3,4))
|
||||
|
||||
|
||||
def test_GetIM(self):
|
||||
# Test the immutable version returned by GetIM
|
||||
|
||||
Reference in New Issue
Block a user