1
1
from __future__import absolute_import ,division ,unicode_literals
2
- from six import text_type
2
+ from six import text_type , string_types
3
3
4
4
import gettext
5
5
_ = gettext .gettext
8
8
spaceCharacters = "" .join (spaceCharacters )
9
9
10
10
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
+
11
29
class TreeWalker (object ):
12
30
def __init__ (self ,tree ):
13
31
self .tree = tree
@@ -19,45 +37,47 @@ def error(self, msg):
19
37
return {"type" :"SerializeError" ,"data" :msg }
20
38
21
39
def 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 )
27
45
for (namespace ,name ),value in attrs .items ())
28
46
29
- yield {"type" :"EmptyTag" ,"name" :name ,
30
- "namespace" :namespace ,
47
+ yield {"type" :"EmptyTag" ,"name" :to_text ( name , False ) ,
48
+ "namespace" :to_text ( namespace ) ,
31
49
"data" :attrs }
32
50
if hasChildren :
33
51
yield self .error (_ ("Void element has children" ))
34
52
35
53
def 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 )
41
59
for (namespace ,name ),value in attrs .items ())
42
60
43
61
return {"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 ())}
47
67
48
68
def 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 )
51
71
52
72
return {"type" :"EndTag" ,
53
- "name" :name ,
54
- "namespace" :namespace ,
73
+ "name" :to_text ( name , False ) ,
74
+ "namespace" :to_text ( namespace ) ,
55
75
"data" : {}}
56
76
57
77
def text (self ,data ):
58
- assert isinstance (data ,text_type ),type (data )
78
+ assert isinstance (data ,string_types ),type (data )
59
79
60
- data = data
80
+ data = to_text ( data )
61
81
middle = data .lstrip (spaceCharacters )
62
82
left = data [:len (data )- len (middle )]
63
83
if left :
@@ -71,25 +91,25 @@ def text(self, data):
71
91
yield {"type" :"SpaceCharacters" ,"data" :right }
72
92
73
93
def comment (self ,data ):
74
- assert isinstance (data ,text_type ),type (data )
94
+ assert isinstance (data ,string_types ),type (data )
75
95
76
- return {"type" :"Comment" ,"data" :data }
96
+ return {"type" :"Comment" ,"data" :text_type ( data ) }
77
97
78
98
def 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 )
82
102
83
103
return {"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 ) }
88
108
89
109
def entity (self ,name ):
90
- assert isinstance (name ,text_type ),type (name )
110
+ assert isinstance (name ,string_types ),type (name )
91
111
92
- return {"type" :"Entity" ,"name" :name }
112
+ return {"type" :"Entity" ,"name" :text_type ( name ) }
93
113
94
114
def unknown (self ,nodeType ):
95
115
return self .error (_ ("Unknown node type: " )+ nodeType )