11from __future__import absolute_import ,division ,unicode_literals
2- from six import text_type
2+ from six import text_type , string_types
33
44import gettext
55_ = gettext .gettext
88spaceCharacters = "" .join (spaceCharacters )
99
1010
11+ def to_text (s ,blank_if_none = True ):
12+ """Wrapper around six.text_type to convert None to empty string"""
13+ if s is None :
14+ if blank_if_none :
15+ return ""
16+ else :
17+ return None
18+ elif isinstance (s ,text_type ):
19+ return s
20+ else :
21+ return text_type (s )
22+
23+
24+ def is_text_or_none (string ):
25+ """Wrapper around isinstance(string_types) or is None"""
26+ return string is None or isinstance (string ,string_types )
27+
28+
1129class TreeWalker (object ):
1230def __init__ (self ,tree ):
1331self .tree = tree
@@ -19,45 +37,47 @@ def error(self, msg):
1937return {"type" :"SerializeError" ,"data" :msg }
2038
2139def emptyTag (self ,namespace ,name ,attrs ,hasChildren = False ):
22- assert namespace is None or isinstance (namespace ,text_type ),type (namespace )
23- assert isinstance (name ,text_type ),type (name )
24- assert all ((namespace is None or isinstance (namespace ,text_type ))and
25- isinstance (name ,text_type )and
26- isinstance (value ,text_type )
40+ assert namespace is None or isinstance (namespace ,string_types ),type (namespace )
41+ assert isinstance (name ,string_types ),type (name )
42+ assert all ((namespace is None or isinstance (namespace ,string_types ))and
43+ isinstance (name ,string_types )and
44+ isinstance (value ,string_types )
2745for (namespace ,name ),value in attrs .items ())
2846
29- yield {"type" :"EmptyTag" ,"name" :name ,
30- "namespace" :namespace ,
47+ yield {"type" :"EmptyTag" ,"name" :to_text ( name , False ) ,
48+ "namespace" :to_text ( namespace ) ,
3149"data" :attrs }
3250if hasChildren :
3351yield self .error (_ ("Void element has children" ))
3452
3553def startTag (self ,namespace ,name ,attrs ):
36- assert namespace is None or isinstance (namespace ,text_type ),type (namespace )
37- assert isinstance (name ,text_type ),type (name )
38- assert all ((namespace is None or isinstance (namespace ,text_type ))and
39- isinstance (name ,text_type )and
40- isinstance (value ,text_type )
54+ assert namespace is None or isinstance (namespace ,string_types ),type (namespace )
55+ assert isinstance (name ,string_types ),type (name )
56+ assert all ((namespace is None or isinstance (namespace ,string_types ))and
57+ isinstance (name ,string_types )and
58+ isinstance (value ,string_types )
4159for (namespace ,name ),value in attrs .items ())
4260
4361return {"type" :"StartTag" ,
44- "name" :name ,
45- "namespace" :namespace ,
46- "data" :attrs }
62+ "name" :text_type (name ),
63+ "namespace" :to_text (namespace ),
64+ "data" :dict (((to_text (namespace ,False ),to_text (name )),
65+ to_text (value ,False ))
66+ for (namespace ,name ),value in attrs .items ())}
4767
4868def endTag (self ,namespace ,name ):
49- assert namespace is None or isinstance (namespace ,text_type ),type (namespace )
50- assert isinstance (name ,text_type ),type (namespace )
69+ assert namespace is None or isinstance (namespace ,string_types ),type (namespace )
70+ assert isinstance (name ,string_types ),type (namespace )
5171
5272return {"type" :"EndTag" ,
53- "name" :name ,
54- "namespace" :namespace ,
73+ "name" :to_text ( name , False ) ,
74+ "namespace" :to_text ( namespace ) ,
5575"data" : {}}
5676
5777def text (self ,data ):
58- assert isinstance (data ,text_type ),type (data )
78+ assert isinstance (data ,string_types ),type (data )
5979
60- data = data
80+ data = to_text ( data )
6181middle = data .lstrip (spaceCharacters )
6282left = data [:len (data )- len (middle )]
6383if left :
@@ -71,25 +91,25 @@ def text(self, data):
7191yield {"type" :"SpaceCharacters" ,"data" :right }
7292
7393def comment (self ,data ):
74- assert isinstance (data ,text_type ),type (data )
94+ assert isinstance (data ,string_types ),type (data )
7595
76- return {"type" :"Comment" ,"data" :data }
96+ return {"type" :"Comment" ,"data" :text_type ( data ) }
7797
7898def doctype (self ,name ,publicId = None ,systemId = None ,correct = True ):
79- assert name is None or isinstance (name , text_type ),type (name )
80- assert publicId is None or isinstance (publicId , text_type ),type (publicId )
81- assert systemId is None or isinstance (systemId , text_type ),type (systemId )
99+ assert is_text_or_none (name ),type (name )
100+ assert is_text_or_none (publicId ),type (publicId )
101+ assert is_text_or_none (systemId ),type (systemId )
82102
83103return {"type" :"Doctype" ,
84- "name" :name if name is not None else "" ,
85- "publicId" :publicId ,
86- "systemId" :systemId ,
87- "correct" :correct }
104+ "name" :to_text ( name ) ,
105+ "publicId" :to_text ( publicId ) ,
106+ "systemId" :to_text ( systemId ) ,
107+ "correct" :to_text ( correct ) }
88108
89109def entity (self ,name ):
90- assert isinstance (name ,text_type ),type (name )
110+ assert isinstance (name ,string_types ),type (name )
91111
92- return {"type" :"Entity" ,"name" :name }
112+ return {"type" :"Entity" ,"name" :text_type ( name ) }
93113
94114def unknown (self ,nodeType ):
95115return self .error (_ ("Unknown node type: " )+ nodeType )