home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyos2bin.zip / Lib / pickle.py < prev    next >
Text File  |  1997-12-10  |  21KB  |  832 lines

  1. """create portable serialized representations of Python objects.
  2.  
  3. See module cPickle for a (much) faster implementation.
  4. See module copy_reg for a mechanism for registering custom picklers.
  5.  
  6. Classes:
  7.  
  8.     Pickler
  9.     Unpickler
  10.  
  11. Functions:
  12.  
  13.     dump(object, file)
  14.     dumps(object) -> string
  15.     load(file) -> object
  16.     loads(string) -> object
  17.  
  18. Misc variables:
  19.  
  20.     __ version__
  21.     format_version
  22.     compatible_formats
  23.  
  24. """
  25.  
  26. __version__ = "1.9"                     # Code version
  27.  
  28. from types import *
  29. from copy_reg import dispatch_table, safe_constructors
  30. import string, marshal
  31.  
  32. format_version = "1.2"                  # File format version we write
  33. compatible_formats = ["1.0", "1.1"]     # Old format versions we can read
  34.  
  35. mdumps = marshal.dumps
  36. mloads = marshal.loads
  37.  
  38. PicklingError = "pickle.PicklingError"
  39. UnpicklingError = "pickle.UnpicklingError"
  40.  
  41. MARK            = '('
  42. STOP            = '.'
  43. POP             = '0'
  44. POP_MARK        = '1'
  45. DUP             = '2'
  46. FLOAT           = 'F'
  47. INT             = 'I'
  48. BININT          = 'J'
  49. BININT1         = 'K'
  50. LONG            = 'L'
  51. BININT2         = 'M'
  52. NONE            = 'N'
  53. PERSID          = 'P'
  54. BINPERSID       = 'Q'
  55. REDUCE          = 'R'
  56. STRING          = 'S'
  57. BINSTRING       = 'T'
  58. SHORT_BINSTRING = 'U'
  59. APPEND          = 'a'
  60. BUILD           = 'b'
  61. GLOBAL          = 'c'
  62. DICT            = 'd'
  63. EMPTY_DICT      = '}'
  64. APPENDS         = 'e'
  65. GET             = 'g'
  66. BINGET          = 'h'
  67. INST            = 'i'
  68. LONG_BINGET     = 'j'
  69. LIST            = 'l'
  70. EMPTY_LIST      = ']'
  71. OBJ             = 'o'
  72. PUT             = 'p'
  73. BINPUT          = 'q'
  74. LONG_BINPUT     = 'r'
  75. SETITEM         = 's'
  76. TUPLE           = 't'
  77. EMPTY_TUPLE     = ')'
  78. SETITEMS        = 'u'
  79.  
  80. class Pickler:
  81.  
  82.     def __init__(self, file, bin = 0):
  83.         self.write = file.write
  84.         self.memo = {}
  85.         self.bin = bin
  86.  
  87.     def dump(self, object):
  88.         self.save(object)
  89.         self.write(STOP)
  90.  
  91.     def dump_special(self, callable, args, state = None):
  92.     if type(args) is not TupleType and args is not None:
  93.             raise PicklingError, "Second argument to dump_special " \
  94.                                  "must be a tuple"
  95.  
  96.         self.save_reduce(callable, args, state)
  97.         self.write(STOP)
  98.  
  99.     def put(self, i):
  100.         if (self.bin):
  101.             s = mdumps(i)[1:]
  102.             if (i < 256):
  103.                 return BINPUT + s[0]
  104.  
  105.             return LONG_BINPUT + s
  106.  
  107.         return PUT + `i` + '\n'
  108.  
  109.     def get(self, i):
  110.         if (self.bin):
  111.             s = mdumps(i)[1:]
  112.  
  113.             if (i < 256):
  114.                 return BINGET + s[0]
  115.  
  116.             return LONG_BINGET + s
  117.  
  118.         return GET + `i` + '\n'
  119.         
  120.     def save(self, object, pers_save = 0):
  121.         memo = self.memo
  122.  
  123.         if (not pers_save):
  124.         pid = self.persistent_id(object)
  125.         if (pid is not None):
  126.                 self.save_pers(pid)
  127.                 return
  128.  
  129.         d = id(object)
  130.  
  131.         t = type(object)
  132.  
  133.     if ((t is TupleType) and (len(object) == 0)):
  134.         if (self.bin):
  135.                 self.save_empty_tuple(object)
  136.             else:
  137.                 self.save_tuple(object)
  138.             return
  139.  
  140.         if memo.has_key(d):
  141.             self.write(self.get(memo[d][0]))
  142.             return
  143.  
  144.         try:
  145.             f = self.dispatch[t]
  146.         except KeyError:
  147.             pid = self.inst_persistent_id(object)
  148.             if pid is not None:
  149.                 self.save_pers(pid)
  150.                 return
  151.  
  152.             try:
  153.                 reduce = dispatch_table[t]
  154.             except KeyError:
  155.                 try:
  156.                     reduce = object.__reduce__
  157.                 except AttributeError:
  158.                     raise PicklingError, \
  159.                         "can't pickle %s objects" % `t.__name__`
  160.                 else:
  161.                     tup = reduce()
  162.             else:
  163.                 tup = reduce(object)
  164.  
  165.         if type(tup) is StringType:
  166.         self.save_global(object, tup)
  167.         return
  168.  
  169.             if (type(tup) is not TupleType):
  170.                 raise PicklingError, "Value returned by %s must be a " \
  171.                                      "tuple" % reduce
  172.  
  173.             l = len(tup)
  174.    
  175.         if ((l != 2) and (l != 3)):
  176.                 raise PicklingError, "tuple returned by %s must contain " \
  177.                                      "only two or three elements" % reduce
  178.  
  179.             callable = tup[0]
  180.             arg_tup  = tup[1]
  181.           
  182.             if (l > 2):
  183.                 state = tup[2]
  184.             else:
  185.                 state = None
  186.  
  187.             if type(arg_tup) is not TupleType and arg_tup is not None:
  188.                 raise PicklingError, "Second element of tuple returned " \
  189.                                      "by %s must be a tuple" % reduce
  190.  
  191.             self.save_reduce(callable, arg_tup, state) 
  192.         memo_len = len(memo)
  193.         self.write(self.put(memo_len))
  194.         memo[d] = (memo_len, object)
  195.             return
  196.  
  197.         f(self, object)
  198.  
  199.     def persistent_id(self, object):
  200.         return None
  201.  
  202.     def inst_persistent_id(self, object):
  203.         return None
  204.  
  205.     def save_pers(self, pid):
  206.         if (not self.bin):
  207.             self.write(PERSID + str(pid) + '\n')
  208.         else:
  209.             self.save(pid, 1)
  210.             self.write(BINPERSID)
  211.  
  212.     def save_reduce(self, callable, arg_tup, state = None):
  213.         write = self.write
  214.         save = self.save
  215.  
  216.         save(callable)
  217.         save(arg_tup)
  218.         write(REDUCE)
  219.         
  220.     if (state is not None):
  221.             save(state)
  222.             write(BUILD)
  223.  
  224.     dispatch = {}
  225.  
  226.     def save_none(self, object):
  227.         self.write(NONE)
  228.     dispatch[NoneType] = save_none
  229.  
  230.     def save_int(self, object):
  231.         if (self.bin):
  232.             i = mdumps(object)[1:]
  233.             if (i[-2:] == '\000\000'):
  234.                 if (i[-3] == '\000'):
  235.                     self.write(BININT1 + i[:-3])
  236.                     return
  237.  
  238.                 self.write(BININT2 + i[:-2])
  239.                 return
  240.  
  241.             self.write(BININT + i)
  242.         else:
  243.             self.write(INT + `object` + '\n')
  244.     dispatch[IntType] = save_int
  245.  
  246.     def save_long(self, object):
  247.         self.write(LONG + `object` + '\n')
  248.     dispatch[LongType] = save_long
  249.  
  250.     def save_float(self, object):
  251.         self.write(FLOAT + `object` + '\n')
  252.     dispatch[FloatType] = save_float
  253.  
  254.     def save_string(self, object):
  255.         d = id(object)
  256.         memo = self.memo
  257.  
  258.         if (self.bin):
  259.             l = len(object)
  260.             s = mdumps(l)[1:]
  261.             if (l < 256):
  262.                 self.write(SHORT_BINSTRING + s[0] + object)
  263.             else:
  264.                 self.write(BINSTRING + s + object)
  265.         else:
  266.             self.write(STRING + `object` + '\n')
  267.  
  268.         memo_len = len(memo)
  269.         self.write(self.put(memo_len))
  270.         memo[d] = (memo_len, object)
  271.     dispatch[StringType] = save_string
  272.  
  273.     def save_tuple(self, object):
  274.  
  275.         write = self.write
  276.         save  = self.save
  277.         memo  = self.memo
  278.  
  279.         d = id(object)
  280.  
  281.         write(MARK)
  282.  
  283.         for element in object:
  284.             save(element)
  285.  
  286.         if (len(object) and memo.has_key(d)):
  287.         if (self.bin):
  288.                 write(POP_MARK + self.get(memo[d][0]))
  289.                 return
  290.            
  291.             write(POP * (len(object) + 1) + self.get(mem[d][0]))
  292.             return
  293.  
  294.         memo_len = len(memo)
  295.         self.write(TUPLE + self.put(memo_len))
  296.         memo[d] = (memo_len, object)
  297.     dispatch[TupleType] = save_tuple
  298.  
  299.     def save_empty_tuple(self, object):
  300.         self.write(EMPTY_TUPLE)
  301.  
  302.     def save_list(self, object):
  303.         d = id(object)
  304.  
  305.         write = self.write
  306.         save  = self.save
  307.         memo  = self.memo
  308.  
  309.     if (self.bin):
  310.             write(EMPTY_LIST)
  311.         else:
  312.             write(MARK + LIST)
  313.  
  314.         memo_len = len(memo)
  315.         write(self.put(memo_len))
  316.         memo[d] = (memo_len, object)
  317.  
  318.         using_appends = (self.bin and (len(object) > 1))
  319.  
  320.         if (using_appends):
  321.             write(MARK)
  322.  
  323.         for element in object:
  324.             save(element)
  325.   
  326.             if (not using_appends):
  327.                 write(APPEND)
  328.  
  329.         if (using_appends):
  330.             write(APPENDS)
  331.     dispatch[ListType] = save_list
  332.  
  333.     def save_dict(self, object):
  334.         d = id(object)
  335.  
  336.         write = self.write
  337.         save  = self.save
  338.         memo  = self.memo
  339.  
  340.     if (self.bin):
  341.             write(EMPTY_DICT)
  342.         else:
  343.             write(MARK + DICT)
  344.  
  345.         memo_len = len(memo)
  346.         self.write(self.put(memo_len))
  347.         memo[d] = (memo_len, object)
  348.  
  349.         using_setitems = (self.bin and (len(object) > 1))
  350.  
  351.         if (using_setitems):
  352.             write(MARK)
  353.  
  354.         items = object.items()
  355.         for key, value in items:
  356.             save(key)
  357.             save(value)
  358.  
  359.             if (not using_setitems):
  360.                 write(SETITEM)
  361.  
  362.         if (using_setitems):
  363.             write(SETITEMS)
  364.  
  365.     dispatch[DictionaryType] = save_dict
  366.  
  367.     def save_inst(self, object):
  368.         d = id(object)
  369.         cls = object.__class__
  370.  
  371.         memo  = self.memo
  372.         write = self.write
  373.         save  = self.save
  374.  
  375.         if hasattr(object, '__getinitargs__'):
  376.             args = object.__getinitargs__()
  377.             len(args) # XXX Assert it's a sequence
  378.         _keep_alive(args, memo)
  379.         else:
  380.             args = ()
  381.  
  382.         write(MARK)
  383.  
  384.         if (self.bin):
  385.             save(cls)
  386.  
  387.         for arg in args:
  388.             save(arg)
  389.  
  390.         memo_len = len(memo)
  391.         if (self.bin):
  392.             write(OBJ + self.put(memo_len))
  393.         else:
  394.             write(INST + cls.__module__ + '\n' + cls.__name__ + '\n' +
  395.                 self.put(memo_len))
  396.  
  397.         memo[d] = (memo_len, object)
  398.  
  399.         try:
  400.             getstate = object.__getstate__
  401.         except AttributeError:
  402.             stuff = object.__dict__
  403.         else:
  404.             stuff = getstate()
  405.         _keep_alive(stuff, memo)
  406.         save(stuff)
  407.         write(BUILD)
  408.     dispatch[InstanceType] = save_inst
  409.  
  410.     def save_global(self, object, name = None):
  411.         write = self.write
  412.         memo = self.memo
  413.  
  414.         if (name is None):
  415.             name = object.__name__
  416.  
  417.     try:
  418.         module = object.__module__
  419.     except AttributeError:
  420.         module = whichmodule(object, name)
  421.  
  422.         memo_len = len(memo)
  423.         write(GLOBAL + module + '\n' + name + '\n' +
  424.             self.put(memo_len))
  425.         memo[id(object)] = (memo_len, object)
  426.     dispatch[ClassType] = save_global
  427.     dispatch[FunctionType] = save_global
  428.     dispatch[BuiltinFunctionType] = save_global
  429.  
  430.  
  431. def _keep_alive(x, memo):
  432.     """Keeps a reference to the object x in the memo.
  433.  
  434.     Because we remember objects by their id, we have
  435.     to assure that possibly temporary objects are kept
  436.     alive by referencing them.
  437.     We store a reference at the id of the memo, which should
  438.     normally not be used unless someone tries to deepcopy
  439.     the memo itself...
  440.     """
  441.     try:
  442.     memo[id(memo)].append(x)
  443.     except KeyError:
  444.     # aha, this is the first one :-)
  445.     memo[id(memo)]=[x]
  446.  
  447.  
  448. classmap = {}
  449.  
  450. # This is no longer used to find classes, but still for functions
  451. def whichmodule(cls, clsname):
  452.     """Figure out the module in which a class occurs.
  453.  
  454.     Search sys.modules for the module.
  455.     Cache in classmap.
  456.     Return a module name.
  457.     If the class cannot be found, return __main__.
  458.     """
  459.     if classmap.has_key(cls):
  460.         return classmap[cls]
  461.     import sys
  462.  
  463.     for name, module in sys.modules.items():
  464.     if name != '__main__' and \
  465.         hasattr(module, clsname) and \
  466.             getattr(module, clsname) is cls:
  467.             break
  468.     else:
  469.         name = '__main__'
  470.     classmap[cls] = name
  471.     return name
  472.  
  473.  
  474. class Unpickler:
  475.  
  476.     def __init__(self, file):
  477.         self.readline = file.readline
  478.         self.read = file.read
  479.         self.memo = {}
  480.  
  481.     def load(self):
  482.         self.mark = ['spam'] # Any new unique object
  483.         self.stack = []
  484.         self.append = self.stack.append
  485.         read = self.read
  486.         dispatch = self.dispatch
  487.         try:
  488.             while 1:
  489.                 key = read(1)
  490.                 dispatch[key](self)
  491.         except STOP, value:
  492.             return value
  493.  
  494.     def marker(self):
  495.         stack = self.stack
  496.         mark = self.mark
  497.         k = len(stack)-1
  498.         while stack[k] is not mark: k = k-1
  499.         return k
  500.  
  501.     dispatch = {}
  502.  
  503.     def load_eof(self):
  504.         raise EOFError
  505.     dispatch[''] = load_eof
  506.  
  507.     def load_persid(self):
  508.         pid = self.readline()[:-1]
  509.         self.append(self.persistent_load(pid))
  510.     dispatch[PERSID] = load_persid
  511.  
  512.     def load_binpersid(self):
  513.         stack = self.stack
  514.          
  515.         pid = stack[-1]
  516.         del stack[-1]
  517.  
  518.         self.append(self.persistent_load(pid))
  519.     dispatch[BINPERSID] = load_binpersid
  520.  
  521.     def load_none(self):
  522.         self.append(None)
  523.     dispatch[NONE] = load_none
  524.  
  525.     def load_int(self):
  526.         self.append(string.atoi(self.readline()[:-1]))
  527.     dispatch[INT] = load_int
  528.  
  529.     def load_binint(self):
  530.         self.append(mloads('i' + self.read(4)))
  531.     dispatch[BININT] = load_binint
  532.  
  533.     def load_binint1(self):
  534.         self.append(mloads('i' + self.read(1) + '\000\000\000'))
  535.     dispatch[BININT1] = load_binint1
  536.  
  537.     def load_binint2(self):
  538.         self.append(mloads('i' + self.read(2) + '\000\000'))
  539.     dispatch[BININT2] = load_binint2
  540.  
  541.     def load_long(self):
  542.         self.append(string.atol(self.readline()[:-1], 0))
  543.     dispatch[LONG] = load_long
  544.  
  545.     def load_float(self):
  546.         self.append(string.atof(self.readline()[:-1]))
  547.     dispatch[FLOAT] = load_float
  548.  
  549.     def load_string(self):
  550.         self.append(eval(self.readline()[:-1],
  551.                          {'__builtins__': {}})) # Let's be careful
  552.     dispatch[STRING] = load_string
  553.  
  554.     def load_binstring(self):
  555.         len = mloads('i' + self.read(4))
  556.         self.append(self.read(len))
  557.     dispatch[BINSTRING] = load_binstring
  558.  
  559.     def load_short_binstring(self):
  560.         len = mloads('i' + self.read(1) + '\000\000\000')
  561.         self.append(self.read(len))
  562.     dispatch[SHORT_BINSTRING] = load_short_binstring
  563.  
  564.     def load_tuple(self):
  565.         k = self.marker()
  566.         self.stack[k:] = [tuple(self.stack[k+1:])]
  567.     dispatch[TUPLE] = load_tuple
  568.  
  569.     def load_empty_tuple(self):
  570.         self.stack.append(())
  571.     dispatch[EMPTY_TUPLE] = load_empty_tuple
  572.  
  573.     def load_empty_list(self):
  574.         self.stack.append([])
  575.     dispatch[EMPTY_LIST] = load_empty_list
  576.  
  577.     def load_empty_dictionary(self):
  578.         self.stack.append({})
  579.     dispatch[EMPTY_DICT] = load_empty_dictionary
  580.  
  581.     def load_list(self):
  582.         k = self.marker()
  583.         self.stack[k:] = [self.stack[k+1:]]
  584.     dispatch[LIST] = load_list
  585.  
  586.     def load_dict(self):
  587.         k = self.marker()
  588.         d = {}
  589.         items = self.stack[k+1:]
  590.         for i in range(0, len(items), 2):
  591.             key = items[i]
  592.             value = items[i+1]
  593.             d[key] = value
  594.         self.stack[k:] = [d]
  595.     dispatch[DICT] = load_dict
  596.  
  597.     def load_inst(self):
  598.         k = self.marker()
  599.         args = tuple(self.stack[k+1:])
  600.         del self.stack[k:]
  601.         module = self.readline()[:-1]
  602.         name = self.readline()[:-1]
  603.         klass = self.find_class(module, name)
  604.     if (not args and type(klass) is ClassType and
  605.         not hasattr(klass, "__getinitargs__")):
  606.         value = _EmptyClass()
  607.         value.__class__ = klass
  608.     else:
  609.         value = apply(klass, args)
  610.         self.append(value)
  611.     dispatch[INST] = load_inst
  612.  
  613.     def load_obj(self):
  614.         stack = self.stack
  615.         k = self.marker()
  616.         klass = stack[k + 1]
  617.         del stack[k + 1]
  618.         args = tuple(stack[k + 1:]) 
  619.         del stack[k:]
  620.     if (not args and type(klass) is ClassType and
  621.         not hasattr(klass, "__getinitargs__")):
  622.         value = _EmptyClass()
  623.         value.__class__ = klass
  624.     else:
  625.         value = apply(klass, args)
  626.         self.append(value)
  627.     dispatch[OBJ] = load_obj                
  628.  
  629.     def load_global(self):
  630.         module = self.readline()[:-1]
  631.         name = self.readline()[:-1]
  632.         klass = self.find_class(module, name)
  633.         self.append(klass)
  634.     dispatch[GLOBAL] = load_global
  635.  
  636.     def find_class(self, module, name):
  637.         env = {}
  638.  
  639.         try:
  640.             exec 'from %s import %s' % (module, name) in env
  641.         except ImportError:
  642.             raise SystemError, \
  643.                   "Failed to import class %s from module %s" % \
  644.                   (name, module)
  645.         klass = env[name]
  646.         return klass
  647.  
  648.     def load_reduce(self):
  649.         stack = self.stack
  650.  
  651.         callable = stack[-2]
  652.         arg_tup  = stack[-1]
  653.     del stack[-2:]
  654.  
  655.     if type(callable) is not ClassType:
  656.         if not safe_constructors.has_key(callable):
  657.         try:
  658.                     safe = callable.__safe_for_unpickling__
  659.                 except AttributeError:
  660.                     safe = None
  661.  
  662.                 if (not safe):
  663.                    raise UnpicklingError, "%s is not safe for " \
  664.                                           "unpickling" % callable
  665.  
  666.     if arg_tup is None:
  667.         value = callable.__basicnew__()
  668.     else:
  669.         value = apply(callable, arg_tup)
  670.         self.append(value)
  671.     dispatch[REDUCE] = load_reduce
  672.  
  673.     def load_pop(self):
  674.         del self.stack[-1]
  675.     dispatch[POP] = load_pop
  676.  
  677.     def load_pop_mark(self):
  678.         k = self.marker()
  679.     del self.stack[k:]
  680.     dispatch[POP_MARK] = load_pop_mark
  681.  
  682.     def load_dup(self):
  683.         self.append(stack[-1])
  684.     dispatch[DUP] = load_dup
  685.  
  686.     def load_get(self):
  687.         self.append(self.memo[self.readline()[:-1]])
  688.     dispatch[GET] = load_get
  689.  
  690.     def load_binget(self):
  691.         i = mloads('i' + self.read(1) + '\000\000\000')
  692.         self.append(self.memo[`i`])
  693.     dispatch[BINGET] = load_binget
  694.  
  695.     def load_long_binget(self):
  696.         i = mloads('i' + self.read(4))
  697.         self.append(self.memo[`i`])
  698.     dispatch[LONG_BINGET] = load_long_binget
  699.  
  700.     def load_put(self):
  701.         self.memo[self.readline()[:-1]] = self.stack[-1]
  702.     dispatch[PUT] = load_put
  703.  
  704.     def load_binput(self):
  705.         i = mloads('i' + self.read(1) + '\000\000\000')
  706.         self.memo[`i`] = self.stack[-1]
  707.     dispatch[BINPUT] = load_binput
  708.  
  709.     def load_long_binput(self):
  710.         i = mloads('i' + self.read(4))
  711.         self.memo[`i`] = self.stack[-1]
  712.     dispatch[LONG_BINPUT] = load_long_binput
  713.  
  714.     def load_append(self):
  715.         stack = self.stack
  716.         value = stack[-1]
  717.         del stack[-1]
  718.         list = stack[-1]
  719.         list.append(value)
  720.     dispatch[APPEND] = load_append
  721.  
  722.     def load_appends(self):
  723.         stack = self.stack
  724.         mark = self.marker()
  725.         list = stack[mark - 1]
  726.     for i in range(mark + 1, len(stack)):
  727.             list.append(stack[i])
  728.  
  729.         del stack[mark:]
  730.     dispatch[APPENDS] = load_appends
  731.            
  732.     def load_setitem(self):
  733.         stack = self.stack
  734.         value = stack[-1]
  735.         key = stack[-2]
  736.         del stack[-2:]
  737.         dict = stack[-1]
  738.         dict[key] = value
  739.     dispatch[SETITEM] = load_setitem
  740.  
  741.     def load_setitems(self):
  742.         stack = self.stack
  743.         mark = self.marker()
  744.         dict = stack[mark - 1]
  745.     for i in range(mark + 1, len(stack), 2):
  746.             dict[stack[i]] = stack[i + 1]
  747.  
  748.         del stack[mark:]
  749.     dispatch[SETITEMS] = load_setitems
  750.  
  751.     def load_build(self):
  752.         stack = self.stack
  753.         value = stack[-1]
  754.         del stack[-1]
  755.         inst = stack[-1]
  756.         try:
  757.             setstate = inst.__setstate__
  758.         except AttributeError:
  759.         inst.__dict__.update(value)
  760.         else:
  761.             setstate(value)
  762.     dispatch[BUILD] = load_build
  763.  
  764.     def load_mark(self):
  765.         self.append(self.mark)
  766.     dispatch[MARK] = load_mark
  767.  
  768.     def load_stop(self):
  769.         value = self.stack[-1]
  770.         del self.stack[-1]
  771.         raise STOP, value
  772.     dispatch[STOP] = load_stop
  773.  
  774. # Helper class for load_inst/load_obj
  775.  
  776. class _EmptyClass:
  777.     pass
  778.  
  779. # Shorthands
  780.  
  781. from StringIO import StringIO
  782.  
  783. def dump(object, file, bin = 0):
  784.     Pickler(file, bin).dump(object)
  785.  
  786. def dumps(object, bin = 0):
  787.     file = StringIO()
  788.     Pickler(file, bin).dump(object)
  789.     return file.getvalue()
  790.  
  791. def load(file):
  792.     return Unpickler(file).load()
  793.  
  794. def loads(str):
  795.     file = StringIO(str)
  796.     return Unpickler(file).load()
  797.  
  798.  
  799. # The rest is used for testing only
  800.  
  801. class C:
  802.     def __cmp__(self, other):
  803.         return cmp(self.__dict__, other.__dict__)
  804.  
  805. def test():
  806.     fn = 'out'
  807.     c = C()
  808.     c.foo = 1
  809.     c.bar = 2
  810.     x = [0, 1, 2, 3]
  811.     y = ('abc', 'abc', c, c)
  812.     x.append(y)
  813.     x.append(y)
  814.     x.append(5)
  815.     f = open(fn, 'w')
  816.     F = Pickler(f)
  817.     F.dump(x)
  818.     f.close()
  819.     f = open(fn, 'r')
  820.     U = Unpickler(f)
  821.     x2 = U.load()
  822.     print x
  823.     print x2
  824.     print x == x2
  825.     print map(id, x)
  826.     print map(id, x2)
  827.     print F.memo
  828.     print U.memo
  829.  
  830. if __name__ == '__main__':
  831.     test()
  832.