1
2
3 """
4 Tests specific to the lxml.objectify API
5 """
6
7
8 import unittest, operator
9
10 from common_imports import etree, StringIO, HelperTestCase, fileInTestDir
11 from common_imports import SillyFileLike, canonicalize, doctest
12
13 from lxml import objectify
14
15 PYTYPE_NAMESPACE = "http://codespeak.net/lxml/objectify/pytype"
16 XML_SCHEMA_NS = "http://www.w3.org/2001/XMLSchema"
17 XML_SCHEMA_INSTANCE_NS = "http://www.w3.org/2001/XMLSchema-instance"
18 XML_SCHEMA_INSTANCE_TYPE_ATTR = "{%s}type" % XML_SCHEMA_INSTANCE_NS
19 XML_SCHEMA_NIL_ATTR = "{%s}nil" % XML_SCHEMA_INSTANCE_NS
20 TREE_PYTYPE = "TREE"
21 DEFAULT_NSMAP = { "py" : PYTYPE_NAMESPACE,
22 "xsi" : XML_SCHEMA_INSTANCE_NS,
23 "xsd" : XML_SCHEMA_NS}
24
25 objectclass2xsitype = {
26
27 objectify.IntElement: ("int", "short", "byte", "unsignedShort",
28 "unsignedByte",),
29 objectify.LongElement: ("integer", "nonPositiveInteger", "negativeInteger",
30 "long", "nonNegativeInteger", "unsignedLong",
31 "unsignedInt", "positiveInteger",),
32 objectify.FloatElement: ("float", "double"),
33 objectify.BoolElement: ("boolean",),
34 objectify.StringElement: ("string", "normalizedString", "token", "language",
35 "Name", "NCName", "ID", "IDREF", "ENTITY",
36 "NMTOKEN", ),
37
38 }
39
40 xsitype2objclass = dict(( (v, k) for k in objectclass2xsitype
41 for v in objectclass2xsitype[k] ))
42
43 objectclass2pytype = {
44
45 objectify.IntElement: "int",
46 objectify.LongElement: "long",
47 objectify.FloatElement: "float",
48 objectify.BoolElement: "bool",
49 objectify.StringElement: "str",
50
51 }
52
53 pytype2objclass = dict(( (objectclass2pytype[k], k) for k in objectclass2pytype))
54
55 xml_str = '''\
56 <obj:root xmlns:obj="objectified" xmlns:other="otherNS">
57 <obj:c1 a1="A1" a2="A2" other:a3="A3">
58 <obj:c2>0</obj:c2>
59 <obj:c2>1</obj:c2>
60 <obj:c2>2</obj:c2>
61 <other:c2>3</other:c2>
62 <c2>3</c2>
63 </obj:c1>
64 </obj:root>'''
65
67 """Test cases for lxml.objectify
68 """
69 etree = etree
70
73
84
90
94
99
106
116
121
127
135
146
150
155
162
172
177
183
191
202
204
205 value = objectify.DataElement(23, _pytype="str", _xsi="foobar",
206 attrib={"gnu": "muh", "cat": "meeow",
207 "dog": "wuff"},
208 bird="tchilp", dog="grrr")
209 self.assertEquals(value.get("gnu"), "muh")
210 self.assertEquals(value.get("cat"), "meeow")
211 self.assertEquals(value.get("dog"), "grrr")
212 self.assertEquals(value.get("bird"), "tchilp")
213
225
227
228
229 arg = objectify.DataElement(23, _pytype="str", _xsi="foobar",
230 attrib={"gnu": "muh", "cat": "meeow",
231 "dog": "wuff"},
232 bird="tchilp", dog="grrr")
233 value = objectify.DataElement(arg, _pytype="NoneType")
234 self.assert_(isinstance(value, objectify.NoneElement))
235 self.assertEquals(value.get(XML_SCHEMA_NIL_ATTR), "true")
236 self.assertEquals(value.text, None)
237 self.assertEquals(value.pyval, None)
238 for attr in arg.attrib:
239
240 self.assertEquals(value.get(attr), arg.get(attr))
241
243
244
245 arg = objectify.DataElement(23, _pytype="str", _xsi="foobar",
246 attrib={"gnu": "muh", "cat": "meeow",
247 "dog": "wuff"},
248 bird="tchilp", dog="grrr")
249 value = objectify.DataElement(arg, _pytype="int")
250 self.assert_(isinstance(value, objectify.IntElement))
251 self.assertEquals(value.get(objectify.PYTYPE_ATTRIBUTE), "int")
252 for attr in arg.attrib:
253 if not attr == objectify.PYTYPE_ATTRIBUTE:
254 self.assertEquals(value.get(attr), arg.get(attr))
255
257
258
259 arg = objectify.DataElement(23, _pytype="str", _xsi="foobar",
260 attrib={"gnu": "muh", "cat": "meeow",
261 "dog": "wuff"},
262 bird="tchilp", dog="grrr")
263 value = objectify.DataElement(arg, _xsi="xsd:int")
264 self.assert_(isinstance(value, objectify.IntElement))
265 self.assertEquals(value.get(XML_SCHEMA_INSTANCE_TYPE_ATTR), "xsd:int")
266 self.assertEquals(value.get(objectify.PYTYPE_ATTRIBUTE), "int")
267 for attr in arg.attrib:
268 if not attr in [objectify.PYTYPE_ATTRIBUTE,
269 XML_SCHEMA_INSTANCE_TYPE_ATTR]:
270 self.assertEquals(value.get(attr), arg.get(attr))
271
273
274
275 arg = objectify.DataElement(23, _pytype="str", _xsi="foobar",
276 attrib={"gnu": "muh", "cat": "meeow",
277 "dog": "wuff"},
278 bird="tchilp", dog="grrr")
279 value = objectify.DataElement(arg, _pytype="int", _xsi="xsd:int")
280 self.assert_(isinstance(value, objectify.IntElement))
281 self.assertEquals(value.get(objectify.PYTYPE_ATTRIBUTE), "int")
282 self.assertEquals(value.get(XML_SCHEMA_INSTANCE_TYPE_ATTR), "xsd:int")
283 for attr in arg.attrib:
284 if not attr in [objectify.PYTYPE_ATTRIBUTE,
285 XML_SCHEMA_INSTANCE_TYPE_ATTR]:
286 self.assertEquals(value.get(attr), arg.get(attr))
287
291
295
300
305
309
313
317
322
324 root = self.XML(xml_str)
325 self.assertEquals("0", getattr(root.c1, "{objectified}c2").text)
326 self.assertEquals("3", getattr(root.c1, "{otherNS}c2").text)
327
329 root = self.XML(xml_str)
330 self.assertRaises(AttributeError, getattr, root.c1, "NOT_THERE")
331 self.assertRaises(AttributeError, getattr, root.c1, "{unknownNS}c2")
332
339
341 root = self.XML(xml_str)
342 self.assertEquals(1, len(root.c1))
343
344 new_el = self.Element("test", myattr="5")
345 root.addattr("c1", new_el)
346 self.assertEquals(2, len(root.c1))
347 self.assertEquals(None, root.c1[0].get("myattr"))
348 self.assertEquals("5", root.c1[1].get("myattr"))
349
351 root = self.XML(xml_str)
352 self.assertEquals(1, len(root.c1))
353
354 new_el = self.Element("test")
355 self.etree.SubElement(new_el, "a", myattr="A")
356 self.etree.SubElement(new_el, "a", myattr="B")
357
358 root.addattr("c1", list(new_el.a))
359 self.assertEquals(3, len(root.c1))
360 self.assertEquals(None, root.c1[0].get("myattr"))
361 self.assertEquals("A", root.c1[1].get("myattr"))
362 self.assertEquals("B", root.c1[2].get("myattr"))
363
370
372 root = self.XML(xml_str)
373 self.assertEquals("0", root.c1.c2[0].text)
374 self.assertEquals("1", root.c1.c2[1].text)
375 self.assertEquals("2", root.c1.c2[2].text)
376 self.assertRaises(IndexError, operator.getitem, root.c1.c2, 3)
377
379 root = self.XML(xml_str)
380 self.assertEquals("0", root.c1.c2[0].text)
381 self.assertEquals("0", root.c1.c2[-3].text)
382 self.assertEquals("1", root.c1.c2[-2].text)
383 self.assertEquals("2", root.c1.c2[-1].text)
384 self.assertRaises(IndexError, operator.getitem, root.c1.c2, -4)
385
387 root = self.XML(xml_str)
388 self.assertEquals(1, len(root))
389 self.assertEquals(1, len(root.c1))
390 self.assertEquals(3, len(root.c1.c2))
391
400
406
416
421
426
428 Element = self.Element
429 SubElement = self.etree.SubElement
430 root = Element("root")
431 root.c = ["c1", "c2"]
432
433 c1 = root.c[0]
434 c2 = root.c[1]
435
436 self.assertEquals([c1,c2], list(root.c))
437 self.assertEquals(["c1", "c2"],
438 [ c.text for c in root.c ])
439
440 root2 = Element("root2")
441 root2.el = [ "test", "test" ]
442 self.assertEquals(["test", "test"],
443 [ el.text for el in root2.el ])
444
445 root.c = [ root2.el, root2.el ]
446 self.assertEquals(["test", "test"],
447 [ c.text for c in root.c ])
448 self.assertEquals(["test", "test"],
449 [ el.text for el in root2.el ])
450
451 root.c[:] = [ c1, c2, c2, c1 ]
452 self.assertEquals(["c1", "c2", "c2", "c1"],
453 [ c.text for c in root.c ])
454
463
472
474
475 Element = self.Element
476 SubElement = self.etree.SubElement
477 root = Element("root")
478
479 root["text"] = "TEST"
480 self.assertEquals(["TEST"],
481 [ c.text for c in root["text"] ])
482
483 root["tail"] = "TEST"
484 self.assertEquals(["TEST"],
485 [ c.text for c in root["tail"] ])
486
487 root["pyval"] = "TEST"
488 self.assertEquals(["TEST"],
489 [ c.text for c in root["pyval"] ])
490
491 root["tag"] = "TEST"
492 self.assertEquals(["TEST"],
493 [ c.text for c in root["tag"] ])
494
502
504 XML = self.XML
505 root = XML('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>')
506 self.assertEquals(2, len(root.findall(".//{X}b")))
507 self.assertEquals(3, len(root.findall(".//b")))
508 self.assertEquals(2, len(root.findall("b")))
509
517
531
537
549
558
565
572
579
581 Element = self.Element
582 SubElement = self.etree.SubElement
583 root = Element("{objectified}root")
584 root.s = "test"
585
586 self.assertEquals("test" * 5, root.s * 5)
587 self.assertEquals(5 * "test", 5 * root.s)
588
589 self.assertRaises(TypeError, operator.mul, root.s, "honk")
590 self.assertRaises(TypeError, operator.mul, "honk", root.s)
591
601
606
611
616
623
630
637
639 Element = self.Element
640 SubElement = self.etree.SubElement
641 root = Element("{objectified}root")
642 root.s = u"test"
643
644 self.assertEquals(u"test" * 5, root.s * 5)
645 self.assertEquals(5 * u"test", 5 * root.s)
646
647 self.assertRaises(TypeError, operator.mul, root.s, u"honk")
648 self.assertRaises(TypeError, operator.mul, u"honk", root.s)
649
659
664
669
674
681
686
693
698
707
716
722
731
733 pyval = 1
734 pytype = "NoneType"
735 objclass = objectify.NoneElement
736 value = objectify.DataElement(pyval, _pytype=pytype)
737 self.assert_(isinstance(value, objclass),
738 "DataElement(%s, _pytype='%s') returns %s, expected %s"
739 % (pyval, pytype, type(value), objclass))
740 self.assertEquals(value.text, None)
741 self.assertEquals(value.pyval, None)
742
744
745 pyval = 1
746 pytype = "none"
747 objclass = objectify.NoneElement
748 value = objectify.DataElement(pyval, _pytype=pytype)
749 self.assert_(isinstance(value, objclass),
750 "DataElement(%s, _pytype='%s') returns %s, expected %s"
751 % (pyval, pytype, type(value), objclass))
752 self.assertEquals(value.text, None)
753 self.assertEquals(value.pyval, None)
754
760 root = Element("{objectified}root")
761 root.myfloat = MyFloat(5.5)
762 self.assert_(isinstance(root.myfloat, objectify.FloatElement))
763 self.assertEquals(root.myfloat.get(objectify.PYTYPE_ATTRIBUTE), None)
764
766 class MyFloat(float):
767 pass
768 value = objectify.DataElement(MyFloat(5.5))
769 self.assert_(isinstance(value, objectify.FloatElement))
770 self.assertEquals(value, 5.5)
771 self.assertEquals(value.get(objectify.PYTYPE_ATTRIBUTE), None)
772
774 XML = self.XML
775 root = XML('''\
776 <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
777 <b xsi:type="boolean">true</b>
778 <b xsi:type="boolean">false</b>
779 <b xsi:type="boolean">1</b>
780 <b xsi:type="boolean">0</b>
781
782 <f xsi:type="float">5</f>
783 <f xsi:type="double">5</f>
784
785 <s xsi:type="string">5</s>
786 <s xsi:type="normalizedString">5</s>
787 <s xsi:type="token">5</s>
788 <s xsi:type="language">5</s>
789 <s xsi:type="Name">5</s>
790 <s xsi:type="NCName">5</s>
791 <s xsi:type="ID">5</s>
792 <s xsi:type="IDREF">5</s>
793 <s xsi:type="ENTITY">5</s>
794 <s xsi:type="NMTOKEN">5</s>
795
796 <l xsi:type="integer">5</l>
797 <l xsi:type="nonPositiveInteger">5</l>
798 <l xsi:type="negativeInteger">5</l>
799 <l xsi:type="long">5</l>
800 <l xsi:type="nonNegativeInteger">5</l>
801 <l xsi:type="unsignedLong">5</l>
802 <l xsi:type="unsignedInt">5</l>
803 <l xsi:type="positiveInteger">5</l>
804
805 <i xsi:type="int">5</i>
806 <i xsi:type="short">5</i>
807 <i xsi:type="byte">5</i>
808 <i xsi:type="unsignedShort">5</i>
809 <i xsi:type="unsignedByte">5</i>
810
811 <n xsi:nil="true"/>
812 </root>
813 ''')
814
815 for b in root.b:
816 self.assert_(isinstance(b, objectify.BoolElement))
817 self.assertEquals(True, root.b[0])
818 self.assertEquals(False, root.b[1])
819 self.assertEquals(True, root.b[2])
820 self.assertEquals(False, root.b[3])
821
822 for f in root.f:
823 self.assert_(isinstance(f, objectify.FloatElement))
824 self.assertEquals(5, f)
825
826 for s in root.s:
827 self.assert_(isinstance(s, objectify.StringElement))
828 self.assertEquals("5", s)
829
830 for l in root.l:
831 self.assert_(isinstance(l, objectify.LongElement))
832 self.assertEquals(5L, l)
833
834 for i in root.i:
835 self.assert_(isinstance(i, objectify.IntElement))
836 self.assertEquals(5, i)
837
838 self.assert_(isinstance(root.n, objectify.NoneElement))
839 self.assertEquals(None, root.n)
840
842 XML = self.XML
843 root = XML('''\
844 <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
845 xmlns:xsd="http://www.w3.org/2001/XMLSchema">
846 <b xsi:type="xsd:boolean">true</b>
847 <b xsi:type="xsd:boolean">false</b>
848 <b xsi:type="xsd:boolean">1</b>
849 <b xsi:type="xsd:boolean">0</b>
850
851 <f xsi:type="xsd:float">5</f>
852 <f xsi:type="xsd:double">5</f>
853
854 <s xsi:type="xsd:string">5</s>
855 <s xsi:type="xsd:normalizedString">5</s>
856 <s xsi:type="xsd:token">5</s>
857 <s xsi:type="xsd:language">5</s>
858 <s xsi:type="xsd:Name">5</s>
859 <s xsi:type="xsd:NCName">5</s>
860 <s xsi:type="xsd:ID">5</s>
861 <s xsi:type="xsd:IDREF">5</s>
862 <s xsi:type="xsd:ENTITY">5</s>
863 <s xsi:type="xsd:NMTOKEN">5</s>
864
865 <l xsi:type="xsd:integer">5</l>
866 <l xsi:type="xsd:nonPositiveInteger">5</l>
867 <l xsi:type="xsd:negativeInteger">5</l>
868 <l xsi:type="xsd:long">5</l>
869 <l xsi:type="xsd:nonNegativeInteger">5</l>
870 <l xsi:type="xsd:unsignedLong">5</l>
871 <l xsi:type="xsd:unsignedInt">5</l>
872 <l xsi:type="xsd:positiveInteger">5</l>
873
874 <i xsi:type="xsd:int">5</i>
875 <i xsi:type="xsd:short">5</i>
876 <i xsi:type="xsd:byte">5</i>
877 <i xsi:type="xsd:unsignedShort">5</i>
878 <i xsi:type="xsd:unsignedByte">5</i>
879
880 <n xsi:nil="true"/>
881 </root>
882 ''')
883
884 for b in root.b:
885 self.assert_(isinstance(b, objectify.BoolElement))
886 self.assertEquals(True, root.b[0])
887 self.assertEquals(False, root.b[1])
888 self.assertEquals(True, root.b[2])
889 self.assertEquals(False, root.b[3])
890
891 for f in root.f:
892 self.assert_(isinstance(f, objectify.FloatElement))
893 self.assertEquals(5, f)
894
895 for s in root.s:
896 self.assert_(isinstance(s, objectify.StringElement))
897 self.assertEquals("5", s)
898
899 for l in root.l:
900 self.assert_(isinstance(l, objectify.LongElement))
901 self.assertEquals(5L, l)
902
903 for i in root.i:
904 self.assert_(isinstance(i, objectify.IntElement))
905 self.assertEquals(5, i)
906
907 self.assert_(isinstance(root.n, objectify.NoneElement))
908 self.assertEquals(None, root.n)
909
911 XML = self.XML
912 root = XML(u'<root><b>why</b><b>try</b></root>')
913 strs = [ str(s) for s in root.b ]
914 self.assertEquals(["why", "try"],
915 strs)
916
937
958
982
988
995
999
1001 XML = self.XML
1002 root = XML(u'''\
1003 <a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1004 xmlns:py="http://codespeak.net/lxml/objectify/pytype">
1005 <b>5</b>
1006 <b>test</b>
1007 <c>1.1</c>
1008 <c>\uF8D2</c>
1009 <x>true</x>
1010 <n xsi:nil="true" />
1011 <n></n>
1012 <b xsi:type="double">5</b>
1013 <b xsi:type="float">5</b>
1014 <s xsi:type="string">23</s>
1015 <s py:pytype="str">42</s>
1016 <f py:pytype="float">300</f>
1017 <l py:pytype="long">2</l>
1018 <t py:pytype="TREE"></t>
1019 </a>
1020 ''')
1021 objectify.annotate(root)
1022
1023 child_types = [ c.get(objectify.PYTYPE_ATTRIBUTE)
1024 for c in root.iterchildren() ]
1025 self.assertEquals("int", child_types[ 0])
1026 self.assertEquals("str", child_types[ 1])
1027 self.assertEquals("float", child_types[ 2])
1028 self.assertEquals("str", child_types[ 3])
1029 self.assertEquals("bool", child_types[ 4])
1030 self.assertEquals("NoneType", child_types[ 5])
1031 self.assertEquals(None, child_types[ 6])
1032 self.assertEquals("float", child_types[ 7])
1033 self.assertEquals("float", child_types[ 8])
1034 self.assertEquals("str", child_types[ 9])
1035 self.assertEquals("int", child_types[10])
1036 self.assertEquals("int", child_types[11])
1037 self.assertEquals("int", child_types[12])
1038 self.assertEquals(None, child_types[13])
1039
1040 self.assertEquals("true", root.n.get(XML_SCHEMA_NIL_ATTR))
1041
1061
1063 XML = self.XML
1064 root = XML(u'''\
1065 <a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1066 xmlns:py="http://codespeak.net/lxml/objectify/pytype">
1067 <b>5</b>
1068 <b>test</b>
1069 <c>1.1</c>
1070 <c>\uF8D2</c>
1071 <x>true</x>
1072 <n xsi:nil="true" />
1073 <n></n>
1074 <b xsi:type="double">5</b>
1075 <b xsi:type="float">5</b>
1076 <s xsi:type="string">23</s>
1077 <s py:pytype="str">42</s>
1078 <f py:pytype="float">300</f>
1079 <l py:pytype="long">2</l>
1080 <t py:pytype="TREE"></t>
1081 </a>
1082 ''')
1083 objectify.annotate(root, ignore_old=False)
1084
1085 child_types = [ c.get(objectify.PYTYPE_ATTRIBUTE)
1086 for c in root.iterchildren() ]
1087 self.assertEquals("int", child_types[ 0])
1088 self.assertEquals("str", child_types[ 1])
1089 self.assertEquals("float", child_types[ 2])
1090 self.assertEquals("str", child_types[ 3])
1091 self.assertEquals("bool", child_types[ 4])
1092 self.assertEquals("NoneType", child_types[ 5])
1093 self.assertEquals(None, child_types[ 6])
1094 self.assertEquals("float", child_types[ 7])
1095 self.assertEquals("float", child_types[ 8])
1096 self.assertEquals("str", child_types[ 9])
1097 self.assertEquals("str", child_types[10])
1098 self.assertEquals("float", child_types[11])
1099 self.assertEquals("long", child_types[12])
1100 self.assertEquals(TREE_PYTYPE, child_types[13])
1101
1102 self.assertEquals("true", root.n.get(XML_SCHEMA_NIL_ATTR))
1103
1105 XML = self.XML
1106 root = XML(u'''\
1107 <a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1108 xmlns:py="http://codespeak.net/lxml/objectify/pytype">
1109 <b>5</b>
1110 <b>test</b>
1111 <c>1.1</c>
1112 <c>\uF8D2</c>
1113 <x>true</x>
1114 <n xsi:nil="true" />
1115 <n></n>
1116 <b xsi:type="double">5</b>
1117 <b xsi:type="float">5</b>
1118 <s xsi:type="string">23</s>
1119 <s py:pytype="str">42</s>
1120 <f py:pytype="float">300</f>
1121 <l py:pytype="long">2</l>
1122 <t py:pytype="TREE"></t>
1123 </a>
1124 ''')
1125 objectify.annotate(root, ignore_old=False, ignore_xsi=False,
1126 annotate_xsi=1, annotate_pytype=1)
1127
1128
1129 child_types = [ c.get(objectify.PYTYPE_ATTRIBUTE)
1130 for c in root.iterchildren() ]
1131 self.assertEquals("int", child_types[ 0])
1132 self.assertEquals("str", child_types[ 1])
1133 self.assertEquals("float", child_types[ 2])
1134 self.assertEquals("str", child_types[ 3])
1135 self.assertEquals("bool", child_types[ 4])
1136 self.assertEquals("NoneType", child_types[ 5])
1137 self.assertEquals(None, child_types[ 6])
1138 self.assertEquals("float", child_types[ 7])
1139 self.assertEquals("float", child_types[ 8])
1140 self.assertEquals("str", child_types[ 9])
1141 self.assertEquals("str", child_types[10])
1142 self.assertEquals("float", child_types[11])
1143 self.assertEquals("long", child_types[12])
1144 self.assertEquals(TREE_PYTYPE, child_types[13])
1145
1146 self.assertEquals("true", root.n.get(XML_SCHEMA_NIL_ATTR))
1147
1148 child_xsitypes = [ c.get(XML_SCHEMA_INSTANCE_TYPE_ATTR)
1149 for c in root.iterchildren() ]
1150
1151
1152 child_types = [ c.get(XML_SCHEMA_INSTANCE_TYPE_ATTR)
1153 for c in root.iterchildren() ]
1154 self.assertEquals("xsd:int", child_types[ 0])
1155 self.assertEquals("xsd:string", child_types[ 1])
1156 self.assertEquals("xsd:double", child_types[ 2])
1157 self.assertEquals("xsd:string", child_types[ 3])
1158 self.assertEquals("xsd:boolean", child_types[ 4])
1159 self.assertEquals(None, child_types[ 5])
1160 self.assertEquals(None, child_types[ 6])
1161 self.assertEquals("xsd:double", child_types[ 7])
1162 self.assertEquals("xsd:float", child_types[ 8])
1163 self.assertEquals("xsd:string", child_types[ 9])
1164 self.assertEquals("xsd:string", child_types[10])
1165 self.assertEquals("xsd:double", child_types[11])
1166 self.assertEquals("xsd:integer", child_types[12])
1167 self.assertEquals(None, child_types[13])
1168
1169 self.assertEquals("true", root.n.get(XML_SCHEMA_NIL_ATTR))
1170
1172 XML = self.XML
1173 root = XML(u'''\
1174 <a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1175 xmlns:py="http://codespeak.net/lxml/objectify/pytype">
1176 <b>5</b>
1177 <b>test</b>
1178 <c>1.1</c>
1179 <c>\uF8D2</c>
1180 <x>true</x>
1181 <n xsi:nil="true" />
1182 <n></n>
1183 <b xsi:type="double">5</b>
1184 <b xsi:type="float">5</b>
1185 <s xsi:type="string">23</s>
1186 <s py:pytype="str">42</s>
1187 <f py:pytype="float">300</f>
1188 <l py:pytype="long">2</l>
1189 <t py:pytype="TREE"></t>
1190 </a>
1191 ''')
1192 objectify.xsiannotate(root, ignore_old=False)
1193
1194 child_types = [ c.get(XML_SCHEMA_INSTANCE_TYPE_ATTR)
1195 for c in root.iterchildren() ]
1196 self.assertEquals("xsd:int", child_types[ 0])
1197 self.assertEquals("xsd:string", child_types[ 1])
1198 self.assertEquals("xsd:double", child_types[ 2])
1199 self.assertEquals("xsd:string", child_types[ 3])
1200 self.assertEquals("xsd:boolean", child_types[ 4])
1201 self.assertEquals(None, child_types[ 5])
1202 self.assertEquals(None, child_types[ 6])
1203 self.assertEquals("xsd:double", child_types[ 7])
1204 self.assertEquals("xsd:float", child_types[ 8])
1205 self.assertEquals("xsd:string", child_types[ 9])
1206 self.assertEquals("xsd:string", child_types[10])
1207 self.assertEquals("xsd:double", child_types[11])
1208 self.assertEquals("xsd:integer", child_types[12])
1209 self.assertEquals(None, child_types[13])
1210
1212 XML = self.XML
1213 root = XML(u'''\
1214 <a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1215 xmlns:py="http://codespeak.net/lxml/objectify/pytype">
1216 <b>5</b>
1217 <b>test</b>
1218 <c>1.1</c>
1219 <c>\uF8D2</c>
1220 <x>true</x>
1221 <n xsi:nil="true" />
1222 <n></n>
1223 <b xsi:type="double">5</b>
1224 <b xsi:type="float">5</b>
1225 <s xsi:type="string">23</s>
1226 <s py:pytype="str">42</s>
1227 <f py:pytype="float">300</f>
1228 <l py:pytype="long">2</l>
1229 <t py:pytype="TREE"></t>
1230 </a>
1231 ''')
1232 objectify.pyannotate(root, ignore_old=True)
1233
1234 child_types = [ c.get(objectify.PYTYPE_ATTRIBUTE)
1235 for c in root.iterchildren() ]
1236 self.assertEquals("int", child_types[ 0])
1237 self.assertEquals("str", child_types[ 1])
1238 self.assertEquals("float", child_types[ 2])
1239 self.assertEquals("str", child_types[ 3])
1240 self.assertEquals("bool", child_types[ 4])
1241 self.assertEquals("NoneType", child_types[ 5])
1242 self.assertEquals(None, child_types[ 6])
1243 self.assertEquals("float", child_types[ 7])
1244 self.assertEquals("float", child_types[ 8])
1245 self.assertEquals("str", child_types[ 9])
1246 self.assertEquals("int", child_types[10])
1247 self.assertEquals("int", child_types[11])
1248 self.assertEquals("int", child_types[12])
1249 self.assertEquals(None, child_types[13])
1250
1251 self.assertEquals("true", root.n.get(XML_SCHEMA_NIL_ATTR))
1252
1272
1274 XML = self.XML
1275 root = XML(u'''\
1276 <a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1277 xmlns:py="http://codespeak.net/lxml/objectify/pytype">
1278 <b>5</b>
1279 <b>test</b>
1280 <c>1.1</c>
1281 <c>\uF8D2</c>
1282 <x>true</x>
1283 <n xsi:nil="true" />
1284 <n></n>
1285 <b xsi:type="double">5</b>
1286 <b xsi:type="float">5</b>
1287 <s xsi:type="string">23</s>
1288 <s py:pytype="str">42</s>
1289 <f py:pytype="float">300</f>
1290 <l py:pytype="long">2</l>
1291 <t py:pytype="TREE"></t>
1292 </a>
1293 ''')
1294 objectify.pyannotate(root)
1295
1296 child_types = [ c.get(objectify.PYTYPE_ATTRIBUTE)
1297 for c in root.iterchildren() ]
1298 self.assertEquals("int", child_types[ 0])
1299 self.assertEquals("str", child_types[ 1])
1300 self.assertEquals("float", child_types[ 2])
1301 self.assertEquals("str", child_types[ 3])
1302 self.assertEquals("bool", child_types[ 4])
1303 self.assertEquals("NoneType", child_types[ 5])
1304 self.assertEquals(None, child_types[ 6])
1305 self.assertEquals("float", child_types[ 7])
1306 self.assertEquals("float", child_types[ 8])
1307 self.assertEquals("str", child_types[ 9])
1308 self.assertEquals("str", child_types[10])
1309 self.assertEquals("float", child_types[11])
1310 self.assertEquals("long", child_types[12])
1311 self.assertEquals(TREE_PYTYPE, child_types[13])
1312
1313 self.assertEquals("true", root.n.get(XML_SCHEMA_NIL_ATTR))
1314
1316 XML = self.XML
1317 root = XML(u'''\
1318 <a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1319 xmlns:py="http://codespeak.net/lxml/objectify/pytype">
1320 <b>5</b>
1321 <b>test</b>
1322 <c>1.1</c>
1323 <c>\uF8D2</c>
1324 <x>true</x>
1325 <n xsi:nil="true" />
1326 <n></n>
1327 <b xsi:type="double">5</b>
1328 <b xsi:type="float">5</b>
1329 <s xsi:type="string">23</s>
1330 <s py:pytype="str">42</s>
1331 <f py:pytype="float">300</f>
1332 <l py:pytype="long">2</l>
1333 <t py:pytype="TREE"></t>
1334 </a>
1335 ''')
1336 objectify.xsiannotate(root, ignore_old=True)
1337
1338 child_types = [ c.get(XML_SCHEMA_INSTANCE_TYPE_ATTR)
1339 for c in root.iterchildren() ]
1340 self.assertEquals("xsd:int", child_types[ 0])
1341 self.assertEquals("xsd:string", child_types[ 1])
1342 self.assertEquals("xsd:double", child_types[ 2])
1343 self.assertEquals("xsd:string", child_types[ 3])
1344 self.assertEquals("xsd:boolean", child_types[ 4])
1345 self.assertEquals(None, child_types[ 5])
1346 self.assertEquals(None, child_types[ 6])
1347 self.assertEquals("xsd:int", child_types[ 7])
1348 self.assertEquals("xsd:int", child_types[ 8])
1349 self.assertEquals("xsd:int", child_types[ 9])
1350 self.assertEquals("xsd:string", child_types[10])
1351 self.assertEquals("xsd:double", child_types[11])
1352 self.assertEquals("xsd:integer", child_types[12])
1353 self.assertEquals(None, child_types[13])
1354
1355 self.assertEquals("true", root.n.get(XML_SCHEMA_NIL_ATTR))
1356
1358 XML = self.XML
1359 root = XML(u'''\
1360 <a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1361 xmlns:py="http://codespeak.net/lxml/objectify/pytype">
1362 <b>5</b>
1363 <b>test</b>
1364 <c>1.1</c>
1365 <c>\uF8D2</c>
1366 <x>true</x>
1367 <n xsi:nil="true" />
1368 <n></n>
1369 <b xsi:type="double">5</b>
1370 <b xsi:type="float">5</b>
1371 <s xsi:type="string">23</s>
1372 <s py:pytype="str">42</s>
1373 <f py:pytype="float">300</f>
1374 <l py:pytype="long">2</l>
1375 <t py:pytype="TREE"></t>
1376 </a>
1377 ''')
1378 objectify.deannotate(root)
1379
1380 for c in root.getiterator():
1381 self.assertEquals(None, c.get(XML_SCHEMA_INSTANCE_TYPE_ATTR))
1382 self.assertEquals(None, c.get(objectify.PYTYPE_ATTRIBUTE))
1383
1384 self.assertEquals("true", root.n.get(XML_SCHEMA_NIL_ATTR))
1385
1387 XML = self.XML
1388 root = XML(u'''\
1389 <a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1390 xmlns:py="http://codespeak.net/lxml/objectify/pytype">
1391 <b>5</b>
1392 <b>test</b>
1393 <c>1.1</c>
1394 <c>\uF8D2</c>
1395 <x>true</x>
1396 <n xsi:nil="true" />
1397 <n></n>
1398 <b xsi:type="double">5</b>
1399 <b xsi:type="float">5</b>
1400 <s xsi:type="string">23</s>
1401 <s py:pytype="str">42</s>
1402 <f py:pytype="float">300</f>
1403 <l py:pytype="long">2</l>
1404 <t py:pytype="TREE"></t>
1405 </a>
1406 ''')
1407 objectify.xsiannotate(root)
1408 objectify.deannotate(root, xsi=False)
1409
1410 child_types = [ c.get(XML_SCHEMA_INSTANCE_TYPE_ATTR)
1411 for c in root.iterchildren() ]
1412 self.assertEquals("xsd:int", child_types[ 0])
1413 self.assertEquals("xsd:string", child_types[ 1])
1414 self.assertEquals("xsd:double", child_types[ 2])
1415 self.assertEquals("xsd:string", child_types[ 3])
1416 self.assertEquals("xsd:boolean", child_types[ 4])
1417 self.assertEquals(None, child_types[ 5])
1418 self.assertEquals(None, child_types[ 6])
1419 self.assertEquals("xsd:int", child_types[ 7])
1420 self.assertEquals("xsd:int", child_types[ 8])
1421 self.assertEquals("xsd:int", child_types[ 9])
1422 self.assertEquals("xsd:string", child_types[10])
1423 self.assertEquals("xsd:double", child_types[11])
1424 self.assertEquals("xsd:integer", child_types[12])
1425 self.assertEquals(None, child_types[13])
1426
1427 self.assertEquals("true", root.n.get(XML_SCHEMA_NIL_ATTR))
1428
1429 for c in root.getiterator():
1430 self.assertEquals(None, c.get(objectify.PYTYPE_ATTRIBUTE))
1431
1433 XML = self.XML
1434 root = XML(u'''\
1435 <a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1436 xmlns:py="http://codespeak.net/lxml/objectify/pytype"
1437 xmlns:xsd="http://www.w3.org/2001/XMLSchema">
1438 <b>5</b>
1439 <b>test</b>
1440 <c>1.1</c>
1441 <c>\uF8D2</c>
1442 <x>true</x>
1443 <n xsi:nil="true" />
1444 <n></n>
1445 <b xsi:type="xsd:double">5</b>
1446 <b xsi:type="xsd:float">5</b>
1447 <s xsi:type="xsd:string">23</s>
1448 <s py:pytype="str">42</s>
1449 <f py:pytype="float">300</f>
1450 <l py:pytype="long">2</l>
1451 <t py:pytype="TREE"></t>
1452 </a>
1453 ''')
1454 objectify.annotate(root)
1455 objectify.deannotate(root, pytype=False)
1456
1457 child_types = [ c.get(objectify.PYTYPE_ATTRIBUTE)
1458 for c in root.iterchildren() ]
1459 self.assertEquals("int", child_types[ 0])
1460 self.assertEquals("str", child_types[ 1])
1461 self.assertEquals("float", child_types[ 2])
1462 self.assertEquals("str", child_types[ 3])
1463 self.assertEquals("bool", child_types[ 4])
1464 self.assertEquals("NoneType", child_types[ 5])
1465 self.assertEquals(None, child_types[ 6])
1466 self.assertEquals("float", child_types[ 7])
1467 self.assertEquals("float", child_types[ 8])
1468 self.assertEquals("str", child_types[ 9])
1469 self.assertEquals("int", child_types[10])
1470 self.assertEquals("int", child_types[11])
1471 self.assertEquals("int", child_types[12])
1472 self.assertEquals(None, child_types[13])
1473
1474 self.assertEquals("true", root.n.get(XML_SCHEMA_NIL_ATTR))
1475
1476 for c in root.getiterator():
1477 self.assertEquals(None, c.get(XML_SCHEMA_INSTANCE_TYPE_ATTR))
1478
1480 XML = self.XML
1481 root = XML(u'''\
1482 <a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1483 xmlns:py="http://codespeak.net/lxml/objectify/pytype"
1484 xmlns:xsd="http://www.w3.org/2001/XMLSchema">
1485 <b xsi:type="xsd:int">5</b>
1486 <b xsi:type="xsd:string">test</b>
1487 <c xsi:type="xsd:float">1.1</c>
1488 <c xsi:type="xsd:string">\uF8D2</c>
1489 <x xsi:type="xsd:boolean">true</x>
1490 <n xsi:nil="true" />
1491 <n></n>
1492 <b xsi:type="xsd:double">5</b>
1493 <b xsi:type="xsd:float">5</b>
1494 <s xsi:type="xsd:string">23</s>
1495 <s xsi:type="xsd:string">42</s>
1496 <f xsi:type="xsd:float">300</f>
1497 <l xsi:type="xsd:long">2</l>
1498 <t py:pytype="TREE"></t>
1499 </a>
1500 ''')
1501 objectify.annotate(root)
1502 objectify.deannotate(root, xsi=False)
1503
1504 child_types = [ c.get(XML_SCHEMA_INSTANCE_TYPE_ATTR)
1505 for c in root.iterchildren() ]
1506 self.assertEquals("xsd:int", child_types[ 0])
1507 self.assertEquals("xsd:string", child_types[ 1])
1508 self.assertEquals("xsd:float", child_types[ 2])
1509 self.assertEquals("xsd:string", child_types[ 3])
1510 self.assertEquals("xsd:boolean", child_types[ 4])
1511 self.assertEquals(None, child_types[ 5])
1512 self.assertEquals(None, child_types[ 6])
1513 self.assertEquals("xsd:double", child_types[ 7])
1514 self.assertEquals("xsd:float", child_types[ 8])
1515 self.assertEquals("xsd:string", child_types[ 9])
1516 self.assertEquals("xsd:string", child_types[10])
1517 self.assertEquals("xsd:float", child_types[11])
1518 self.assertEquals("xsd:long", child_types[12])
1519 self.assertEquals(None, child_types[13])
1520
1521 self.assertEquals("true", root.n.get(XML_SCHEMA_NIL_ATTR))
1522
1523 for c in root.getiterator():
1524 self.assertEquals(None, c.get(objectify.PYTYPE_ATTRIBUTE))
1525
1527 XML = self.XML
1528
1529 xml = u'''\
1530 <a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
1531 <b>5</b>
1532 <b>test</b>
1533 <c>1.1</c>
1534 <c>\uF8D2</c>
1535 <x>true</x>
1536 <n xsi:nil="true" />
1537 <n></n>
1538 <b xsi:type="double">5</b>
1539 </a>
1540 '''
1541
1542 pytype_ns, pytype_name = objectify.PYTYPE_ATTRIBUTE[1:].split('}')
1543 objectify.setPytypeAttributeTag("{TEST}test")
1544
1545 root = XML(xml)
1546 objectify.annotate(root)
1547
1548 attribs = root.xpath("//@py:%s" % pytype_name, {"py" : pytype_ns})
1549 self.assertEquals(0, len(attribs))
1550 attribs = root.xpath("//@py:test", {"py" : "TEST"})
1551 self.assertEquals(7, len(attribs))
1552
1553 objectify.setPytypeAttributeTag()
1554 pytype_ns, pytype_name = objectify.PYTYPE_ATTRIBUTE[1:].split('}')
1555
1556 self.assertNotEqual("test", pytype_ns.lower())
1557 self.assertNotEqual("test", pytype_name.lower())
1558
1559 root = XML(xml)
1560 attribs = root.xpath("//@py:%s" % pytype_name, {"py" : pytype_ns})
1561 self.assertEquals(0, len(attribs))
1562
1563 objectify.annotate(root)
1564 attribs = root.xpath("//@py:%s" % pytype_name, {"py" : pytype_ns})
1565 self.assertEquals(7, len(attribs))
1566
1576
1577 def checkMyType(s):
1578 return True
1579
1580 pytype = objectify.PyType("mytype", checkMyType, NewType)
1581 pytype.register()
1582 self.assert_(pytype in objectify.getRegisteredTypes())
1583 pytype.unregister()
1584
1585 pytype.register(before = [objectify.getRegisteredTypes()[0].name])
1586 self.assertEquals(pytype, objectify.getRegisteredTypes()[0])
1587 pytype.unregister()
1588
1589 pytype.register(after = [objectify.getRegisteredTypes()[0].name])
1590 self.assertNotEqual(pytype, objectify.getRegisteredTypes()[0])
1591 pytype.unregister()
1592
1593 self.assertRaises(ValueError, pytype.register,
1594 before = [objectify.getRegisteredTypes()[0].name],
1595 after = [objectify.getRegisteredTypes()[1].name])
1596
1597 finally:
1598 for pytype in objectify.getRegisteredTypes():
1599 pytype.unregister()
1600 for pytype in orig_types:
1601 pytype.register()
1602
1608
1614
1620
1628
1647
1652
1657
1662
1667
1687
1689 root = self.XML(xml_str)
1690 path = objectify.ObjectPath( ['root', 'c1[0]', 'c2[0]'] )
1691 self.assertEquals(root.c1.c2.text, path(root).text)
1692
1693 path = objectify.ObjectPath( ['root', 'c1[0]', 'c2[2]'] )
1694 self.assertEquals(root.c1.c2[2].text, path(root).text)
1695
1696 path = objectify.ObjectPath( ['root', 'c1', 'c2[2]'] )
1697 self.assertEquals(root.c1.c2[2].text, path(root).text)
1698
1699 path = objectify.ObjectPath( ['root', 'c1', 'c2[-1]'] )
1700 self.assertEquals(root.c1.c2[-1].text, path(root).text)
1701
1702 path = objectify.ObjectPath( ['root', 'c1', 'c2[-3]'] )
1703 self.assertEquals(root.c1.c2[-3].text, path(root).text)
1704
1706 self.assertRaises(ValueError, objectify.ObjectPath,
1707 "root.c1[0].c2[-1-2]")
1708 self.assertRaises(ValueError, objectify.ObjectPath,
1709 ['root', 'c1[0]', 'c2[-1-2]'])
1710
1711 self.assertRaises(ValueError, objectify.ObjectPath,
1712 "root[2].c1.c2")
1713 self.assertRaises(ValueError, objectify.ObjectPath,
1714 ['root[2]', 'c1', 'c2'])
1715
1716 self.assertRaises(ValueError, objectify.ObjectPath,
1717 [])
1718 self.assertRaises(ValueError, objectify.ObjectPath,
1719 ['', '', ''])
1720
1722 root = self.XML(xml_str)
1723 path = objectify.ObjectPath("root.c1[9999].c2")
1724 self.assertRaises(AttributeError, path, root)
1725
1726 path = objectify.ObjectPath("root.c1[0].c2[9999]")
1727 self.assertRaises(AttributeError, path, root)
1728
1729 path = objectify.ObjectPath(".c1[9999].c2[0]")
1730 self.assertRaises(AttributeError, path, root)
1731
1732 path = objectify.ObjectPath("root.c1[-2].c2")
1733 self.assertRaises(AttributeError, path, root)
1734
1735 path = objectify.ObjectPath("root.c1[0].c2[-4]")
1736 self.assertRaises(AttributeError, path, root)
1737
1751
1753 root = self.XML(xml_str)
1754 path = objectify.ObjectPath( ['{objectified}root', 'c1', 'c2'] )
1755 self.assertEquals(root.c1.c2.text, path.find(root).text)
1756 path = objectify.ObjectPath( ['{objectified}root', '{objectified}c1', 'c2'] )
1757 self.assertEquals(root.c1.c2.text, path.find(root).text)
1758 path = objectify.ObjectPath( ['root', '{objectified}c1', '{objectified}c2'] )
1759 self.assertEquals(root.c1.c2.text, path.find(root).text)
1760 path = objectify.ObjectPath( ['root', '{objectified}c1', '{objectified}c2[2]'] )
1761 self.assertEquals(root.c1.c2[2].text, path.find(root).text)
1762 path = objectify.ObjectPath( ['root', 'c1', '{objectified}c2'] )
1763 self.assertEquals(root.c1.c2.text, path.find(root).text)
1764 path = objectify.ObjectPath( ['root', 'c1', '{objectified}c2[2]'] )
1765 self.assertEquals(root.c1.c2[2].text, path.find(root).text)
1766 path = objectify.ObjectPath( ['root', 'c1', '{otherNS}c2'] )
1767 self.assertEquals(getattr(root.c1, '{otherNS}c2').text,
1768 path.find(root).text)
1769
1782
1797
1809
1823
1825 root = self.XML(xml_str)
1826 path = objectify.ObjectPath( "root.c1.c99" )
1827 self.assertRaises(AttributeError, path.find, root)
1828
1829 new_el = self.Element("{objectified}test")
1830 new_el.a = ["TEST1", "TEST2"]
1831 new_el.a[0].set("myattr", "ATTR1")
1832 new_el.a[1].set("myattr", "ATTR2")
1833
1834 path.setattr(root, list(new_el.a))
1835
1836 self.assertEquals(2, len(root.c1.c99))
1837 self.assertEquals("ATTR1", root.c1.c99[0].get("myattr"))
1838 self.assertEquals("TEST1", root.c1.c99[0].text)
1839 self.assertEquals("ATTR2", root.c1.c99[1].get("myattr"))
1840 self.assertEquals("TEST2", root.c1.c99[1].text)
1841 self.assertEquals("TEST1", path(root).text)
1842
1851
1865
1877
1891
1906
1908 root = self.XML(xml_str)
1909 self.assertEquals(
1910 ['{objectified}root', '{objectified}root.c1',
1911 '{objectified}root.c1.c2',
1912 '{objectified}root.c1.c2[1]', '{objectified}root.c1.c2[2]',
1913 '{objectified}root.c1.{otherNS}c2', '{objectified}root.c1.{}c2'],
1914 root.descendantpaths())
1915
1917 root = self.XML(xml_str)
1918 self.assertEquals(
1919 ['{objectified}c1', '{objectified}c1.c2',
1920 '{objectified}c1.c2[1]', '{objectified}c1.c2[2]',
1921 '{objectified}c1.{otherNS}c2', '{objectified}c1.{}c2'],
1922 root.c1.descendantpaths())
1923
1925 root = self.XML(xml_str)
1926 self.assertEquals(
1927 ['root.{objectified}c1', 'root.{objectified}c1.c2',
1928 'root.{objectified}c1.c2[1]', 'root.{objectified}c1.c2[2]',
1929 'root.{objectified}c1.{otherNS}c2',
1930 'root.{objectified}c1.{}c2'],
1931 root.c1.descendantpaths('root'))
1932
1944
1945
1946
1951
1956
1961
1966
1971
1976
1981
1986
1991
1993 E = objectify.E
1994 DataElement = objectify.DataElement
1995 root = E.root("text", E.sub(E.subsub()), "tail", DataElement(1),
1996 DataElement(2.0))
1997 self.assert_(isinstance(root, objectify.ObjectifiedElement))
1998 self.assertEquals(root.text, "text")
1999 self.assert_(isinstance(root.sub, objectify.ObjectifiedElement))
2000 self.assertEquals(root.sub.tail, "tail")
2001 self.assert_(isinstance(root.sub.subsub, objectify.StringElement))
2002 self.assertEquals(len(root.value), 2)
2003 self.assert_(isinstance(root.value[0], objectify.IntElement))
2004 self.assert_(isinstance(root.value[1], objectify.FloatElement))
2005
2007 suite = unittest.TestSuite()
2008 suite.addTests([unittest.makeSuite(ObjectifyTestCase)])
2009 suite.addTests(
2010 [doctest.DocFileSuite('../../../doc/objectify.txt')])
2011 return suite
2012
2013 if __name__ == '__main__':
2014 print 'to test use test.py %s' % __file__
2015