[Lxml-checkins] r32536 - in lxml/branch/lxml-1.1: . doc src/lxml

scoder at codespeak.net scoder at codespeak.net
Wed Sep 20 17:41:32 CEST 2006


Author: scoder
Date: Wed Sep 20 17:41:29 2006
New Revision: 32536

Modified:
   lxml/branch/lxml-1.1/CHANGES.txt
   lxml/branch/lxml-1.1/doc/mkhtml.py
   lxml/branch/lxml-1.1/doc/objectify.txt
   lxml/branch/lxml-1.1/src/lxml/objectify.pyx
Log:
merge from trunk: objectify fixes by Holger

Modified: lxml/branch/lxml-1.1/CHANGES.txt
==============================================================================
--- lxml/branch/lxml-1.1/CHANGES.txt	(original)
+++ lxml/branch/lxml-1.1/CHANGES.txt	Wed Sep 20 17:41:29 2006
@@ -17,6 +17,8 @@
 Bugs fixed
 ----------
 
+* lxml.objectify failed to support long data values (e.g., "123L")
+
 * Error messages from XSLT did not reach ``XSLT.error_log``
 
 * Factories objectify.Element() and objectify.DataElement() were missing

Modified: lxml/branch/lxml-1.1/doc/mkhtml.py
==============================================================================
--- lxml/branch/lxml-1.1/doc/mkhtml.py	(original)
+++ lxml/branch/lxml-1.1/doc/mkhtml.py	Wed Sep 20 17:41:29 2006
@@ -33,8 +33,8 @@
               os.path.join(dirname, 'index.html'))
 
 def rest2html(script, source_path, dest_path, stylesheet_url):
-    command = ('%s --stylesheet=%s --link-stylesheet %s > %s' %
-               (script, stylesheet_url, source_path, dest_path))
+    command = ('%s %s --stylesheet=%s --link-stylesheet %s > %s' %
+               (sys.executable, script, stylesheet_url, source_path, dest_path))
     os.system(command)
 
 if __name__ == '__main__':

Modified: lxml/branch/lxml-1.1/doc/objectify.txt
==============================================================================
--- lxml/branch/lxml-1.1/doc/objectify.txt	(original)
+++ lxml/branch/lxml-1.1/doc/objectify.txt	Wed Sep 20 17:41:29 2006
@@ -559,7 +559,7 @@
     ['test']
 
 If you need to run sequence operations on data types, you must ask the API for
-the *real* Python value.  The string value is always available throught the
+the *real* Python value.  The string value is always available through the
 normal ElementTree ``.text`` attribute.  Additionally, all data classes
 provide a ``.pyval`` attribute that returns the value as plain Python type::
 
@@ -591,13 +591,48 @@
     >>> print root.a
     25
 
+In other words, objectify data elements behave like immutable Python types.
+
 
 How data types are matched
 --------------------------
 
-Objectify determines data types by trial and error, unless it finds an
-attribute named ``lxml.objectify.PYTYPE_ATTRIBUTE``, which must contain any of
-the following string values: int, long, float, str, unicode, none::
+Objectify uses two different types of Elements.  Structural Elements (or tree
+Elements) represent the object tree structure.  Data Elements represent the
+data containers at the leafs.  You can explicitly create tree Elements with
+the ``objectify.Element()`` factory and data Elements with the
+``objectify.DataElement()`` factory.
+
+When Element objects are created, lxml.objectify must determine which
+implementation class to use for them.  This is relatively easy for tree
+Elements and less so for data Elements.  The algorithm is as follows:
+
+1. If an element has children, use the default tree class.
+
+2. If an element is defined as xsi:nil, use the NoneElement class.
+
+3. If a "Python type hint" attribute is given, use this to determine the element
+   class, see below.
+ 
+4. If an XML Schema xsi:type hint is given, use this to determine the element
+   class, see below.
+
+5. Try to determine the element class from the text content type by trial and
+   error.
+
+6. If the element is a root node then use the default tree class.
+
+7. Otherwise, use the default class for empty data classes.
+
+You can change the default classes for tree Elements and empty data Elements
+at setup time.  The ``ObjectifyElementClassLookup()`` call accepts two keyword
+arguments, ``tree_class`` and ``empty_data_class``, that determine the Element
+classes used in these cases.  By default, ``tree_class`` is a class called
+``ObjectifiedElement`` and ``empty_data_class`` is a ``StringElement``.
+
+The "type hint" mechanism deploys an XML attribute defined as
+``lxml.objectify.PYTYPE_ATTRIBUTE``.  It may contain any of the following
+string values: int, long, float, str, unicode, none::
 
     >>> print objectify.PYTYPE_ATTRIBUTE
     {http://codespeak.net/lxml/objectify/pytype}pytype
@@ -658,9 +693,9 @@
         s = '5' [StringElement]
           * xsi:type = 'string'
 
-For convenience, there is a special factory ``DataElement()`` that supports
-creating an Element with a Python value in one step.  You can pass the
-required Python type name or the XSI type name::
+For convenience, the ``DataElement()`` factory creates an Element with a
+Python value in one step.  You can pass the required Python type name or the
+XSI type name::
 
     >>> root = objectify.Element("root")
     >>> root.x = objectify.DataElement(5, _pytype="long")
@@ -683,16 +718,38 @@
           * py:pytype = 'int'
           * xsi:type = 'integer'
 
+There is a side effect of the type lookup.  If you assign a string value using
+attribute assignment and that string value turns out to be valid for any of
+the type checks, you will end up with the resolved type instead of a
+StringElement::
+
+    >>> root = objectify.Element("root")
+    >>> root.s = "5"
+    >>> print objectify.dump(root)
+    root = None [ObjectifiedElement]
+        s = 5 [IntElement]
+
+You can use the ``DataElement()`` factory to avoid this behaviour and thus
+provide the type of a data element by hand::
+
+    >>> root = objectify.Element("root")
+    >>> root.s = objectify.DataElement(5,  _pytype="str")
+    >>> print objectify.dump(root)
+    root = None [ObjectifiedElement]
+        s = '5' [StringElement]
+          * py:pytype = 'str'
 
+ 
 Defining additional data classes
 --------------------------------
 
-Data classes can either inherit from ``ObjectifiedDataElement`` directly or
-from one of the specialised classes like ``NumberElement`` or ``BoolElement``.
-The numeric types require an initial call to the NumberElement method
-``self._setValueParser(function)`` to set their type conversion funtion
-(string -> numeric Python type).  This call should be placed into the element
-``_init()`` method.
+You can plug additional data classes into objectify that will be used in
+exactly the same way as the predefined types.  Data classes can either inherit
+from ``ObjectifiedDataElement`` directly or from one of the specialised
+classes like ``NumberElement`` or ``BoolElement``.  The numeric types require
+an initial call to the NumberElement method ``self._setValueParser(function)``
+to set their type conversion function (string -> numeric Python type).  This
+call should be placed into the element ``_init()`` method.
 
 The registration of data classes uses the ``PyType`` class::
 
@@ -706,6 +763,16 @@
 
     >>> xmas_type = objectify.PyType('date', checkChristmasDate, ChristmasDate)
 
+The PyType constructor takes a string type name, an (optional) callable type 
+check and the custom data class.  If a type check is provided it must accept a 
+string as argument and raise ValueError or TypeError if it cannot handle the
+string value.
+
+PyTypes are used if an element carries a ``py:pytype`` attribute denoting its
+data type or, in absence of such an attribute, if the given type check callable
+does not raise a ValueError/TypeError exception when applied to the element
+text. 
+
 If you want, you can also register this type under an XML Schema type name::
 
     >>> xmas_type.xmlSchemaTypes = ("date",)
@@ -805,6 +872,10 @@
 Such a different Element API obviously implies some side effects to the normal
 behaviour of the rest of the API.
 
+* len(<element>) returns the sibling count, not the number of children of
+  <element>. You can retrieve the number of children with the
+  ``countchildren()`` method. 
+
 * Iteration over elements does not yield the children, but the siblings.  You
   can access all children with the ``iterchildren()`` method on elements or
   retrieve a list by calling the ``getchildren()`` method.

Modified: lxml/branch/lxml-1.1/src/lxml/objectify.pyx
==============================================================================
--- lxml/branch/lxml-1.1/src/lxml/objectify.pyx	(original)
+++ lxml/branch/lxml-1.1/src/lxml/objectify.pyx	Wed Sep 20 17:41:29 2006
@@ -845,7 +845,7 @@
                              "int", "unsignedInt", "short", "unsignedShort")
     pytype.register()
 
-    pytype = PyType('long', None, LongElement)
+    pytype = PyType('long', long, LongElement)
     pytype.xmlSchemaTypes = ("long", "unsignedLong")
     pytype.register()
 


More information about the lxml-checkins mailing list