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 )
0 commit comments