mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2026-01-05 11:30:06 +01:00
Add magic methods to wx.Size and add unit tests for wx.Size. Also a bit of related refactoring and cleanup.
git-svn-id: https://svn.wxwidgets.org/svn/wx/sandbox/trunk/Phoenix@66147 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -29,9 +29,9 @@ etgtools.parseDoxyXML(module, ITEMS)
|
||||
# Tweak the parsed meta objects in the module object as needed for customizing
|
||||
# the generated code and docstrings.
|
||||
|
||||
import etgtools.tweaker_tools
|
||||
etgtools.tweaker_tools.ignoreAssignmentOperators(module)
|
||||
etgtools.tweaker_tools.removeWxPrefixes(module)
|
||||
import etgtools.tweaker_tools as tools
|
||||
tools.ignoreAssignmentOperators(module)
|
||||
tools.removeWxPrefixes(module)
|
||||
|
||||
|
||||
# These items are in their own etg scripts for easier maintainability,
|
||||
|
||||
@@ -32,9 +32,9 @@ etgtools.parseDoxyXML(module, ITEMS)
|
||||
# Tweak the parsed meta objects in the module object as needed for customizing
|
||||
# the generated code and docstrings.
|
||||
|
||||
import etgtools.tweaker_tools
|
||||
etgtools.tweaker_tools.ignoreAssignmentOperators(module)
|
||||
etgtools.tweaker_tools.removeWxPrefixes(module)
|
||||
import etgtools.tweaker_tools as tools
|
||||
tools.ignoreAssignmentOperators(module)
|
||||
tools.removeWxPrefixes(module)
|
||||
|
||||
|
||||
module.addHeaderCode('#include <wx/wx.h>')
|
||||
@@ -73,7 +73,7 @@ c = module.find('wxPoint')
|
||||
|
||||
# Some operators are documented within the class that shouldn't be, so just
|
||||
# ignore them all.
|
||||
etgtools.tweaker_tools.ignoreAllOperators(c)
|
||||
tools.ignoreAllOperators(c)
|
||||
|
||||
# Undo a few of those ignores for legitimate items that were
|
||||
# documented correctly
|
||||
@@ -100,46 +100,12 @@ module.insertItemAfter(c, wc)
|
||||
|
||||
|
||||
# wxPoint typemap
|
||||
c.convertFromPyObject = """\
|
||||
// is it just a typecheck?
|
||||
if (!sipIsErr) {
|
||||
if (sipCanConvertToType(sipPy, sipType_wxPoint, SIP_NO_CONVERTORS))
|
||||
return 1;
|
||||
c.convertFromPyObject = tools.convertTwoIntegersTemplate('wxPoint')
|
||||
|
||||
if (PySequence_Check(sipPy) && PySequence_Size(sipPy) == 2) {
|
||||
int rval = 1;
|
||||
PyObject* o1 = PySequence_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_ITEM(sipPy, 1);
|
||||
if (!PyNumber_Check(o1) || !PyNumber_Check(o2))
|
||||
rval = 0;
|
||||
Py_DECREF(o1);
|
||||
Py_DECREF(o2);
|
||||
return rval;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// otherwise do the conversion
|
||||
if (PySequence_Check(sipPy)) {
|
||||
PyObject* o1 = PySequence_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_ITEM(sipPy, 1);
|
||||
*sipCppPtr = new wxPoint(PyInt_AsLong(o1), PyInt_AsLong(o2));
|
||||
Py_DECREF(o1);
|
||||
Py_DECREF(o2);
|
||||
return sipGetState(sipTransferObj);
|
||||
}
|
||||
*sipCppPtr = reinterpret_cast<wxPoint*>(sipConvertToType(
|
||||
sipPy, sipType_wxPoint, sipTransferObj, SIP_NO_CONVERTORS, 0, sipIsErr));
|
||||
return 0;
|
||||
"""
|
||||
|
||||
|
||||
# Helper to convert a Point to a tuple
|
||||
c.addCppMethod('SIP_PYOBJECT', 'Get', '()', """\
|
||||
sipRes = sipBuildResult(&sipIsErr, "(ii)", sipCpp->x, sipCpp->y);
|
||||
""", briefDoc="""\
|
||||
Get() -> (x,y)
|
||||
|
||||
Get() -> (x,y)\n
|
||||
Return the x and y properties as a tuple.""")
|
||||
|
||||
# Add sequence protocol methods and other goodies
|
||||
@@ -168,7 +134,7 @@ c.addProperty("width GetWidth SetWidth")
|
||||
c.addProperty("height GetHeight SetHeight")
|
||||
|
||||
# take care of the same issues as wxPoint
|
||||
etgtools.tweaker_tools.ignoreAllOperators(c)
|
||||
tools.ignoreAllOperators(c)
|
||||
for f in c.find('operator+=').all() + \
|
||||
c.find('operator-=').all() + \
|
||||
c.find('operator*=').all() + \
|
||||
@@ -186,12 +152,38 @@ wxSize operator/(const wxSize& s, int i);
|
||||
module.insertItemAfter(c, wc)
|
||||
|
||||
|
||||
# wxSize typemap
|
||||
c.convertFromPyObject = tools.convertTwoIntegersTemplate('wxSize')
|
||||
|
||||
c.addCppMethod('SIP_PYOBJECT', 'Get', '()', """\
|
||||
sipRes = sipBuildResult(&sipIsErr, "(ii)", sipCpp->GetWidth(), sipCpp->GetHeight());
|
||||
""", briefDoc="""\
|
||||
Get() -> (width, height)\n
|
||||
Return the width and height properties as a tuple.""")
|
||||
|
||||
# Add sequence protocol methods and other goodies
|
||||
c.addPyMethod('__str__', '(self)', 'return str(self.Get())')
|
||||
c.addPyMethod('__repr__', '(self)', 'return "wx.Size"+str(self.Get())')
|
||||
c.addPyMethod('__len__', '(self)', 'return len(self.Get())')
|
||||
c.addPyMethod('__nonzero__', '(self)', 'return self.Get() != (0,0)')
|
||||
c.addPyMethod('__reduce__', '(self)', 'return (Size, self.Get())')
|
||||
c.addPyMethod('__getitem__', '(self, idx)', 'return self.Get()[idx]')
|
||||
c.addPyMethod('__setitem__', '(self, idx, val)',
|
||||
"""\
|
||||
if idx == 0: self.width = val
|
||||
elif idx == 1: self.height = val
|
||||
else: raise IndexError
|
||||
""")
|
||||
c.addPyCode('Size.__safe_for_unpickling__ = True')
|
||||
|
||||
|
||||
|
||||
#---------------------------------------
|
||||
# wxRect tweaks
|
||||
c = module.find('wxRect')
|
||||
|
||||
# take care of the same issues as wxPoint
|
||||
etgtools.tweaker_tools.ignoreAllOperators(c)
|
||||
tools.ignoreAllOperators(c)
|
||||
for f in c.find('operator+=').all() + \
|
||||
c.find('operator*=').all():
|
||||
f.ignore(False)
|
||||
@@ -216,7 +208,7 @@ module.find('wxRect.Intersect').findOverload(') const').ignore()
|
||||
c = module.find('wxRealPoint')
|
||||
|
||||
# take care of the same issues as wxPoint
|
||||
etgtools.tweaker_tools.ignoreAllOperators(c)
|
||||
tools.ignoreAllOperators(c)
|
||||
for f in c.find('operator+=').all() + \
|
||||
c.find('operator-=').all():
|
||||
f.ignore(False)
|
||||
|
||||
@@ -30,9 +30,9 @@ etgtools.parseDoxyXML(module, ITEMS)
|
||||
# Tweak the parsed meta objects in the module object as needed for customizing
|
||||
# the generated code and docstrings.
|
||||
|
||||
import etgtools.tweaker_tools
|
||||
etgtools.tweaker_tools.ignoreAssignmentOperators(module)
|
||||
etgtools.tweaker_tools.removeWxPrefixes(module)
|
||||
import etgtools.tweaker_tools as tools
|
||||
tools.ignoreAssignmentOperators(module)
|
||||
tools.removeWxPrefixes(module)
|
||||
|
||||
|
||||
module.addHeaderCode('#include <wx/wx.h>')
|
||||
|
||||
@@ -31,9 +31,9 @@ etgtools.parseDoxyXML(module, ITEMS)
|
||||
# Tweak the parsed meta objects in the module object as needed for customizing
|
||||
# the generated code and docstrings.
|
||||
|
||||
import etgtools.tweaker_tools
|
||||
etgtools.tweaker_tools.ignoreAssignmentOperators(module)
|
||||
etgtools.tweaker_tools.removeWxPrefixes(module)
|
||||
import etgtools.tweaker_tools as tools
|
||||
tools.ignoreAssignmentOperators(module)
|
||||
tools.removeWxPrefixes(module)
|
||||
|
||||
|
||||
module.find('wxObject.operator delete').ignore()
|
||||
|
||||
@@ -27,9 +27,9 @@ etgtools.parseDoxyXML(module, ITEMS)
|
||||
# Tweak the parsed meta objects in the module object as needed for customizing
|
||||
# the generated code and docstrings.
|
||||
|
||||
import etgtools.tweaker_tools
|
||||
etgtools.tweaker_tools.ignoreAssignmentOperators(module)
|
||||
etgtools.tweaker_tools.removeWxPrefixes(module)
|
||||
import etgtools.tweaker_tools as tools
|
||||
tools.ignoreAssignmentOperators(module)
|
||||
tools.removeWxPrefixes(module)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -326,7 +326,7 @@ from %s import *
|
||||
stream.write(')')
|
||||
if prop.briefDoc:
|
||||
stream.write(' // %s' % prop.briefDoc)
|
||||
stream.write('\n')
|
||||
stream.write('\n\n')
|
||||
|
||||
|
||||
def generateMethod(self, method, stream, indent):
|
||||
|
||||
@@ -54,3 +54,39 @@ def createPyArgsStrings(node):
|
||||
items that can be used as part of the docstring.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def convertTwoIntegersTemplate(CLASS):
|
||||
return """\
|
||||
// is it just a typecheck?
|
||||
if (!sipIsErr) {{
|
||||
if (sipCanConvertToType(sipPy, sipType_{CLASS}, SIP_NO_CONVERTORS))
|
||||
return 1;
|
||||
|
||||
if (PySequence_Check(sipPy) && PySequence_Size(sipPy) == 2) {{
|
||||
int rval = 1;
|
||||
PyObject* o1 = PySequence_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_ITEM(sipPy, 1);
|
||||
if (!PyNumber_Check(o1) || !PyNumber_Check(o2))
|
||||
rval = 0;
|
||||
Py_DECREF(o1);
|
||||
Py_DECREF(o2);
|
||||
return rval;
|
||||
}}
|
||||
return 0;
|
||||
}}
|
||||
|
||||
// otherwise do the conversion
|
||||
if (PySequence_Check(sipPy)) {{
|
||||
PyObject* o1 = PySequence_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_ITEM(sipPy, 1);
|
||||
*sipCppPtr = new {CLASS}(PyInt_AsLong(o1), PyInt_AsLong(o2));
|
||||
Py_DECREF(o1);
|
||||
Py_DECREF(o2);
|
||||
return sipGetState(sipTransferObj);
|
||||
}}
|
||||
*sipCppPtr = reinterpret_cast<{CLASS}*>(sipConvertToType(
|
||||
sipPy, sipType_{CLASS}, sipTransferObj, SIP_NO_CONVERTORS, 0, sipIsErr));
|
||||
return 0;
|
||||
""".format(**locals())
|
||||
|
||||
|
||||
@@ -271,10 +271,105 @@ public:
|
||||
);
|
||||
|
||||
%Property(name=width, get=GetWidth, set=SetWidth)
|
||||
|
||||
%Property(name=height, get=GetHeight, set=SetHeight)
|
||||
|
||||
SIP_PYOBJECT Get();
|
||||
%MethodCode
|
||||
sipRes = sipBuildResult(&sipIsErr, "(ii)", sipCpp->GetWidth(), sipCpp->GetHeight());
|
||||
%End
|
||||
|
||||
%ConvertToTypeCode
|
||||
// is it just a typecheck?
|
||||
if (!sipIsErr) {
|
||||
if (sipCanConvertToType(sipPy, sipType_wxSize, SIP_NO_CONVERTORS))
|
||||
return 1;
|
||||
|
||||
if (PySequence_Check(sipPy) && PySequence_Size(sipPy) == 2) {
|
||||
int rval = 1;
|
||||
PyObject* o1 = PySequence_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_ITEM(sipPy, 1);
|
||||
if (!PyNumber_Check(o1) || !PyNumber_Check(o2))
|
||||
rval = 0;
|
||||
Py_DECREF(o1);
|
||||
Py_DECREF(o2);
|
||||
return rval;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// otherwise do the conversion
|
||||
if (PySequence_Check(sipPy)) {
|
||||
PyObject* o1 = PySequence_ITEM(sipPy, 0);
|
||||
PyObject* o2 = PySequence_ITEM(sipPy, 1);
|
||||
*sipCppPtr = new wxSize(PyInt_AsLong(o1), PyInt_AsLong(o2));
|
||||
Py_DECREF(o1);
|
||||
Py_DECREF(o2);
|
||||
return sipGetState(sipTransferObj);
|
||||
}
|
||||
*sipCppPtr = reinterpret_cast<wxSize*>(sipConvertToType(
|
||||
sipPy, sipType_wxSize, sipTransferObj, SIP_NO_CONVERTORS, 0, sipIsErr));
|
||||
return 0;
|
||||
%End
|
||||
}; // end of class wxSize
|
||||
|
||||
|
||||
%Extract pycode
|
||||
def _Size___str__(self):
|
||||
return str(self.Get())
|
||||
Size.__str__ = _Size___str__
|
||||
|
||||
%End
|
||||
|
||||
%Extract pycode
|
||||
def _Size___repr__(self):
|
||||
return "wx.Size"+str(self.Get())
|
||||
Size.__repr__ = _Size___repr__
|
||||
|
||||
%End
|
||||
|
||||
%Extract pycode
|
||||
def _Size___len__(self):
|
||||
return len(self.Get())
|
||||
Size.__len__ = _Size___len__
|
||||
|
||||
%End
|
||||
|
||||
%Extract pycode
|
||||
def _Size___nonzero__(self):
|
||||
return self.Get() != (0,0)
|
||||
Size.__nonzero__ = _Size___nonzero__
|
||||
|
||||
%End
|
||||
|
||||
%Extract pycode
|
||||
def _Size___reduce__(self):
|
||||
return (Size, self.Get())
|
||||
Size.__reduce__ = _Size___reduce__
|
||||
|
||||
%End
|
||||
|
||||
%Extract pycode
|
||||
def _Size___getitem__(self, idx):
|
||||
return self.Get()[idx]
|
||||
Size.__getitem__ = _Size___getitem__
|
||||
|
||||
%End
|
||||
|
||||
%Extract pycode
|
||||
def _Size___setitem__(self, idx, val):
|
||||
if idx == 0: self.width = val
|
||||
elif idx == 1: self.height = val
|
||||
else: raise IndexError
|
||||
Size.__setitem__ = _Size___setitem__
|
||||
|
||||
%End
|
||||
|
||||
%Extract pycode
|
||||
Size.__safe_for_unpickling__ = True
|
||||
|
||||
%End
|
||||
|
||||
bool operator==(const wxSize& s1, const wxSize& s2);
|
||||
bool operator!=(const wxSize& s1, const wxSize& s2);
|
||||
wxSize operator*(const wxSize& s, int i);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import unittest2
|
||||
import wx
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
class Point(unittest2.TestCase):
|
||||
|
||||
def test_default_ctor(self):
|
||||
@@ -80,8 +83,132 @@ class Point(unittest2.TestCase):
|
||||
with self.assertRaises(IndexError):
|
||||
p[2]
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class Size(unittest2.TestCase):
|
||||
|
||||
def test_default_ctor(self):
|
||||
s = wx.Size()
|
||||
self.assertTrue(s == (0,0))
|
||||
|
||||
def test_wh_ctor(self):
|
||||
s = wx.Size(100,200)
|
||||
|
||||
def test_copy_ctor(self):
|
||||
s1 = wx.Size(100,200)
|
||||
s2 = wx.Size(s1)
|
||||
self.assertTrue(s1 is not s2)
|
||||
self.assertTrue(s1 == s2)
|
||||
|
||||
def test_bogus_ctor(self):
|
||||
with self.assertRaises(TypeError):
|
||||
s = wx.Size("aa", "bb")
|
||||
|
||||
def test_DecBy(self):
|
||||
s = wx.Size(100,100)
|
||||
s.DecBy(wx.Point(5,5))
|
||||
self.assertTrue(s == (95,95))
|
||||
s.DecBy(wx.Size(5,5))
|
||||
self.assertTrue(s == (90,90))
|
||||
s.DecBy(5,5)
|
||||
self.assertTrue(s == (85,85))
|
||||
s.DecBy(5)
|
||||
self.assertTrue(s == (80,80))
|
||||
s.DecBy( (5,5) )
|
||||
self.assertTrue(s == (75,75))
|
||||
|
||||
|
||||
def test_IncBy(self):
|
||||
s = wx.Size(50,50)
|
||||
s.IncBy(wx.Point(5,5))
|
||||
self.assertTrue(s == (55,55))
|
||||
s.IncBy(wx.Size(5,5))
|
||||
self.assertTrue(s == (60,60))
|
||||
s.IncBy(5,5)
|
||||
self.assertTrue(s == (65,65))
|
||||
s.IncBy(5)
|
||||
self.assertTrue(s == (70,70))
|
||||
s.IncBy( (5,5) )
|
||||
self.assertTrue(s == (75,75))
|
||||
|
||||
def test_DecTo(self):
|
||||
s = wx.Size(5, 15)
|
||||
s.DecTo( (10,10) )
|
||||
self.assertTrue(s == (5,10))
|
||||
|
||||
def test_IncTo(self):
|
||||
s = wx.Size(5, 15)
|
||||
s.IncTo( (10,10) )
|
||||
self.assertTrue(s == (10,15))
|
||||
|
||||
def test_properties(self):
|
||||
s = wx.Size(23,34)
|
||||
self.assertTrue(s.width == 23 and s.height == 34)
|
||||
s.width += 1
|
||||
s.height += 1
|
||||
self.assertTrue(s == (24,35))
|
||||
|
||||
def test_operators(self):
|
||||
s1 = wx.Size(100,200)
|
||||
s2 = wx.Size(30,40)
|
||||
s1 += s2
|
||||
s1 -= s2
|
||||
s1 *= 5
|
||||
s1 /= 5
|
||||
s1 == s2
|
||||
s1 != s2
|
||||
s = s1 * 5
|
||||
s = 5 * s1
|
||||
s = s1 + s2
|
||||
s = s1 - s2
|
||||
s = s1 / 5
|
||||
|
||||
def test_GetSet(self):
|
||||
s = wx.Size(100,200)
|
||||
t = s.Get()
|
||||
self.assertTrue(type(t) == tuple)
|
||||
self.assertTrue(t == (100,200))
|
||||
s.Set(5,10)
|
||||
self.assertTrue(s.Get() == (5,10))
|
||||
|
||||
def test_SetDefaults(self):
|
||||
s = wx.Size(50, -1)
|
||||
s.SetDefaults( (25,25) )
|
||||
self.assertTrue(s == (50,25))
|
||||
|
||||
def test_FullySpecified(self):
|
||||
self.assertTrue(wx.Size(40,50).IsFullySpecified())
|
||||
self.assertTrue(not wx.Size(-1,50).IsFullySpecified())
|
||||
self.assertTrue(not wx.Size(40,-1).IsFullySpecified())
|
||||
|
||||
def test_magic(self):
|
||||
s = wx.Size(5,6)
|
||||
self.assertTrue(str(s) == "(5, 6)")
|
||||
self.assertTrue(repr(s) == "wx.Size(5, 6)")
|
||||
self.assertTrue(len(s) == 2)
|
||||
w, h = s
|
||||
self.assertTrue(5 == 5 and h == 6)
|
||||
s[0] += 1 # tests both getitem and setitem
|
||||
s[1] += 2
|
||||
self.assertTrue(s == (6,8))
|
||||
with self.assertRaises(IndexError):
|
||||
s[2]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest2.main()
|
||||
Reference in New Issue
Block a user