10
10
integer_types ,
11
11
)
12
12
from tarantool .error import (
13
+ Error ,
13
14
SchemaError ,
14
15
DatabaseError
15
16
)
16
17
import tarantool .const as const
17
18
18
19
20
+ class RecursionError (Error ):
21
+ """Report the situation when max recursion depth is reached.
22
+
23
+ This is internal error for <to_unicode_recursive> caller
24
+ and it should be re-raised properly be the caller.
25
+ """
26
+
27
+
28
+ def to_unicode (s ):
29
+ if isinstance (s , bytes ):
30
+ return s .decode (encoding = 'utf-8' )
31
+ return s
32
+
33
+
34
+ def to_unicode_recursive (x , max_depth ):
35
+ """Same as to_unicode(), but traverses over dictionaries,
36
+ lists and tuples recursivery.
37
+
38
+ x: value to convert
39
+
40
+ max_depth: 1 accepts a scalar, 2 accepts a list of scalars,
41
+ etc.
42
+ """
43
+ if max_depth <= 0 :
44
+ raise RecursionError ('Max recursion depth is reached' )
45
+
46
+ if isinstance (x , dict ):
47
+ res = dict ()
48
+ for key , val in x .items ():
49
+ key = to_unicode_recursive (key , max_depth - 1 )
50
+ val = to_unicode_recursive (val , max_depth - 1 )
51
+ res [key ] = val
52
+ return res
53
+
54
+ if isinstance (x , list ) or isinstance (x , tuple ):
55
+ res = []
56
+ for val in x :
57
+ val = to_unicode_recursive (val , max_depth - 1 )
58
+ res .append (val )
59
+ if isinstance (x , tuple ):
60
+ return tuple (res )
61
+ return res
62
+
63
+ return to_unicode (x )
64
+
65
+
19
66
class SchemaIndex (object ):
20
67
def __init__ (self , index_row , space ):
21
68
self .iid = index_row [1 ]
22
69
self .name = index_row [2 ]
23
- if isinstance (self .name , bytes ):
24
- self .name = self .name .decode ()
70
+ self .name = to_unicode (index_row [2 ])
25
71
self .index = index_row [3 ]
26
72
self .unique = index_row [4 ]
27
73
self .parts = []
28
- if isinstance (index_row [5 ], (list , tuple )):
29
- for val in index_row [5 ]:
74
+ try :
75
+ parts_raw = to_unicode_recursive (index_row [5 ], 3 )
76
+ except RecursionError as e :
77
+ errmsg = 'Unexpected index parts structure: ' + str (e )
78
+ raise SchemaError (errmsg )
79
+ if isinstance (parts_raw , (list , tuple )):
80
+ for val in parts_raw :
30
81
if isinstance (val , dict ):
31
82
self .parts .append ((val ['field' ], val ['type' ]))
32
83
else :
33
84
self .parts .append ((val [0 ], val [1 ]))
34
85
else :
35
- for i in range (index_row [ 5 ] ):
86
+ for i in range (parts_raw ):
36
87
self .parts .append ((
37
- index_row [5 + 1 + i * 2 ],
38
- index_row [5 + 2 + i * 2 ]
88
+ to_unicode ( index_row [5 + 1 + i * 2 ]) ,
89
+ to_unicode ( index_row [5 + 2 + i * 2 ])
39
90
))
40
91
self .space = space
41
92
self .space .indexes [self .iid ] = self
@@ -52,16 +103,19 @@ class SchemaSpace(object):
52
103
def __init__ (self , space_row , schema ):
53
104
self .sid = space_row [0 ]
54
105
self .arity = space_row [1 ]
55
- self .name = space_row [2 ]
56
- if isinstance (self .name , bytes ):
57
- self .name = self .name .decode ()
106
+ self .name = to_unicode (space_row [2 ])
58
107
self .indexes = {}
59
108
self .schema = schema
60
109
self .schema [self .sid ] = self
61
110
if self .name :
62
111
self .schema [self .name ] = self
63
112
self .format = dict ()
64
- for part_id , part in enumerate (space_row [6 ]):
113
+ try :
114
+ format_raw = to_unicode_recursive (space_row [6 ], 3 )
115
+ except RecursionError as e :
116
+ errmsg = 'Unexpected space format structure: ' + str (e )
117
+ raise SchemaError (errmsg )
118
+ for part_id , part in enumerate (format_raw ):
65
119
part ['id' ] = part_id
66
120
self .format [part ['name' ]] = part
67
121
self .format [part_id ] = part
@@ -78,6 +132,8 @@ def __init__(self, con):
78
132
self .con = con
79
133
80
134
def get_space (self , space ):
135
+ space = to_unicode (space )
136
+
81
137
try :
82
138
return self .schema [space ]
83
139
except KeyError :
@@ -135,6 +191,9 @@ def fetch_space_all(self):
135
191
SchemaSpace (row , self .schema )
136
192
137
193
def get_index (self , space , index ):
194
+ space = to_unicode (space )
195
+ index = to_unicode (index )
196
+
138
197
_space = self .get_space (space )
139
198
try :
140
199
return _space .indexes [index ]
@@ -203,6 +262,9 @@ def fetch_index_from(self, space, index):
203
262
return index_row
204
263
205
264
def get_field (self , space , field ):
265
+ space = to_unicode (space )
266
+ field = to_unicode (field )
267
+
206
268
_space = self .get_space (space )
207
269
try :
208
270
return _space .format [field ]
0 commit comments