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