@@ -601,6 +601,13 @@ class Packer(object):
601
601
Convert unicode to bytes with this encoding. (default: 'utf-8')
602
602
:param str unicode_errors:
603
603
Error handler for encoding unicode. (default: 'strict')
604
+ :param bool precise_mode:
605
+ If set to true, types will be checked to be exact. Derived classes
606
+ from serializeable types will not be serialized and will be
607
+ treated as unsupported type and forwarded to default.
608
+ Additionally tuples will not be serialized as lists.
609
+ This is useful when trying to implement accurate serialization
610
+ for python types.
604
611
:param bool use_single_float:
605
612
Use single precision float type for float. (default: False)
606
613
:param bool autoreset:
@@ -611,7 +618,9 @@ class Packer(object):
611
618
It also enable str8 type for unicode.
612
619
"""
613
620
def __init__ (self , default = None , encoding = 'utf-8' , unicode_errors = 'strict' ,
614
- use_single_float = False , autoreset = True , use_bin_type = False ):
621
+ precise_mode = False , use_single_float = False , autoreset = True ,
622
+ use_bin_type = False ):
623
+ self ._precise_mode = precise_mode
615
624
self ._use_float = use_single_float
616
625
self ._autoreset = autoreset
617
626
self ._use_bin_type = use_bin_type
@@ -623,18 +632,30 @@ def __init__(self, default=None, encoding='utf-8', unicode_errors='strict',
623
632
raise TypeError ("default must be callable" )
624
633
self ._default = default
625
634
626
- def _pack (self , obj , nest_limit = DEFAULT_RECURSE_LIMIT , isinstance = isinstance ):
635
+ def _check_precise (obj , t , type = type , tuple = tuple ):
636
+ if type (t ) is tuple :
637
+ return type (obj ) in t
638
+ else :
639
+ return type (obj ) is t
640
+
641
+ def _pack (self , obj , nest_limit = DEFAULT_RECURSE_LIMIT ,
642
+ check = isinstance , check_precise = _check_precise ):
627
643
default_used = False
644
+ if self ._precise_mode :
645
+ check = check_precise
646
+ list_types = list
647
+ else :
648
+ list_types = (list , tuple )
628
649
while True :
629
650
if nest_limit < 0 :
630
651
raise PackValueError ("recursion limit exceeded" )
631
652
if obj is None :
632
653
return self ._buffer .write (b"\xc0 " )
633
- if isinstance (obj , bool ):
654
+ if check (obj , bool ):
634
655
if obj :
635
656
return self ._buffer .write (b"\xc3 " )
636
657
return self ._buffer .write (b"\xc2 " )
637
- if isinstance (obj , int_types ):
658
+ if check (obj , int_types ):
638
659
if 0 <= obj < 0x80 :
639
660
return self ._buffer .write (struct .pack ("B" , obj ))
640
661
if - 0x20 <= obj < 0 :
@@ -660,7 +681,7 @@ def _pack(self, obj, nest_limit=DEFAULT_RECURSE_LIMIT, isinstance=isinstance):
660
681
default_used = True
661
682
continue
662
683
raise PackValueError ("Integer value out of range" )
663
- if self ._use_bin_type and isinstance (obj , bytes ):
684
+ if self ._use_bin_type and check (obj , bytes ):
664
685
n = len (obj )
665
686
if n <= 0xff :
666
687
self ._buffer .write (struct .pack ('>BB' , 0xc4 , n ))
@@ -671,8 +692,8 @@ def _pack(self, obj, nest_limit=DEFAULT_RECURSE_LIMIT, isinstance=isinstance):
671
692
else :
672
693
raise PackValueError ("Bytes is too large" )
673
694
return self ._buffer .write (obj )
674
- if isinstance (obj , (Unicode , bytes )):
675
- if isinstance (obj , Unicode ):
695
+ if check (obj , (Unicode , bytes )):
696
+ if check (obj , Unicode ):
676
697
if self ._encoding is None :
677
698
raise TypeError (
678
699
"Can't encode unicode string: "
@@ -690,11 +711,11 @@ def _pack(self, obj, nest_limit=DEFAULT_RECURSE_LIMIT, isinstance=isinstance):
690
711
else :
691
712
raise PackValueError ("String is too large" )
692
713
return self ._buffer .write (obj )
693
- if isinstance (obj , float ):
714
+ if check (obj , float ):
694
715
if self ._use_float :
695
716
return self ._buffer .write (struct .pack (">Bf" , 0xca , obj ))
696
717
return self ._buffer .write (struct .pack (">Bd" , 0xcb , obj ))
697
- if isinstance (obj , ExtType ):
718
+ if check (obj , ExtType ):
698
719
code = obj .code
699
720
data = obj .data
700
721
assert isinstance (code , int )
@@ -719,13 +740,13 @@ def _pack(self, obj, nest_limit=DEFAULT_RECURSE_LIMIT, isinstance=isinstance):
719
740
self ._buffer .write (struct .pack ("b" , code ))
720
741
self ._buffer .write (data )
721
742
return
722
- if isinstance (obj , ( list , tuple ) ):
743
+ if check (obj , list_types ):
723
744
n = len (obj )
724
745
self ._fb_pack_array_header (n )
725
746
for i in xrange (n ):
726
747
self ._pack (obj [i ], nest_limit - 1 )
727
748
return
728
- if isinstance (obj , dict ):
749
+ if check (obj , dict ):
729
750
return self ._fb_pack_map_pairs (len (obj ), dict_iteritems (obj ),
730
751
nest_l
3EFF
imit - 1 )
731
752
if not default_used and self ._default is not None :
0 commit comments