[Lxml-checkins] r53639 - in lxml/trunk: . src/lxml src/lxml/tests
scoder at codespeak.net
scoder at codespeak.net
Thu Apr 10 08:00:39 CEST 2008
Author: scoder
Date: Thu Apr 10 08:00:37 2008
New Revision: 53639
Modified:
lxml/trunk/ (props changed)
lxml/trunk/src/lxml/lxml.objectify.pyx
lxml/trunk/src/lxml/tests/test_objectify.py
Log:
r3916 at delle: sbehnel | 2008-04-08 09:45:15 +0200
objectify: let BoolElement inherit from IntElement (as in Python), lots of cleanup in 'special methods'
Modified: lxml/trunk/src/lxml/lxml.objectify.pyx
==============================================================================
--- lxml/trunk/src/lxml/lxml.objectify.pyx (original)
+++ lxml/trunk/src/lxml/lxml.objectify.pyx Thu Apr 10 08:00:37 2008
@@ -618,41 +618,44 @@
cetree.setNodeText(self._c_node, s)
cdef class NumberElement(ObjectifiedDataElement):
- cdef object _type
+ cdef object _parse_value
def _setValueParser(self, function):
- "Set the function that parses the Python value from a string."
- self._type = function
+ """Set the function that parses the Python value from a string.
- cdef _value(self):
- return self._type(textOf(self._c_node))
+ Do not use this unless you know what you are doing.
+ """
+ self._parse_value = function
property pyval:
def __get__(self):
- return self._value()
+ return _parseNumber(self)
def __int__(self):
- return int(textOf(self._c_node))
+ return int(_parseNumber(self))
def __long__(self):
- return long(textOf(self._c_node))
+ return long(_parseNumber(self))
def __float__(self):
- return float(textOf(self._c_node))
+ return float(_parseNumber(self))
+
+ def __complex__(self):
+ return complex(_parseNumber(self))
def __str__(self):
- return str(self._type(textOf(self._c_node)))
+ return str(_parseNumber(self))
def __repr__(self):
- return repr(self._type(textOf(self._c_node)))
+ return repr(_parseNumber(self))
+
+ def __oct__(self):
+ return oct(_parseNumber(self))
-# def __oct__(self):
-# def __hex__(self):
+ def __hex__(self):
+ return hex(_parseNumber(self))
def __richcmp__(self, other, int op):
- if hasattr(other, 'pyval'):
- other = other.pyval
- return python.PyObject_RichCompare(
- _numericValueOf(self), other, op)
+ return _richcmpPyvals(self, other, op)
def __add__(self, other):
return _numericValueOf(self) + _numericValueOf(other)
@@ -710,15 +713,15 @@
cdef class IntElement(NumberElement):
def _init(self):
- self._type = int
+ self._parse_value = int
cdef class LongElement(NumberElement):
def _init(self):
- self._type = long
+ self._parse_value = long
cdef class FloatElement(NumberElement):
def _init(self):
- self._type = float
+ self._parse_value = float
cdef class StringElement(ObjectifiedDataElement):
"""String data class.
@@ -748,10 +751,7 @@
return len(text) > 0
def __richcmp__(self, other, int op):
- if hasattr(other, 'pyval'):
- other = other.pyval
- return python.PyObject_RichCompare(
- _strValueOf(self), other, op)
+ return _richcmpPyvals(self, other, op)
def __add__(self, other):
text = _strValueOf(self)
@@ -807,61 +807,64 @@
def __get__(self):
return None
-cdef class BoolElement(ObjectifiedDataElement):
+cdef class BoolElement(IntElement):
"""Boolean type base on string values: 'true' or 'false'.
+
+ Note that this inherits from IntElement to mimic the behaviour of
+ Python's bool type.
"""
- cdef int _boolval(self) except -1:
- cdef char* c_str
- text = textOf(self._c_node)
- if text is None:
- return 0
- c_str = _cstr(text)
- if c_str[0] == c'0' or c_str[0] == c'f' or c_str[0] == c'F':
- if c_str[1] == c'\0' or text == "false" or text.lower() == "false":
- # '0' or 'f' or 'false'
- return 0
- elif c_str[0] == c'1' or c_str[0] == c't' or c_str[0] == c'T':
- if c_str[1] == c'\0' or text == "true" or text.lower() == "true":
- # '1' or 't' or 'true'
- return 1
- raise ValueError("Invalid boolean value: '%s'" % text)
+ def _init(self):
+ self._parse_value = __parseBool
def __nonzero__(self):
- if self._boolval():
- return True
- else:
- return False
+ return __parseBool(textOf(self._c_node))
def __richcmp__(self, other, int op):
- if hasattr(other, 'pyval'):
- other = other.pyval
- if hasattr(self, 'pyval'):
- self_val = self.pyval
- else:
- self_val = bool(self)
- return python.PyObject_RichCompare(self_val, other, op)
+ return _richcmpPyvals(self, other, op)
def __str__(self):
- if self._boolval():
- return "True"
- else:
- return "False"
+ return str(__parseBool(textOf(self._c_node)))
def __repr__(self):
- if self._boolval():
- return "True"
- else:
- return "False"
+ return repr(__parseBool(textOf(self._c_node)))
property pyval:
def __get__(self):
- return self.__nonzero__()
+ return __parseBool(textOf(self._c_node))
def __checkBool(s):
- if s != 'true' and s != 'false' and s != '1' and s != '0':
+ cdef int value = -1
+ if s is not None:
+ value = __parseBoolAsInt(s)
+ if value == -1:
raise ValueError
-cdef object _strValueOf(obj):
+cpdef __parseBool(s):
+ cdef int value
+ if s is None:
+ return False
+ value = __parseBoolAsInt(s)
+ if value == -1:
+ raise ValueError("Invalid boolean value: '%s'" % s)
+ return <bint>value
+
+cdef inline int __parseBoolAsInt(text):
+ cdef char* c_str
+ c_str = _cstr(text)
+ if c_str[0] == c'0' or c_str[0] == c'f' or c_str[0] == c'F':
+ if c_str[1] == c'\0' or text == "false" or text.lower() == "false":
+ # '0' or 'f' or 'false'
+ return 0
+ elif c_str[0] == c'1' or c_str[0] == c't' or c_str[0] == c'T':
+ if c_str[1] == c'\0' or text == "true" or text.lower() == "true":
+ # '1' or 't' or 'true'
+ return 1
+ return -1
+
+cdef inline _parseNumber(NumberElement element):
+ return element._parse_value(textOf(element._c_node))
+
+cdef inline object _strValueOf(obj):
if python._isString(obj):
return obj
if isinstance(obj, _Element):
@@ -870,15 +873,20 @@
return ''
return str(obj)
-cdef object _numericValueOf(obj):
+cdef inline object _numericValueOf(obj):
if isinstance(obj, NumberElement):
- return (<NumberElement>obj)._type(
- textOf((<NumberElement>obj)._c_node))
+ return _parseNumber(<NumberElement>obj)
elif hasattr(obj, 'pyval'):
# not always numeric, but Python will raise the right exception
return obj.pyval
return obj
+cdef inline _richcmpPyvals(left, right, int op):
+ left = getattr3(left, 'pyval', left)
+ right = getattr3(right, 'pyval', right)
+ return python.PyObject_RichCompare(left, right, op)
+
+
################################################################################
# Python type registry
Modified: lxml/trunk/src/lxml/tests/test_objectify.py
==============================================================================
--- lxml/trunk/src/lxml/tests/test_objectify.py (original)
+++ lxml/trunk/src/lxml/tests/test_objectify.py Thu Apr 10 08:00:37 2008
@@ -737,10 +737,20 @@
root = Element("{objectified}root")
root.bool = True
self.assertEquals(root.bool, True)
+ self.assertEquals(root.bool + root.bool, True + True)
+ self.assertEquals(True + root.bool, True + root.bool)
+ self.assertEquals(root.bool * root.bool, True * True)
+ self.assertEquals(int(root.bool), int(True))
+ self.assertEquals(complex(root.bool), complex(True))
self.assert_(isinstance(root.bool, objectify.BoolElement))
root.bool = False
self.assertEquals(root.bool, False)
+ self.assertEquals(root.bool + root.bool, False + False)
+ self.assertEquals(False + root.bool, False + root.bool)
+ self.assertEquals(root.bool * root.bool, False * False)
+ self.assertEquals(int(root.bool), int(False))
+ self.assertEquals(complex(root.bool), complex(False))
self.assert_(isinstance(root.bool, objectify.BoolElement))
def test_data_element_bool(self):
More information about the lxml-checkins
mailing list