[Lxml-checkins] r44706 - in lxml/branch/html: . doc src/lxml src/lxml/tests

ianb at codespeak.net ianb at codespeak.net
Tue Jul 3 19:01:34 CEST 2007


Author: ianb
Date: Tue Jul  3 19:01:33 2007
New Revision: 44706

Modified:
   lxml/branch/html/CHANGES.txt
   lxml/branch/html/doc/main.txt
   lxml/branch/html/doc/objectify.txt
   lxml/branch/html/doc/tutorial.txt
   lxml/branch/html/setup.py
   lxml/branch/html/src/lxml/etree.pyx
   lxml/branch/html/src/lxml/objectify.pyx
   lxml/branch/html/src/lxml/proxy.pxi
   lxml/branch/html/src/lxml/pyclasslookup.pyx
   lxml/branch/html/src/lxml/python.pxd
   lxml/branch/html/src/lxml/tests/test_classlookup.py
   lxml/branch/html/src/lxml/tests/test_dtd.py
   lxml/branch/html/src/lxml/tests/test_elementtree.py
   lxml/branch/html/src/lxml/tests/test_errors.py
   lxml/branch/html/src/lxml/tests/test_etree.py
   lxml/branch/html/src/lxml/tests/test_htmlparser.py
   lxml/branch/html/src/lxml/tests/test_io.py
   lxml/branch/html/src/lxml/tests/test_nsclasses.py
   lxml/branch/html/src/lxml/tests/test_objectify.py
   lxml/branch/html/src/lxml/tests/test_pyclasslookup.py
   lxml/branch/html/src/lxml/tests/test_relaxng.py
   lxml/branch/html/src/lxml/tests/test_sax.py
   lxml/branch/html/src/lxml/tests/test_xmlschema.py
   lxml/branch/html/src/lxml/tests/test_xpathevaluator.py
   lxml/branch/html/src/lxml/tests/test_xslt.py
   lxml/branch/html/src/lxml/xpath.pxi
Log:
svn merge -r44624:HEAD http://codespeak.net/svn/lxml/trunk

Modified: lxml/branch/html/CHANGES.txt
==============================================================================
--- lxml/branch/html/CHANGES.txt	(original)
+++ lxml/branch/html/CHANGES.txt	Tue Jul  3 19:01:33 2007
@@ -8,8 +8,6 @@
 Features added
 --------------
 
-* E-factory support for lxml.objectify (``objectify.E``)
-
 * Entity support through an ``Entity`` factory and element classes. XML
   parsers now have a ``resolve_entities`` keyword argument that can be set to
   False to keep entities in the document.
@@ -50,6 +48,29 @@
 * major refactoring in XPath/XSLT extension function code
 
 
+1.3.1 (2007-07-02)
+==================
+
+Features added
+--------------
+
+* objectify.DataElement now supports setting values from existing data
+  elements (not just plain Python types) and reuses defined namespaces etc.
+
+* E-factory support for lxml.objectify (``objectify.E``)
+
+Bugs fixed
+----------
+
+* Better way to prevent crashes in Element proxy cleanup code
+
+* objectify.DataElement didn't set up None value correctly
+
+* objectify.DataElement didn't check the value against the provided type hints
+
+* Reference-counting bug in ``Element.attrib.pop()``
+
+
 1.3 (2007-06-24)
 ================
 

Modified: lxml/branch/html/doc/main.txt
==============================================================================
--- lxml/branch/html/doc/main.txt	(original)
+++ lxml/branch/html/doc/main.txt	Tue Jul  3 19:01:33 2007
@@ -129,7 +129,7 @@
 .. _`lxml at the Python cheeseshop`: http://cheeseshop.python.org/pypi/lxml/
 .. _`this key`: pubkey.asc
 
-The latest version is `lxml 1.3`_, released 2007-06-24 (`changes for 1.3`_).
+The latest version is `lxml 1.3.1`_, released 2007-07-02 (`changes for 1.3.1`_).
 `Older versions`_ are listed below.
 
 .. _`Older versions`: #old-versions
@@ -179,6 +179,8 @@
 Old Versions
 ------------
 
+* `lxml 1.3`_, released 2007-06-24 (`changes for 1.3`_)
+
 * `lxml 1.2.1`_, released 2007-02-27 (`changes for 1.2.1`_)
 
 * `lxml 1.2`_, released 2007-02-20 (`changes for 1.2`_)
@@ -215,6 +217,7 @@
 
 * `lxml 0.5`_,   released 2005-04-08
 
+.. _`lxml 1.3.1`: lxml-1.3.1.tgz
 .. _`lxml 1.3`: lxml-1.3.tgz
 .. _`lxml 1.2.1`: lxml-1.2.1.tgz
 .. _`lxml 1.2`: lxml-1.2.tgz
@@ -235,7 +238,8 @@
 .. _`lxml 0.5.1`: lxml-0.5.1.tgz
 .. _`lxml 0.5`: lxml-0.5.tgz
 
-.. _`CHANGES for 1.3`: changes-1.3.html
+.. _`changes for 1.3.1`: changes-1.3.1.html
+.. _`changes for 1.3`: changes-1.3.html
 .. _`changes for 1.2.1`: changes-1.2.1.html
 .. _`changes for 1.2`: changes-1.2.html
 .. _`changes for 1.1.2`: changes-1.1.2.html

Modified: lxml/branch/html/doc/objectify.txt
==============================================================================
--- lxml/branch/html/doc/objectify.txt	(original)
+++ lxml/branch/html/doc/objectify.txt	Tue Jul  3 19:01:33 2007
@@ -287,7 +287,24 @@
       <c>true</c>
       <d tell="me">how</d>
     </root>
-    
+
+This allows you to write up a specific language in tags::
+
+    >>> ROOT = objectify.E.root
+    >>> TITLE = objectify.E.title
+    >>> TYPE = objectify.E.type
+
+    >>> root = ROOT(
+    ...   TITLE("The title"),
+    ...   TYPE(5)
+    ... )
+
+    >>> print etree.tostring(root, pretty_print=True)
+    <root>
+      <title>The title</title>
+      <type>5</type>
+    </root>
+
 
 Namespace handling
 ------------------

Modified: lxml/branch/html/doc/tutorial.txt
==============================================================================
--- lxml/branch/html/doc/tutorial.txt	(original)
+++ lxml/branch/html/doc/tutorial.txt	Tue Jul  3 19:01:33 2007
@@ -426,7 +426,7 @@
     ...     E.body(
     ...       E.h1("Hello!", CLASS("title")),
     ...       E.p("This is a paragraph with ", E.b("bold"), " text in it!"),
-    ...       E.p("This is another paragraph, with a ",
+    ...       E.p("This is another paragraph, with a", "\n      ",
     ...         E.a("link", href="http://www.python.org"), "."),
     ...       E.p("Here are some reservered characters: <spam&egg>."),
     ...       etree.XML("<p>And finally an embedded XHTML fragment.</p>"),
@@ -442,7 +442,8 @@
       <body>
         <h1 class="title">Hello!</h1>
         <p>This is a paragraph with <b>bold</b> text in it!</p>
-        <p>This is another paragraph, with a <a href="http://www.python.org">link</a>.</p>
+        <p>This is another paragraph, with a
+          <a href="http://www.python.org">link</a>.</p>
         <p>Here are some reservered characters: &lt;spam&amp;egg&gt;.</p>
         <p>And finally an embedded XHTML fragment.</p>
       </body>

Modified: lxml/branch/html/setup.py
==============================================================================
--- lxml/branch/html/setup.py	(original)
+++ lxml/branch/html/setup.py	Tue Jul  3 19:01:33 2007
@@ -1,13 +1,12 @@
 import sys, os
 
 try:
+    import pkg_resources
     try:
-        import pkg_resources
         pkg_resources.require("setuptools>=0.6c5")
     except pkg_resources.VersionConflict, e:
         from ez_setup import use_setuptools
         use_setuptools(version="0.6c5")
-    raise ImportError
     from setuptools import setup
 except ImportError:
     # not setuptools installed

Modified: lxml/branch/html/src/lxml/etree.pyx
==============================================================================
--- lxml/branch/html/src/lxml/etree.pyx	(original)
+++ lxml/branch/html/src/lxml/etree.pyx	Tue Jul  3 19:01:33 2007
@@ -131,12 +131,19 @@
         try:
             item = int(item)
         except ValueError:
-            if item == 'dev':
-                item = -3
-            elif item == 'alpha':
-                item = -2
-            elif item == 'beta':
-                item = -1
+            if item.startswith('dev'):
+                count = item[3:]
+                item = -300
+            elif item.startswith('alpha'):
+                count = item[5:]
+                item = -200
+            elif item.startswith('beta'):
+                count = item[4:]
+                item = -100
+            else:
+                count = 0
+            if count:
+                item = item + int(count)
         version_list.append(item)
     return tuple(version_list)
 
@@ -739,15 +746,16 @@
             cdef xmlNs* c_ns
             nsmap = {}
             c_node = self._c_node
-            while c_node is not NULL and _isElement(c_node):
+            while c_node is not NULL and c_node.type == tree.XML_ELEMENT_NODE:
                 c_ns = c_node.nsDef
                 while c_ns is not NULL:
                     if c_ns.prefix is NULL:
                         prefix = None
                     else:
                         prefix = funicode(c_ns.prefix)
-                    if prefix not in nsmap:
-                        nsmap[prefix] = funicode(c_ns.href)
+                    if not python.PyDict_Contains(nsmap, prefix):
+                        python.PyDict_SetItem(
+                            nsmap, prefix, funicode(c_ns.href))
                     c_ns = c_ns.next
                 c_node = c_node.parent
             return nsmap

Modified: lxml/branch/html/src/lxml/objectify.pyx
==============================================================================
--- lxml/branch/html/src/lxml/objectify.pyx	(original)
+++ lxml/branch/html/src/lxml/objectify.pyx	Tue Jul  3 19:01:33 2007
@@ -13,6 +13,8 @@
 # initialize C-API of lxml.etree
 import_etree(etree)
 
+__version__ = etree.__version__
+
 cdef object SubElement
 SubElement = etree.SubElement
 
@@ -1918,10 +1920,34 @@
     cdef python.PyObject* dict_result
     if nsmap is None:
         nsmap = _DEFAULT_NSMAP
-    if attrib is not None:
+    if attrib is not None and attrib:
         if python.PyDict_Size(_attributes):
+            attrib = dict(attrib)
             attrib.update(_attributes)
         _attributes = attrib
+    if isinstance(_value, ObjectifiedDataElement):
+        # reuse existing nsmap unless redefined in nsmap parameter
+        temp = _value.nsmap
+        if temp is not None and temp:
+            temp = dict(_value.nsmap)
+            temp.update(nsmap)
+            nsmap = temp
+        # reuse existing attributes unless redefined in attrib/_attributes
+        temp = _value.attrib
+        if temp is not None and temp:
+            temp = dict(_value.attrib)
+            temp.update(_attributes)
+            _attributes = temp
+        # reuse existing xsi:type or py:pytype attributes, unless provided as
+        # arguments
+        if _xsi is None and _pytype is None:
+            dict_result = python.PyDict_GetItem(_attributes,
+                                                XML_SCHEMA_INSTANCE_TYPE_ATTR)
+            if dict_result is not NULL:
+                _xsi = <object>dict_result
+            dict_result = python.PyDict_GetItem(_attributes, PYTYPE_ATTRIBUTE)
+            if dict_result is not NULL:
+                _pytype = <object>dict_result
     if _xsi is not None:
         if ':' in _xsi:
             prefix, name = _xsi.split(':', 1)
@@ -1956,23 +1982,34 @@
             strval = "true"
         else:
             strval = "false"
+    elif _value is None:
+        strval = None
     else:
         strval = str(_value)
 
     if _pytype is None:
-        for type_check, pytype in _TYPE_CHECKS:
-            try:
-                type_check(strval)
-                _pytype = (<PyType>pytype).name
-                break
-            except IGNORABLE_ERRORS:
-                pass
+        if strval is not None:
+            for type_check, pytype in _TYPE_CHECKS:
+                try:
+                    type_check(strval)
+                    _pytype = (<PyType>pytype).name
+                    break
+                except IGNORABLE_ERRORS:
+                    pass
         if _pytype is None:
             if _value is None:
-                _pytype = "none"
+                python.PyDict_SetItem(_attributes, XML_SCHEMA_INSTANCE_NIL_ATTR, "true")
             elif python._isString(_value):
                 _pytype = "str"
-    if _pytype is not None:
+    else:
+        # check if type information from arguments is valid
+        dict_result = python.PyDict_GetItem(_PYTYPE_DICT, _pytype)
+        if dict_result is not NULL:
+            type_check = (<PyType>dict_result).type_check
+            if type_check is not None:
+                type_check(strval)
+        
+    if _pytype is not None: 
         python.PyDict_SetItem(_attributes, PYTYPE_ATTRIBUTE, _pytype)
 
     return _makeElement("value", strval, _attributes, nsmap)

Modified: lxml/branch/html/src/lxml/proxy.pxi
==============================================================================
--- lxml/branch/html/src/lxml/proxy.pxi	(original)
+++ lxml/branch/html/src/lxml/proxy.pxi	Tue Jul  3 19:01:33 2007
@@ -173,19 +173,6 @@
     tree.END_FOR_EACH_ELEMENT_FROM(c_node)
     return 1
 
-## cdef void _deallocDocument(xmlDoc* c_doc):
-##     """We cannot rely on Python's GC to *always* dealloc the _Document *after*
-##     all proxies it contains => traverse the document and mark all its proxies
-##     as dead by deleting their xmlNode* reference.
-##     """
-##     cdef xmlNode* c_node
-##     c_node = c_doc.children
-##     tree.BEGIN_FOR_EACH_ELEMENT_FROM(<xmlNode*>c_doc, c_node, 1)
-##     if c_node._private is not NULL:
-##         (<_Element>c_node._private)._c_node = NULL
-##     tree.END_FOR_EACH_ELEMENT_FROM(c_node)
-##     tree.xmlFreeDoc(c_doc)
-
 ################################################################################
 # fix _Document references and namespaces when a node changes documents
 

Modified: lxml/branch/html/src/lxml/pyclasslookup.pyx
==============================================================================
--- lxml/branch/html/src/lxml/pyclasslookup.pyx	(original)
+++ lxml/branch/html/src/lxml/pyclasslookup.pyx	Tue Jul  3 19:01:33 2007
@@ -15,6 +15,8 @@
 # initialize C-API of lxml.etree
 import_etree(etree)
 
+__version__ = etree.__version__
+
 cdef class _ElementProxy:
     cdef tree.xmlNode* _c_node
     cdef object _source_proxy

Modified: lxml/branch/html/src/lxml/python.pxd
==============================================================================
--- lxml/branch/html/src/lxml/python.pxd	(original)
+++ lxml/branch/html/src/lxml/python.pxd	Tue Jul  3 19:01:33 2007
@@ -55,6 +55,7 @@
     cdef int PyDict_DelItem(object d, object key) except -1
     cdef void PyDict_Clear(object d)
     cdef object PyDict_Copy(object d)
+    cdef int PyDict_Contains(object d, object key) except -1
     cdef Py_ssize_t PyDict_Size(object d)
     cdef object PySequence_List(object o)
     cdef object PySequence_Tuple(object o)

Modified: lxml/branch/html/src/lxml/tests/test_classlookup.py
==============================================================================
--- lxml/branch/html/src/lxml/tests/test_classlookup.py	(original)
+++ lxml/branch/html/src/lxml/tests/test_classlookup.py	Tue Jul  3 19:01:33 2007
@@ -178,4 +178,4 @@
     return suite
 
 if __name__ == '__main__':
-    unittest.main()
+    print 'to test use test.py %s' % __file__

Modified: lxml/branch/html/src/lxml/tests/test_dtd.py
==============================================================================
--- lxml/branch/html/src/lxml/tests/test_dtd.py	(original)
+++ lxml/branch/html/src/lxml/tests/test_dtd.py	Tue Jul  3 19:01:33 2007
@@ -72,4 +72,4 @@
     return suite
 
 if __name__ == '__main__':
-    unittest.main()
+    print 'to test use test.py %s' % __file__

Modified: lxml/branch/html/src/lxml/tests/test_elementtree.py
==============================================================================
--- lxml/branch/html/src/lxml/tests/test_elementtree.py	(original)
+++ lxml/branch/html/src/lxml/tests/test_elementtree.py	Tue Jul  3 19:01:33 2007
@@ -2594,4 +2594,4 @@
     return suite
 
 if __name__ == '__main__':
-    unittest.main()
+    print 'to test use test.py %s' % __file__

Modified: lxml/branch/html/src/lxml/tests/test_errors.py
==============================================================================
--- lxml/branch/html/src/lxml/tests/test_errors.py	(original)
+++ lxml/branch/html/src/lxml/tests/test_errors.py	Tue Jul  3 19:01:33 2007
@@ -25,4 +25,4 @@
     return suite
 
 if __name__ == '__main__':
-    unittest.main()
+    print 'to test use test.py %s' % __file__

Modified: lxml/branch/html/src/lxml/tests/test_etree.py
==============================================================================
--- lxml/branch/html/src/lxml/tests/test_etree.py	(original)
+++ lxml/branch/html/src/lxml/tests/test_etree.py	Tue Jul  3 19:01:33 2007
@@ -14,7 +14,7 @@
 from common_imports import SillyFileLike, canonicalize, doctest
 
 print
-print "TESTED VERSION:"
+print "TESTED VERSION:", etree.__version__
 print "    Python:           ", sys.version_info
 print "    lxml.etree:       ", etree.LXML_VERSION
 print "    libxml used:      ", etree.LIBXML_VERSION
@@ -24,7 +24,7 @@
 print
 
 try:
-    sorted(())
+    sorted
 except NameError:
     # Python 2.3
     def sorted(seq):
@@ -1729,4 +1729,4 @@
     return suite
 
 if __name__ == '__main__':
-    unittest.main()
+    print 'to test use test.py %s' % __file__

Modified: lxml/branch/html/src/lxml/tests/test_htmlparser.py
==============================================================================
--- lxml/branch/html/src/lxml/tests/test_htmlparser.py	(original)
+++ lxml/branch/html/src/lxml/tests/test_htmlparser.py	Tue Jul  3 19:01:33 2007
@@ -115,4 +115,4 @@
     return suite
 
 if __name__ == '__main__':
-    unittest.main()
+    print 'to test use test.py %s' % __file__

Modified: lxml/branch/html/src/lxml/tests/test_io.py
==============================================================================
--- lxml/branch/html/src/lxml/tests/test_io.py	(original)
+++ lxml/branch/html/src/lxml/tests/test_io.py	Tue Jul  3 19:01:33 2007
@@ -172,4 +172,4 @@
     return suite
 
 if __name__ == '__main__':
-    unittest.main()
+    print 'to test use test.py %s' % __file__

Modified: lxml/branch/html/src/lxml/tests/test_nsclasses.py
==============================================================================
--- lxml/branch/html/src/lxml/tests/test_nsclasses.py	(original)
+++ lxml/branch/html/src/lxml/tests/test_nsclasses.py	Tue Jul  3 19:01:33 2007
@@ -163,4 +163,4 @@
     return suite
 
 if __name__ == '__main__':
-    unittest.main()
+    print 'to test use test.py %s' % __file__

Modified: lxml/branch/html/src/lxml/tests/test_objectify.py
==============================================================================
--- lxml/branch/html/src/lxml/tests/test_objectify.py	(original)
+++ lxml/branch/html/src/lxml/tests/test_objectify.py	Tue Jul  3 19:01:33 2007
@@ -13,10 +13,32 @@
 
 from lxml import objectify
 
+PYTYPE_NAMESPACE = "http://codespeak.net/lxml/objectify/pytype"
 XML_SCHEMA_NS = "http://www.w3.org/2001/XMLSchema"
 XML_SCHEMA_INSTANCE_NS = "http://www.w3.org/2001/XMLSchema-instance"
 XML_SCHEMA_INSTANCE_TYPE_ATTR = "{%s}type" % XML_SCHEMA_INSTANCE_NS
 XML_SCHEMA_NIL_ATTR = "{%s}nil" % XML_SCHEMA_INSTANCE_NS
+DEFAULT_NSMAP = { "py" : PYTYPE_NAMESPACE,
+                  "xsi" : XML_SCHEMA_INSTANCE_NS,
+                  "xsd" : XML_SCHEMA_NS}
+
+objectclass2xsitype = {
+    # objectify built-in
+    objectify.IntElement: ("int", "short", "byte", "unsignedShort",
+                           "unsignedByte",),
+    objectify.LongElement: ("integer", "nonPositiveInteger", "negativeInteger",
+                            "long", "nonNegativeInteger", "unsignedLong",
+                            "unsignedInt", "positiveInteger",),
+    objectify.FloatElement: ("float", "double"),
+    objectify.BoolElement: ("boolean",),
+    objectify.StringElement: ("string", "normalizedString", "token", "language",
+                              "Name", "NCName", "ID", "IDREF", "ENTITY",
+                              "NMTOKEN", ),
+    # None: xsi:nil="true"
+    }
+
+xsitype2objclass = dict(( (v, k) for k in objectclass2xsitype
+                          for v in objectclass2xsitype[k] ))
 
 xml_str = '''\
 <obj:root xmlns:obj="objectified" xmlns:other="otherNS">
@@ -52,6 +74,205 @@
         self.etree.Namespace("otherNS").clear()
         objectify.setPytypeAttributeTag()
 
+    def test_element_nsmap_default(self):
+        elt = objectify.Element("test")
+        self.assertEquals(elt.nsmap, DEFAULT_NSMAP)
+
+    def test_element_nsmap_empty(self):
+        nsmap = {}
+        elt = objectify.Element("test", nsmap=nsmap)
+        self.assertEquals(elt.nsmap.values(), [PYTYPE_NAMESPACE])
+
+    def test_element_nsmap_custom_prefixes(self):
+        nsmap = {"mypy": PYTYPE_NAMESPACE,
+                 "myxsi": XML_SCHEMA_INSTANCE_NS,
+                 "myxsd": XML_SCHEMA_NS}
+        elt = objectify.Element("test", nsmap=nsmap)
+        self.assertEquals(elt.nsmap, nsmap)
+        
+    def test_element_nsmap_custom(self):
+        nsmap = {"my": "someNS",
+                 "myother": "someOtherNS",
+                 "myxsd": XML_SCHEMA_NS}
+        elt = objectify.Element("test", nsmap=nsmap)
+        self.assert_(PYTYPE_NAMESPACE in elt.nsmap.values())
+        for prefix, ns in nsmap.items():
+            self.assert_(prefix in elt.nsmap)
+            self.assertEquals(nsmap[prefix], elt.nsmap[prefix]) 
+        
+    def test_sub_element_nsmap_default(self):
+        root = objectify.Element("root")
+        root.sub = objectify.Element("test")
+        self.assertEquals(root.sub.nsmap, DEFAULT_NSMAP)
+
+    def test_sub_element_nsmap_empty(self):
+        root = objectify.Element("root")
+        nsmap = {}
+        root.sub = objectify.Element("test", nsmap=nsmap)
+        self.assertEquals(root.sub.nsmap, DEFAULT_NSMAP)
+
+    def test_sub_element_nsmap_custom_prefixes(self):
+        root = objectify.Element("root")
+        nsmap = {"mypy": PYTYPE_NAMESPACE,
+                 "myxsi": XML_SCHEMA_INSTANCE_NS,
+                 "myxsd": XML_SCHEMA_NS}
+        root.sub = objectify.Element("test", nsmap=nsmap)
+        self.assertEquals(root.sub.nsmap, DEFAULT_NSMAP)
+        
+    def test_sub_element_nsmap_custom(self):
+        root = objectify.Element("root")
+        nsmap = {"my": "someNS",
+                 "myother": "someOtherNS",
+                 "myxsd": XML_SCHEMA_NS,}
+        root.sub = objectify.Element("test", nsmap=nsmap)
+        expected = nsmap.copy()
+        del expected["myxsd"]
+        expected.update(DEFAULT_NSMAP)
+        self.assertEquals(root.sub.nsmap, expected) 
+        
+    def test_data_element_nsmap_default(self):
+        value = objectify.DataElement("test this")
+        self.assertEquals(value.nsmap, DEFAULT_NSMAP)
+
+    def test_data_element_nsmap_empty(self):
+        nsmap = {}
+        value = objectify.DataElement("test this", nsmap=nsmap)
+        self.assertEquals(value.nsmap.values(), [PYTYPE_NAMESPACE])
+
+    def test_data_element_nsmap_custom_prefixes(self):
+        nsmap = {"mypy": PYTYPE_NAMESPACE,
+                 "myxsi": XML_SCHEMA_INSTANCE_NS,
+                 "myxsd": XML_SCHEMA_NS}
+        value = objectify.DataElement("test this", nsmap=nsmap)
+        self.assertEquals(value.nsmap, nsmap)
+        
+    def test_data_element_nsmap_custom(self):
+        nsmap = {"my": "someNS",
+                 "myother": "someOtherNS",
+                 "myxsd": XML_SCHEMA_NS,}
+        value = objectify.DataElement("test", nsmap=nsmap)
+        self.assert_(PYTYPE_NAMESPACE in value.nsmap.values())
+        for prefix, ns in nsmap.items():
+            self.assert_(prefix in value.nsmap)
+            self.assertEquals(nsmap[prefix], value.nsmap[prefix]) 
+        
+    def test_sub_data_element_nsmap_default(self):
+        root = objectify.Element("root")
+        root.value = objectify.DataElement("test this")
+        self.assertEquals(root.value.nsmap, DEFAULT_NSMAP)
+
+    def test_sub_data_element_nsmap_empty(self):
+        root = objectify.Element("root")
+        nsmap = {}
+        root.value = objectify.DataElement("test this", nsmap=nsmap)
+        self.assertEquals(root.value.nsmap, DEFAULT_NSMAP)
+
+    def test_sub_data_element_nsmap_custom_prefixes(self):
+        root = objectify.Element("root")
+        nsmap = {"mypy": PYTYPE_NAMESPACE,
+                 "myxsi": XML_SCHEMA_INSTANCE_NS,
+                 "myxsd": XML_SCHEMA_NS}
+        root.value = objectify.DataElement("test this", nsmap=nsmap)
+        self.assertEquals(root.value.nsmap, DEFAULT_NSMAP)
+        
+    def test_sub_data_element_nsmap_custom(self):
+        root = objectify.Element("root")
+        nsmap = {"my": "someNS",
+                 "myother": "someOtherNS",
+                 "myxsd": XML_SCHEMA_NS}
+        root.value = objectify.DataElement("test", nsmap=nsmap)
+        expected = nsmap.copy()
+        del expected["myxsd"]
+        expected.update(DEFAULT_NSMAP)
+        self.assertEquals(root.value.nsmap, expected) 
+        
+    def test_data_element_attrib_attributes_precedence(self):
+        # keyword arguments override attrib entries
+        value = objectify.DataElement(23, _pytype="str", _xsi="foobar",
+                                      attrib={"gnu": "muh", "cat": "meeow",
+                                              "dog": "wuff"},
+                                      bird="tchilp", dog="grrr")
+        self.assertEquals(value.get("gnu"), "muh")
+        self.assertEquals(value.get("cat"), "meeow")
+        self.assertEquals(value.get("dog"), "grrr")
+        self.assertEquals(value.get("bird"), "tchilp")
+        
+    def test_data_element_data_element_arg(self):
+        # Check that DataElement preserves all attributes ObjectifiedDataElement
+        # arguments
+        arg = objectify.DataElement(23, _pytype="str", _xsi="foobar",
+                                    attrib={"gnu": "muh", "cat": "meeow",
+                                            "dog": "wuff"},
+                                    bird="tchilp", dog="grrr")
+        value = objectify.DataElement(arg)
+        self.assert_(isinstance(value, objectify.StringElement))
+        for attr in arg.attrib:
+            self.assertEquals(value.get(attr), arg.get(attr))
+
+    def test_data_element_data_element_arg_pytype(self):
+        # Check that _pytype arg overrides original py:pytype of
+        # ObjectifiedDataElement
+        arg = objectify.DataElement(23, _pytype="str", _xsi="foobar",
+                                    attrib={"gnu": "muh", "cat": "meeow",
+                                            "dog": "wuff"},
+                                    bird="tchilp", dog="grrr")
+        value = objectify.DataElement(arg, _pytype="int")
+        self.assert_(isinstance(value, objectify.IntElement))
+        self.assertEquals(value.get(objectify.PYTYPE_ATTRIBUTE), "int")
+        for attr in arg.attrib:
+            if not attr == objectify.PYTYPE_ATTRIBUTE:
+                self.assertEquals(value.get(attr), arg.get(attr))
+
+    def test_data_element_data_element_arg_xsitype(self):
+        # Check that _xsi arg overrides original xsi:type of given
+        # ObjectifiedDataElement
+        arg = objectify.DataElement(23, _pytype="str", _xsi="foobar",
+                                    attrib={"gnu": "muh", "cat": "meeow",
+                                            "dog": "wuff"},
+                                    bird="tchilp", dog="grrr")
+        value = objectify.DataElement(arg, _xsi="xsd:int")
+        self.assert_(isinstance(value, objectify.IntElement))
+        self.assertEquals(value.get(XML_SCHEMA_INSTANCE_TYPE_ATTR), "xsd:int")
+        self.assertEquals(value.get(objectify.PYTYPE_ATTRIBUTE), "int")
+        for attr in arg.attrib:
+            if not attr in [objectify.PYTYPE_ATTRIBUTE,
+                            XML_SCHEMA_INSTANCE_TYPE_ATTR]:
+                self.assertEquals(value.get(attr), arg.get(attr))
+
+    def test_data_element_data_element_arg_pytype_xsitype(self):
+        # Check that _pytype and _xsi args override original py:pytype and
+        # xsi:type attributes of given ObjectifiedDataElement
+        arg = objectify.DataElement(23, _pytype="str", _xsi="foobar",
+                                    attrib={"gnu": "muh", "cat": "meeow",
+                                            "dog": "wuff"},
+                                    bird="tchilp", dog="grrr")
+        value = objectify.DataElement(arg, _pytype="int", _xsi="xsd:int")
+        self.assert_(isinstance(value, objectify.IntElement))
+        self.assertEquals(value.get(objectify.PYTYPE_ATTRIBUTE), "int")
+        self.assertEquals(value.get(XML_SCHEMA_INSTANCE_TYPE_ATTR), "xsd:int")
+        for attr in arg.attrib:
+            if not attr in [objectify.PYTYPE_ATTRIBUTE,
+                            XML_SCHEMA_INSTANCE_TYPE_ATTR]:
+                self.assertEquals(value.get(attr), arg.get(attr))
+
+    def test_data_element_invalid_pytype(self):
+        self.assertRaises(ValueError, objectify.DataElement, 3.1415,
+                          _pytype="int")
+
+    def test_data_element_invalid_xsi(self):
+        self.assertRaises(ValueError, objectify.DataElement, 3.1415,
+                          _xsi="xsd:int")
+        
+    def test_data_element_data_element_arg_invalid_pytype(self):
+        arg = objectify.DataElement(3.1415)
+        self.assertRaises(ValueError, objectify.DataElement, arg,
+                          _pytype="int")
+
+    def test_data_element_data_element_arg_invalid_xsi(self):
+        arg = objectify.DataElement(3.1415)
+        self.assertRaises(ValueError, objectify.DataElement, arg,
+                          _xsi="xsd:int")
+        
     def test_root(self):
         root = self.Element("test")
         self.assert_(isinstance(root, objectify.ObjectifiedElement))
@@ -268,7 +489,7 @@
         Element = self.Element
         SubElement = self.etree.SubElement
 
-        nil_attr = "{http://www.w3.org/2001/XMLSchema-instance}nil"
+        nil_attr = XML_SCHEMA_NIL_ATTR
         root = Element("{objectified}root")
         SubElement(root, "{objectified}none")
         SubElement(root, "{objectified}none", {nil_attr : "true"})
@@ -282,13 +503,19 @@
         value = objectify.DataElement(None)
         self.assert_(isinstance(value, objectify.NoneElement))
         self.assertEquals(value, None)
+        self.assertEquals(value.get(XML_SCHEMA_NIL_ATTR), "true")
 
     def test_type_bool(self):
         Element = self.Element
         SubElement = self.etree.SubElement
         root = Element("{objectified}root")
-        root.none = 'true'
-        self.assert_(isinstance(root.none, objectify.BoolElement))
+        root.bool = 'true'
+        self.assert_(isinstance(root.bool, objectify.BoolElement))
+        self.assertEquals(root.bool, True)
+
+        root.bool = 'false'
+        self.assert_(isinstance(root.bool, objectify.BoolElement))
+        self.assertEquals(root.bool, False)
 
     def test_data_element_bool(self):
         value = objectify.DataElement(True)
@@ -357,6 +584,24 @@
         self.assert_(isinstance(value, objectify.FloatElement))
         self.assertEquals(value, 5.5)
 
+    def test_data_element_xsitypes(self):
+        for xsi, objclass in xsitype2objclass.iteritems():
+            # 1 is a valid value for all ObjectifiedDataElement classes
+            value = objectify.DataElement(1, _xsi=xsi)
+            self.assert_(isinstance(value, objclass))
+        
+    def test_data_element_xsitypes_xsdprefixed(self):
+        for xsi, objclass in xsitype2objclass.iteritems():
+            # 1 is a valid value for all ObjectifiedDataElement classes
+            value = objectify.DataElement(1, _xsi="xsd:%s" % xsi)
+            self.assert_(isinstance(value, objclass))
+        
+    def test_data_element_xsitypes_prefixed(self):
+        for xsi, objclass in xsitype2objclass.iteritems():
+            # 1 is a valid value for all ObjectifiedDataElement classes
+            self.assertRaises(ValueError, objectify.DataElement, 1,
+                              _xsi="foo:%s" % xsi)
+
     def test_schema_types(self):
         XML = self.XML
         root = XML('''\
@@ -401,9 +646,9 @@
 
         for b in root.b:
             self.assert_(isinstance(b, objectify.BoolElement))
-        self.assertEquals(True, root.b[0])
+        self.assertEquals(True,  root.b[0])
         self.assertEquals(False, root.b[1])
-        self.assertEquals(True, root.b[2])
+        self.assertEquals(True,  root.b[2])
         self.assertEquals(False, root.b[3])
 
         for f in root.f:
@@ -416,7 +661,7 @@
 
         for l in root.l:
             self.assert_(isinstance(l, objectify.LongElement))
-            self.assertEquals(5l, l)
+            self.assertEquals(5L, l)
 
         for i in root.i:
             self.assert_(isinstance(i, objectify.IntElement))
@@ -425,6 +670,75 @@
         self.assert_(isinstance(root.n, objectify.NoneElement))
         self.assertEquals(None, root.n)
 
+    def test_schema_types_prefixed(self):
+        XML = self.XML
+        root = XML('''\
+        <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+          <b xsi:type="xsd:boolean">true</b>
+          <b xsi:type="xsd:boolean">false</b>
+          <b xsi:type="xsd:boolean">1</b>
+          <b xsi:type="xsd:boolean">0</b>
+
+          <f xsi:type="xsd:float">5</f>
+          <f xsi:type="xsd:double">5</f>
+        
+          <s xsi:type="xsd:string">5</s>
+          <s xsi:type="xsd:normalizedString">5</s>
+          <s xsi:type="xsd:token">5</s>
+          <s xsi:type="xsd:language">5</s>
+          <s xsi:type="xsd:Name">5</s>
+          <s xsi:type="xsd:NCName">5</s>
+          <s xsi:type="xsd:ID">5</s>
+          <s xsi:type="xsd:IDREF">5</s>
+          <s xsi:type="xsd:ENTITY">5</s>
+          <s xsi:type="xsd:NMTOKEN">5</s>
+
+          <l xsi:type="xsd:integer">5</l>
+          <l xsi:type="xsd:nonPositiveInteger">5</l>
+          <l xsi:type="xsd:negativeInteger">5</l>
+          <l xsi:type="xsd:long">5</l>
+          <l xsi:type="xsd:nonNegativeInteger">5</l>
+          <l xsi:type="xsd:unsignedLong">5</l>
+          <l xsi:type="xsd:unsignedInt">5</l>
+          <l xsi:type="xsd:positiveInteger">5</l>
+          
+          <i xsi:type="xsd:int">5</i>
+          <i xsi:type="xsd:short">5</i>
+          <i xsi:type="xsd:byte">5</i>
+          <i xsi:type="xsd:unsignedShort">5</i>
+          <i xsi:type="xsd:unsignedByte">5</i>
+
+          <n xsi:nil="true"/>
+        </root>
+        ''')
+
+        for b in root.b:
+            self.assert_(isinstance(b, objectify.BoolElement))
+        self.assertEquals(True,  root.b[0])
+        self.assertEquals(False, root.b[1])
+        self.assertEquals(True,  root.b[2])
+        self.assertEquals(False, root.b[3])
+
+        for f in root.f:
+            self.assert_(isinstance(f, objectify.FloatElement))
+            self.assertEquals(5, f)
+            
+        for s in root.s:
+            self.assert_(isinstance(s, objectify.StringElement))
+            self.assertEquals("5", s)
+
+        for l in root.l:
+            self.assert_(isinstance(l, objectify.LongElement))
+            self.assertEquals(5L, l)
+
+        for i in root.i:
+            self.assert_(isinstance(i, objectify.IntElement))
+            self.assertEquals(5, i)
+            
+        self.assert_(isinstance(root.n, objectify.NoneElement))
+        self.assertEquals(None, root.n)
+        
     def test_type_str_sequence(self):
         XML = self.XML
         root = XML(u'<root><b>why</b><b>try</b></root>')
@@ -539,19 +853,19 @@
 
         child_types = [ c.get(objectify.PYTYPE_ATTRIBUTE)
                         for c in root.iterchildren() ]
-        self.assertEquals("int",   child_types[0])
-        self.assertEquals("str",   child_types[1])
-        self.assertEquals("float", child_types[2])
-        self.assertEquals("str",   child_types[3])
-        self.assertEquals("bool",  child_types[4])
-        self.assertEquals("none",  child_types[5])
-        self.assertEquals(None,    child_types[6])
-        self.assertEquals("float", child_types[7])
-        self.assertEquals("float", child_types[8])
-        self.assertEquals("str", child_types[9])
-        self.assertEquals("int", child_types[10])
-        self.assertEquals("int", child_types[11])
-        self.assertEquals("int", child_types[12])
+        self.assertEquals("int",   child_types[ 0])
+        self.assertEquals("str",   child_types[ 1])
+        self.assertEquals("float", child_types[ 2])
+        self.assertEquals("str",   child_types[ 3])
+        self.assertEquals("bool",  child_types[ 4])
+        self.assertEquals("none",  child_types[ 5])
+        self.assertEquals(None,    child_types[ 6])
+        self.assertEquals("float", child_types[ 7])
+        self.assertEquals("float", child_types[ 8])
+        self.assertEquals("str",   child_types[ 9])
+        self.assertEquals("int",   child_types[10])
+        self.assertEquals("int",   child_types[11])
+        self.assertEquals("int",   child_types[12])
         
         self.assertEquals("true", root.n.get(XML_SCHEMA_NIL_ATTR))
 
@@ -771,7 +1085,8 @@
         XML = self.XML
         root = XML(u'''\
         <a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xmlns:py="http://codespeak.net/lxml/objectify/pytype">
+        xmlns:py="http://codespeak.net/lxml/objectify/pytype"
+        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
           <b>5</b>
           <b>test</b>
           <c>1.1</c>
@@ -779,9 +1094,9 @@
           <x>true</x>
           <n xsi:nil="true" />
           <n></n>
-          <b xsi:type="double">5</b>
-          <b xsi:type="float">5</b>
-          <s xsi:type="string">23</s>
+          <b xsi:type="xsd:double">5</b>
+          <b xsi:type="xsd:float">5</b>
+          <s xsi:type="xsd:string">23</s>
           <s py:pytype="str">42</s>
           <f py:pytype="float">300</f>
           <l py:pytype="long">2</l>
@@ -811,6 +1126,51 @@
         for c in root.getiterator():
             self.assertEquals(None, c.get(XML_SCHEMA_INSTANCE_TYPE_ATTR))
 
+    def test_pytype_deannotate(self):
+        XML = self.XML
+        root = XML(u'''\
+        <a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xmlns:py="http://codespeak.net/lxml/objectify/pytype"
+        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+          <b xsi:type="xsd:int">5</b>
+          <b xsi:type="xsd:string">test</b>
+          <c xsi:type="xsd:float">1.1</c>
+          <c xsi:type="xsd:string">\uF8D2</c>
+          <x xsi:type="xsd:boolean">true</x>
+          <n xsi:nil="true" />
+          <n></n>
+          <b xsi:type="xsd:double">5</b>
+          <b xsi:type="xsd:float">5</b>
+          <s xsi:type="xsd:string">23</s>
+          <s xsi:type="xsd:string">42</s>
+          <f xsi:type="xsd:float">300</f>
+          <l xsi:type="xsd:long">2</l>
+        </a>
+        ''')
+        objectify.annotate(root)
+        objectify.deannotate(root, xsi=False)
+
+        child_types = [ c.get(XML_SCHEMA_INSTANCE_TYPE_ATTR)
+                        for c in root.iterchildren() ]
+        self.assertEquals("xsd:int",      child_types[ 0])
+        self.assertEquals("xsd:string",   child_types[ 1])
+        self.assertEquals("xsd:float",    child_types[ 2])
+        self.assertEquals("xsd:string",   child_types[ 3])
+        self.assertEquals("xsd:boolean",  child_types[ 4])
+        self.assertEquals(None,           child_types[ 5])
+        self.assertEquals(None,           child_types[ 6])
+        self.assertEquals("xsd:double",   child_types[ 7])
+        self.assertEquals("xsd:float",    child_types[ 8])
+        self.assertEquals("xsd:string",   child_types[ 9])
+        self.assertEquals("xsd:string",   child_types[10])
+        self.assertEquals("xsd:float",    child_types[11])
+        self.assertEquals("xsd:long",     child_types[12])
+
+        self.assertEquals("true", root.n.get(XML_SCHEMA_NIL_ATTR))
+
+        for c in root.getiterator():
+            self.assertEquals(None, c.get(objectify.PYTYPE_ATTRIBUTE))
+
     def test_change_pytype_attribute(self):
         XML = self.XML
 
@@ -1238,4 +1598,4 @@
     return suite
 
 if __name__ == '__main__':
-    unittest.main()
+    print 'to test use test.py %s' % __file__

Modified: lxml/branch/html/src/lxml/tests/test_pyclasslookup.py
==============================================================================
--- lxml/branch/html/src/lxml/tests/test_pyclasslookup.py	(original)
+++ lxml/branch/html/src/lxml/tests/test_pyclasslookup.py	Tue Jul  3 19:01:33 2007
@@ -287,4 +287,4 @@
     return suite
 
 if __name__ == '__main__':
-    unittest.main()
+    print 'to test use test.py %s' % __file__

Modified: lxml/branch/html/src/lxml/tests/test_relaxng.py
==============================================================================
--- lxml/branch/html/src/lxml/tests/test_relaxng.py	(original)
+++ lxml/branch/html/src/lxml/tests/test_relaxng.py	Tue Jul  3 19:01:33 2007
@@ -142,4 +142,4 @@
     return suite
 
 if __name__ == '__main__':
-    unittest.main()
+    print 'to test use test.py %s' % __file__

Modified: lxml/branch/html/src/lxml/tests/test_sax.py
==============================================================================
--- lxml/branch/html/src/lxml/tests/test_sax.py	(original)
+++ lxml/branch/html/src/lxml/tests/test_sax.py	Tue Jul  3 19:01:33 2007
@@ -222,4 +222,4 @@
     return suite
 
 if __name__ == '__main__':
-    unittest.main()
+    print 'to test use test.py %s' % __file__

Modified: lxml/branch/html/src/lxml/tests/test_xmlschema.py
==============================================================================
--- lxml/branch/html/src/lxml/tests/test_xmlschema.py	(original)
+++ lxml/branch/html/src/lxml/tests/test_xmlschema.py	Tue Jul  3 19:01:33 2007
@@ -81,4 +81,4 @@
     return suite
 
 if __name__ == '__main__':
-    unittest.main()
+    print 'to test use test.py %s' % __file__

Modified: lxml/branch/html/src/lxml/tests/test_xpathevaluator.py
==============================================================================
--- lxml/branch/html/src/lxml/tests/test_xpathevaluator.py	(original)
+++ lxml/branch/html/src/lxml/tests/test_xpathevaluator.py	Tue Jul  3 19:01:33 2007
@@ -532,4 +532,4 @@
     return suite
 
 if __name__ == '__main__':
-    unittest.main()
+    print 'to test use test.py %s' % __file__

Modified: lxml/branch/html/src/lxml/tests/test_xslt.py
==============================================================================
--- lxml/branch/html/src/lxml/tests/test_xslt.py	(original)
+++ lxml/branch/html/src/lxml/tests/test_xslt.py	Tue Jul  3 19:01:33 2007
@@ -1011,4 +1011,4 @@
     return suite
 
 if __name__ == '__main__':
-    unittest.main()
+    print 'to test use test.py %s' % __file__

Modified: lxml/branch/html/src/lxml/xpath.pxi
==============================================================================
--- lxml/branch/html/src/lxml/xpath.pxi	(original)
+++ lxml/branch/html/src/lxml/xpath.pxi	Tue Jul  3 19:01:33 2007
@@ -392,6 +392,9 @@
         if self._xpath is not NULL:
             xpath.xmlXPathFreeCompExpr(self._xpath)
 
+    def __repr__(self):
+        return path
+
 
 cdef object _replace_strings
 cdef object _find_namespaces


More information about the lxml-checkins mailing list