3
3
import struct
4
4
5
5
from pymysqlreplication import constants , event , row_event
6
+ from typing import List , Tuple , Any , Dict , Optional , Union
6
7
7
8
# Constants from PyMYSQL source code
8
9
NULL_COLUMN = 251
36
37
JSONB_LITERAL_FALSE = 0x2
37
38
38
39
39
- def read_offset_or_inline (packet , large ) :
40
+ def read_offset_or_inline (packet , large : bool ) -> Tuple [ Any , Any , Any ] :
40
41
t = packet .read_uint8 ()
41
42
42
43
if t in (JSONB_TYPE_LITERAL ,
43
44
JSONB_TYPE_INT16 , JSONB_TYPE_UINT16 ):
44
- return ( t , None , packet .read_binary_json_type_inlined (t , large ) )
45
+ return t , None , packet .read_binary_json_type_inlined (t , large )
45
46
if large and t in (JSONB_TYPE_INT32 , JSONB_TYPE_UINT32 ):
46
- return ( t , None , packet .read_binary_json_type_inlined (t , large ) )
47
+ return t , None , packet .read_binary_json_type_inlined (t , large )
47
48
48
49
if large :
49
- return ( t , packet .read_uint32 (), None )
50
- return ( t , packet .read_uint16 (), None )
50
+ return t , packet .read_uint32 (), None
51
+ return t , packet .read_uint16 (), None
51
52
52
53
53
54
class BinLogPacketWrapper (object ):
54
55
"""
55
- Bin Log Packet Wrapper. It uses an existing packet object, and wraps
56
- around it, exposing useful variables while still providing access
56
+ Bin Log Packet Wrapper uses an existing packet object and wraps around it,
57
+ exposing useful variables while still providing access
57
58
to the original packet objects variables and methods.
58
59
"""
59
60
@@ -155,7 +156,7 @@ def __init__(self, from_packet, table_map,
155
156
if self .event ._processed == False :
156
157
self .event = None
157
158
158
- def read (self , size ) :
159
+ def read (self , size : int ) -> Union [ int , bytes ] :
159
160
size = int (size )
160
161
self .read_bytes += size
161
162
if len (self .__data_buffer ) > 0 :
@@ -167,14 +168,15 @@ def read(self, size):
167
168
return data + self .packet .read (size - len (data ))
168
169
return self .packet .read (size )
169
170
170
- def unread (self , data ):
171
- '''Push again data in data buffer. It's use when you want
172
- to extract a bit from a value a let the rest of the code normally
173
- read the datas'''
171
+ def unread (self , data : str ):
172
+ """
173
+ Push again data in data buffer.
174
+ Use to extract a bit from a value and ensure that the rest of the code reads data normally
175
+ """
174
176
self .read_bytes -= len (data )
175
177
self .__data_buffer += data
176
178
177
- def advance (self , size ):
179
+ def advance (self , size : int ):
178
180
size = int (size )
179
181
self .read_bytes += size
180
182
buffer_len = len (self .__data_buffer )
@@ -185,13 +187,11 @@ def advance(self, size):
185
187
else :
186
188
self .packet .advance (size )
187
189
188
- def read_length_coded_binary (self ):
189
- """Read a 'Length Coded Binary' number from the data buffer.
190
-
190
+ def read_length_coded_binary (self ) -> Optional [ str ] :
191
+ """
192
+ Read a 'Length Coded Binary' number from the data buffer.
191
193
Length coded numbers can be anywhere from 1 to 9 bytes depending
192
- on the value of the first byte.
193
-
194
- From PyMYSQL source code
194
+ on the value of the first byte. (From PyMYSQL source code)
195
195
"""
196
196
c = struct .unpack ("!B" , self .read (1 ))[0 ]
197
197
if c == NULL_COLUMN :
@@ -205,14 +205,12 @@ def read_length_coded_binary(self):
205
205
elif c == UNSIGNED_INT64_COLUMN :
206
206
return self .unpack_int64 (self .read (UNSIGNED_INT64_LENGTH ))
207
207
208
- def read_length_coded_string (self ):
209
- """Read a 'Length Coded String' from the data buffer.
210
-
211
- A 'Length Coded String' consists first of a length coded
212
- (unsigned, positive) integer represented in 1-9 bytes followed by
213
- that many bytes of binary data. (For example "cat" would be "3cat".)
214
-
215
- From PyMYSQL source code
208
+ def read_length_coded_string (self ) -> Optional [str ]:
209
+ """
210
+ Read a 'Length Coded String' from the data buffer.
211
+ A 'Length Coded String' consists first of a length coded (unsigned, positive) integer
212
+ represented in 1-9 bytes followed by that many bytes of binary data.
213
+ (For example, "cat" would be "3cat". - From PyMYSQL source code)
216
214
"""
217
215
length = self .read_length_coded_binary ()
218
216
if length is None :
@@ -226,8 +224,10 @@ def __getattr__(self, key):
226
224
raise AttributeError ("%s instance has no attribute '%s'" %
227
225
(self .__class__ , key ))
228
226
229
- def read_int_be_by_size (self , size ):
230
- '''Read a big endian integer values based on byte number'''
227
+ def read_int_be_by_size (self , size : int ):
228
+ """
229
+ Read a big endian integer values based on byte number
230
+ """
231
231
if size == 1 :
232
232
return struct .unpack ('>b' , self .read (size ))[0 ]
233
233
elif size == 2 :
@@ -241,8 +241,10 @@ def read_int_be_by_size(self, size):
241
241
elif size == 8 :
242
242
return struct .unpack ('>l' , self .read (size ))[0 ]
243
243
244
- def read_uint_by_size (self , size ):
245
- '''Read a little endian integer values based on byte number'''
244
+ def read_uint_by_size (self , size : int ) -> str :
245
+ """
246
+ Read a little endian integer values based on byte number
247
+ """
246
248
if size == 1 :
247
249
return self .read_uint8 ()
248
250
elif size == 2 :
@@ -260,19 +262,18 @@ def read_uint_by_size(self, size):
260
262
elif size == 8 :
261
263
return self .read_uint64 ()
262
264
263
- def read_length_coded_pascal_string (self , size ):
264
- """Read a string with length coded using pascal style.
265
+ def read_length_coded_pascal_string (self , size : int ) -> Union [int , bytes ]:
266
+ """
267
+ Read a string with length coded using pascal style.
265
268
The string start by the size of the string
266
269
"""
267
270
length = self .read_uint_by_size (size )
268
271
return self .read (length )
269
272
270
- def read_variable_length_string (self ):
271
- """Read a variable length string where the first 1-5 bytes stores the
272
- length of the string.
273
-
274
- For each byte, the first bit being high indicates another byte must be
275
- read.
273
+ def read_variable_length_string (self ) -> Union [int , bytes ]:
274
+ """
275
+ Read a variable length string where the first 1-5 bytes stores the length of the string.
276
+ For each byte, the first bit being high indicates another byte must be read.
276
277
"""
277
278
byte = 0x80
278
279
length = 0
@@ -283,65 +284,65 @@ def read_variable_length_string(self):
283
284
bits_read = bits_read + 7
284
285
return self .read (length )
285
286
286
- def read_int24 (self ):
287
+ def read_int24 (self ) -> str :
287
288
a , b , c = struct .unpack ("BBB" , self .read (3 ))
288
289
res = a | (b << 8 ) | (c << 16 )
289
290
if res >= 0x800000 :
290
291
res -= 0x1000000
291
292
return res
292
293
293
- def read_int24_be (self ):
294
+ def read_int24_be (self ) -> str :
294
295
a , b , c = struct .unpack ('BBB' , self .read (3 ))
295
296
res = (a << 16 ) | (b << 8 ) | c
296
297
if res >= 0x800000 :
297
298
res -= 0x1000000
298
299
return res
299
300
300
- def read_uint8 (self ):
301
+ def read_uint8 (self ) -> str :
301
302
return struct .unpack ('<B' , self .read (1 ))[0 ]
302
303
303
- def read_int16 (self ):
304
+ def read_int16 (self ) -> str :
304
305
return struct .unpack ('<h' , self .read (2 ))[0 ]
305
306
306
- def read_uint16 (self ):
307
+ def read_uint16 (self ) -> str :
307
308
return struct .unpack ('<H' , self .read (2 ))[0 ]
308
309
309
- def read_uint24 (self ):
310
+ def read_uint24 (self ) -> str :
310
311
a , b , c = struct .unpack ("<BBB" , self .read (3 ))
311
312
return a + (b << 8 ) + (c << 16 )
312
313
313
- def read_uint32 (self ):
314
+ def read_uint32 (self ) -> str :
314
315
return struct .unpack ('<I' , self .read (4 ))[0 ]
315
316
316
- def read_int32 (self ):
317
+ def read_int32 (self ) -> str :
317
318
return struct .unpack ('<i' , self .read (4 ))[0 ]
318
319
319
- def read_uint40 (self ):
320
+ def read_uint40 (self ) -> str :
320
321
a , b = struct .unpack ("<BI" , self .read (5 ))
321
322
return a + (b << 8 )
322
323
323
- def read_int40_be (self ):
324
+ def read_int40_be (self ) -> str :
324
325
a , b = struct .unpack (">IB" , self .read (5 ))
325
326
return b + (a << 8 )
326
327
327
- def read_uint48 (self ):
328
+ def read_uint48 (self ) -> str :
328
329
a , b , c = struct .unpack ("<HHH" , self .read (6 ))
329
330
return a + (b << 16 ) + (c << 32 )
330
331
331
- def read_uint56 (self ):
332
+ def read_uint56 (self ) -> str :
332
333
a , b , c = struct .unpack ("<BHI" , self .read (7 ))
333
334
return a + (b << 8 ) + (c << 24 )
334
335
335
- def read_uint64 (self ):
336
+ def read_uint64 (self ) -> str :
336
337
return struct .unpack ('<Q' , self .read (8 ))[0 ]
337
338
338
- def read_int64 (self ):
339
+ def read_int64 (self ) -> str :
339
340
return struct .unpack ('<q' , self .read (8 ))[0 ]
340
341
341
- def unpack_uint16 (self , n ) :
342
+ def unpack_uint16 (self , n : bytes ) -> str :
342
343
return struct .unpack ('<H' , n [0 :2 ])[0 ]
343
344
344
- def unpack_int24 (self , n ) :
345
+ def unpack_int24 (self , n : bytes ) -> Optional [ str , int ] :
345
346
try :
346
347
return struct .unpack ('B' , n [0 ])[0 ] \
347
348
+ (struct .unpack ('B' , n [1 ])[0 ] << 8 ) \
@@ -358,7 +359,7 @@ def unpack_int32(self, n):
358
359
except TypeError :
359
360
return n [0 ] + (n [1 ] << 8 ) + (n [2 ] << 16 ) + (n [3 ] << 24 )
360
361
361
- def read_binary_json (self , size ) :
362
+ def read_binary_json (self , size : int ) -> Optional [ str ] :
362
363
length = self .read_uint_by_size (size )
363
364
if length == 0 :
364
365
# handle NULL value
@@ -369,7 +370,7 @@ def read_binary_json(self, size):
369
370
370
371
return self .read_binary_json_type (t , length )
371
372
372
- def read_binary_json_type (self , t , length ) :
373
+ def read_binary_json_type (self , t : bytes , length : int ) -> Optional [ bool , str ] :
373
374
large = (t in (JSONB_TYPE_LARGE_OBJECT , JSONB_TYPE_LARGE_ARRAY ))
374
375
if t in (JSONB_TYPE_SMALL_OBJECT , JSONB_TYPE_LARGE_OBJECT ):
375
376
return self .read_binary_json_object (length - 1 , large )
@@ -402,7 +403,7 @@ def read_binary_json_type(self, t, length):
402
403
403
404
raise ValueError ('Json type %d is not handled' % t )
404
405
405
- def read_binary_json_type_inlined (self , t , large ) :
406
+ def read_binary_json_type_inlined (self , t : bytes , large : bool ) -> Optional [ bool , str ] :
406
407
if t == JSONB_TYPE_LITERAL :
407
408
value = self .read_uint32 () if large else self .read_uint16 ()
408
409
if value == JSONB_LITERAL_NULL :
@@ -422,7 +423,7 @@ def read_binary_json_type_inlined(self, t, large):
422
423
423
424
raise ValueError ('Json type %d is not handled' % t )
424
425
425
- def read_binary_json_object (self , length , large ) :
426
+ def read_binary_json_object (self , length : int , large : bool ) -> Dict [ str , str ] :
426
427
if large :
427
428
elements = self .read_uint32 ()
428
429
size = self .read_uint32 ()
@@ -460,7 +461,7 @@ def read_binary_json_object(self, length, large):
460
461
461
462
return out
462
463
463
- def read_binary_json_array (self , length , large ) :
464
+ def read_binary_json_array (self , length : int , large : bool ) -> List :
464
465
if large :
465
466
elements = self .read_uint32 ()
466
467
size = self .read_uint32 ()
@@ -482,13 +483,11 @@ def _read(x):
482
483
483
484
return [_read (x ) for x in values_type_offset_inline ]
484
485
485
- def read_string (self ):
486
- """Read a 'Length Coded String' from the data buffer.
487
-
486
+ def read_string (self ) -> bytes :
487
+ """
488
+ Read a 'Length Coded String' from the data buffer.
488
489
Read __data_buffer until NULL character (0 = \0 = \x00 )
489
-
490
- Returns:
491
- Binary string parsed from __data_buffer
490
+ :return string: Binary string parsed from __data_buffer
492
491
"""
493
492
string = b''
494
493
while True :
0 commit comments