Index: Lib/ctypes/__init__.py =================================================================== --- Lib/ctypes/__init__.py (revision 67045) +++ Lib/ctypes/__init__.py (working copy) @@ -15,6 +15,7 @@ from _ctypes import ArgumentError from struct import calcsize as _calcsize +from mixins import _NumberMixin if __version__ != _ctypes_version: raise Exception("Version number mismatch", __version__, _ctypes_version) @@ -165,19 +166,19 @@ return "%s()" % type(self).__name__ _check_size(py_object, "P") -class c_short(_SimpleCData): +class c_short(_SimpleCData, _NumberMixin): _type_ = "h" _check_size(c_short) -class c_ushort(_SimpleCData): +class c_ushort(_SimpleCData, _NumberMixin): _type_ = "H" _check_size(c_ushort) -class c_long(_SimpleCData): +class c_long(_SimpleCData, _NumberMixin): _type_ = "l" _check_size(c_long) -class c_ulong(_SimpleCData): +class c_ulong(_SimpleCData, _NumberMixin): _type_ = "L" _check_size(c_ulong) @@ -186,23 +187,23 @@ c_int = c_long c_uint = c_ulong else: - class c_int(_SimpleCData): + class c_int(_SimpleCData, _NumberMixin): _type_ = "i" _check_size(c_int) - class c_uint(_SimpleCData): + class c_uint(_SimpleCData, _NumberMixin): _type_ = "I" _check_size(c_uint) -class c_float(_SimpleCData): +class c_float(_SimpleCData, _NumberMixin): _type_ = "f" _check_size(c_float) -class c_double(_SimpleCData): +class c_double(_SimpleCData, _NumberMixin): _type_ = "d" _check_size(c_double) -class c_longdouble(_SimpleCData): +class c_longdouble(_SimpleCData, _NumberMixin): _type_ = "g" if sizeof(c_longdouble) == sizeof(c_double): c_longdouble = c_double @@ -212,25 +213,25 @@ c_longlong = c_long c_ulonglong = c_ulong else: - class c_longlong(_SimpleCData): + class c_longlong(_SimpleCData, _NumberMixin): _type_ = "q" _check_size(c_longlong) - class c_ulonglong(_SimpleCData): + class c_ulonglong(_SimpleCData, _NumberMixin): _type_ = "Q" ## def from_param(cls, val): ## return ('d', float(val), val) ## from_param = classmethod(from_param) _check_size(c_ulonglong) -class c_ubyte(_SimpleCData): +class c_ubyte(_SimpleCData, _NumberMixin): _type_ = "B" c_ubyte.__ctype_le__ = c_ubyte.__ctype_be__ = c_ubyte # backward compatibility: ##c_uchar = c_ubyte _check_size(c_ubyte) -class c_byte(_SimpleCData): +class c_byte(_SimpleCData, _NumberMixin): _type_ = "b" c_byte.__ctype_le__ = c_byte.__ctype_be__ = c_byte _check_size(c_byte) @@ -391,7 +392,7 @@ # XXX Hm, what about HRESULT as normal parameter? # Mustn't it derive from c_long then? from _ctypes import _check_HRESULT, _SimpleCData - class HRESULT(_SimpleCData): + class HRESULT(_SimpleCData, _NumberMixin): _type_ = "l" # _check_retval_ is called with the function's result when it # is used as restype. It checks for the FAILED bit, and Index: Lib/ctypes/mixins.py =================================================================== --- Lib/ctypes/mixins.py (revision 0) +++ Lib/ctypes/mixins.py (revision 0) @@ -0,0 +1,128 @@ +class _NumberMixin(object): + """A mixin class that provides numeric operations for ctypes int + and float types""" + + ################################ + # oct, hex + def __hex__(self): + return hex(self.value) + + def __oct__(self): + return oct(self.value) + + ################################ + # neg, pos, abs, invert + def __neg__(self): + return type(self)(-self.value) + + def __pos__(self): + return self + + def __abs__(self): + return type(self)(abs(self.value)) + + def __invert__(self): + return type(self)(~self.value) + + ################################ + # coerce (do we need that?) + + ################################ + # int, long, float, complex, index + def __int__(self): + return self.value + __index__ = __long__ = __int__ + + def __float__(self): + return float(self.value) + + def __complex__(self): + return complex(self.value) + + ################################ + # add, sub, mul, div + # radd, rsub, rmul, rdiv + def __add__(self, other): + try: + return type(self)(self.value + type(self)(other).value) + except TypeError: + return NotImplemented + __radd__ = __add__ + + def __sub__(self, other): + try: + return type(self)(self.value - type(self)(other).value) + except TypeError: + return NotImplemented + + def __rsub__(self, other): + try: + return type(self)(type(self)(other).value - self.value) + except TypeError: + return NotImplemented + + def __mul__(self, other): + try: + return type(self)(self.value * type(self)(other).value) + except TypeError: + return NotImplemented + __rmul__ = __mul__ + + def __div__(self, other): + try: + return type(self)(self.value / type(self)(other).value) + except TypeError: + return NotImplemented + + def __rdiv__(self, other): + try: + return type(self)(type(self)(other).value / self.value) + except TypeError: + return NotImplemented + + ################################ + # iadd, isub, imul, idiv + def __iadd__(self, other): + try: + self.value += type(self)(other).value + except TypeError: + return NotImplemented + return self + + def __isub__(self, other): + try: + self.value -= type(self)(other).value + except TypeError: + return NotImplemented + return self + + def __imul__(self, other): + try: + self.value *= type(self)(other).value + except TypeError: + return NotImplemented + return self + + def __idiv__(self, other): + try: + self.value /= type(self)(other).value + except TypeError: + return NotImplemented + return self + + ################################ + # lshift, rshift, rlshift, rrshift + # mod, divmod, pow, + # rmod, rdivmod, rpow + # rlshift, rrshift + # and, xor, or, + # rand, rxor, ror + + + ################################ + # floordiv, truediv + # rfloordiv, rtruediv + + # itruediv, ifloordiv, imod, ipow, + # ilshift, irshift, iand, ixor, ior + Property changes on: Lib\ctypes\mixins.py ___________________________________________________________________ Name: svn:eol-style + native Index: Lib/ctypes/test/test_numbers.py =================================================================== --- Lib/ctypes/test/test_numbers.py (revision 67045) +++ Lib/ctypes/test/test_numbers.py (working copy) @@ -211,10 +211,7 @@ # self.failUnlessEqual(type(v) is t) def test_init(self): - # c_int() can be initialized from Python's int, and c_int. - # Not from c_long or so, which seems strange, abd should - # probably be changed: - self.assertRaises(TypeError, c_int, c_long(42)) + c_int(c_long(42)) ## def test_perf(self): ## check_perf() Index: Modules/_ctypes/_ctypes.c =================================================================== --- Modules/_ctypes/_ctypes.c (revision 67045) +++ Modules/_ctypes/_ctypes.c (working copy) @@ -4717,30 +4717,20 @@ return Simple_get_value((CDataObject *)self); } +static PyObject * +Simple_nonzero(CDataObject *self, PyObject *arg) +{ + if (memcmp(self->b_ptr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", self->b_size)) + Py_RETURN_FALSE; + Py_RETURN_TRUE; +} + static PyMethodDef Simple_methods[] = { { "__ctypes_from_outparam__", Simple_from_outparm, METH_NOARGS, }, + { "__nonzero__", Simple_nonzero, METH_NOARGS, }, { NULL, NULL }, }; -static int Simple_nonzero(CDataObject *self) -{ - return memcmp(self->b_ptr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", self->b_size); -} - -static PyNumberMethods Simple_as_number = { - 0, /* nb_add */ - 0, /* nb_subtract */ - 0, /* nb_multiply */ - 0, /* nb_divide */ - 0, /* nb_remainder */ - 0, /* nb_divmod */ - 0, /* nb_power */ - 0, /* nb_negative */ - 0, /* nb_positive */ - 0, /* nb_absolute */ - (inquiry)Simple_nonzero, /* nb_nonzero */ -}; - /* "%s(%s)" % (self.__class__.__name__, self.value) */ static PyObject * Simple_repr(CDataObject *self) @@ -4791,7 +4781,7 @@ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)&Simple_repr, /* tp_repr */ - &Simple_as_number, /* tp_as_number */ + 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */