@@ -485,10 +485,13 @@ class Packer(object):
485485 Convert unicode to bytes with this encoding. (default: 'utf-8')
486486 :param str unicode_errors:
487487 Error handler for encoding unicode. (default: 'strict')
488- :param bool distinguish_tuple:
489- If set to true, tuples will not be serialized as lists
490- and will be treated as unsupported type. This is useful when trying
491- to implement accurate serialization for python types.
488+ :param bool precise_mode:
489+ If set to true, types will be checked to be exact. Derived classes
490+ from serializeable types will not be serialized and will be
491+ treated as unsupported type and forwarded to default.
492+ Additionally tuples will not be serialized as lists.
493+ This is useful when trying to implement accurate serialization
494+ for python types.
492495 :param bool use_single_float:
493496 Use single precision float type for float. (default: False)
494497 :param bool autoreset:
@@ -499,9 +502,9 @@ class Packer(object):
499502 It also enable str8 type for unicode.
500503 """
501504 def __init__ (self , default = None , encoding = 'utf-8' , unicode_errors = 'strict' ,
502- distinguish_tuple = False , use_single_float = False , autoreset = True ,
505+ precise_mode = False , use_single_float = False , autoreset = True ,
503506 use_bin_type = False ):
504- self ._distinguish_tuple = distinguish_tuple
507+ self ._precise_mode = precise_mode
505508 self ._use_float = use_single_float
506509 self ._autoreset = autoreset
507510 self ._use_bin_type = use_bin_type
@@ -513,19 +516,30 @@ def __init__(self, default=None, encoding='utf-8', unicode_errors='strict',
513516 raise TypeError ("default must be callable" )
514517 self ._default = default
515518
516- def _pack (self , obj , nest_limit = DEFAULT_RECURSE_LIMIT , isinstance = isinstance ):
519+ def _check_precise (obj , t , type = type , tuple = tuple ):
520+ if type (t ) is tuple :
521+ return type (obj ) in t
522+ else :
523+ return type (obj ) is t
524+
525+ def _pack (self , obj , nest_limit = DEFAULT_RECURSE_LIMIT ,
526+ check = isinstance , check_precise = _check_precise ):
517527 default_used = False
518- list_type = list if self ._distinguish_tuple else (list , tuple )
528+ if self ._precise_mode :
529+ check = check_precise
530+ list_types = list
531+ else :
532+ list_types = (list , tuple )
519533 while True :
520534 if nest_limit < 0 :
521535 raise PackValueError ("recursion limit exceeded" )
522536 if obj is None :
523537 return self ._buffer .write (b"\xc0 " )
524- if isinstance (obj , bool ):
538+ if check (obj , bool ):
525539 if obj :
526540 return self ._buffer .write (b"\xc3 " )
527541 return self ._buffer .write (b"\xc2 " )
528- if isinstance (obj , int_types ):
542+ if check (obj , int_types ):
529543 if 0 <= obj < 0x80 :
530544 return self ._buffer .write (struct .pack ("B" , obj ))
531545 if - 0x20 <= obj < 0 :
@@ -547,7 +561,7 @@ def _pack(self, obj, nest_limit=DEFAULT_RECURSE_LIMIT, isinstance=isinstance):
547561 if - 0x8000000000000000 <= obj < - 0x80000000 :
548562 return self ._buffer .write (struct .pack (">Bq" , 0xd3 , obj ))
549563 raise PackValueError ("Integer value out of range" )
550- if self ._use_bin_type and isinstance (obj , bytes ):
564+ if self ._use_bin_type and check (obj , bytes ):
551565 n = len (obj )
552566 if n <= 0xff :
553567 self ._buffer .write (struct .pack ('>BB' , 0xc4 , n ))
@@ -558,8 +572,8 @@ def _pack(self, obj, nest_limit=DEFAULT_RECURSE_LIMIT, isinstance=isinstance):
558572 else :
559573 raise PackValueError ("Bytes is too large" )
560574 return self ._buffer .write (obj )
561- if isinstance (obj , (Unicode , bytes )):
562- if isinstance (obj , Unicode ):
575+ if check (obj , (Unicode , bytes )):
576+ if check (obj , Unicode ):
563577 if self ._encoding is None :
564578 raise TypeError (
565579 "Can't encode unicode string: "
@@ -577,11 +591,11 @@ def _pack(self, obj, nest_limit=DEFAULT_RECURSE_LIMIT, isinstance=isinstance):
577591 else :
578592 raise PackValueError ("String is too large" )
579593 return self ._buffer .write (obj )
580- if isinstance (obj , float ):
594+ if check (obj , float ):
581595 if self ._use_float :
582596 return self ._buffer .write (struct .pack (">Bf" , 0xca , obj ))
583597 return self ._buffer .write (struct .pack (">Bd" , 0xcb , obj ))
584- if isinstance (obj , ExtType ):
598+ if check (obj , ExtType ):
585599 code = obj .code
586600 data = obj .data
587601 assert isinstance (code , int )
@@ -606,13 +620,13 @@ def _pack(self, obj, nest_limit=DEFAULT_RECURSE_LIMIT, isinstance=isinstance):
606620 self ._buffer .write (struct .pack ("b" , code ))
607621 self ._buffer .write (data )
608622 return
609- if isinstance (obj , list_type ):
623+ if check (obj , list_types ):
610624 n = len (obj )
611625 self ._fb_pack_array_header (n )
612626 for i in xrange (n ):
613627 self ._pack (obj [i ], nest_limit - 1 )
614628 return
615- if isinstance (obj , dict ):
629+ if check (obj , dict ):
616630 return self ._fb_pack_map_pairs (len (obj ), dict_iteritems (obj ),
617631 nest_limit - 1 )
618632 if not default_used and self ._default is not None :
0 commit comments