Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0c891ce

Browse files
committed
pickle classes; add format_version, load(s)/dump(s) shortcuts
1 parent cc08112 commit 0c891ce

1 file changed

Lines changed: 61 additions & 16 deletions

File tree

Lib/pickle.py

Lines changed: 61 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
1818
- recursive objects
1919
- pointer sharing
20-
- class instances
20+
- classes and class instances
2121
2222
Pickle is Python-specific. This has the advantage that there are no
2323
restrictions imposed by external standards such as CORBA (which probably
@@ -62,7 +62,7 @@
6262
return a *tuple* containing the arguments to be passed to the class
6363
constructor.
6464
65-
Classes can influence how they are pickled -- if the class defines
65+
Classes can influence how their instances are pickled -- if the class defines
6666
the method __getstate__, it is called and the return state is pickled
6767
as the contents for the instance, and if the class defines the
6868
method __setstate__, it is called with the unpickled state. (Note
@@ -108,6 +108,7 @@
108108
- strings
109109
- tuples, lists and dictionaries containing only picklable objects
110110
- class instances whose __dict__ or __setstate__() is picklable
111+
- classes
111112
112113
Attempts to pickle unpicklable objects will raise an exception
113114
after having written an unspecified number of bytes to the file argument.
@@ -125,12 +126,14 @@
125126
I have no answers. Garbage Collection may also become a problem here.)
126127
"""
127128

128-
__format_version__ = "1.0" # File format version
129-
__version__ = "1.4" # Code version
129+
__version__ = "1.5" # Code version
130130

131131
from types import *
132132
import string
133133

134+
format_version = "1.1" # File format version we write
135+
compatible_formats = ["1.0"] # Old format versions we can read
136+
134137
PicklingError = "pickle.PicklingError"
135138

136139
AtomicTypes = [NoneType, IntType, FloatType, StringType]
@@ -153,6 +156,7 @@ def safe(object):
153156
LIST = 'l'
154157
DICT = 'd'
155158
INST = 'i'
159+
CLASS = 'c'
156160
GET = 'g'
157161
PUT = 'p'
158162
APPEND = 'a'
@@ -300,8 +304,8 @@ def save_inst(self, object):
300304
self.write(MARK)
301305
for arg in args:
302306
self.save(arg)
303-
self.write(INST + module + '\n' + name + '\n' +
304-
PUT + `d` + '\n')
307+
self.write(INST + module + '\n' + name + '\n' +
308+
PUT + `d` + '\n')
305309
self.memo[d] = object
306310
try:
307311
getstate = object.__getstate__
@@ -313,6 +317,14 @@ def save_inst(self, object):
313317
self.write(BUILD)
314318
dispatch[InstanceType] = save_inst
315319

320+
def save_class(self, object):
321+
d = id(object)
322+
module = whichmodule(object)
323+
name = object.__name__
324+
self.write(CLASS + module + '\n' + name + '\n' +
325+
PUT + `d` + '\n')
326+
dispatch[ClassType] = save_class
327+
316328

317329
classmap = {}
318330

@@ -410,25 +422,36 @@ def load_inst(self):
410422
del self.stack[k:]
411423
module = self.readline()[:-1]
412424
name = self.readline()[:-1]
425+
klass = self.find_class(module, name)
426+
value = apply(klass, args)
427+
self.stack.append(value)
428+
dispatch[INST] = load_inst
429+
430+
def load_class(self):
431+
module = self.readline()[:-1]
432+
name = self.readline()[:-1]
433+
klass = self.find_class(module, name)
434+
self.stack.append(klass)
435+
return klass
436+
dispatch[CLASS] = load_class
437+
438+
def find_class(self, module, name):
413439
env = {}
414440
try:
415441
exec 'from %s import %s' % (module, name) in env
416442
except ImportError:
417443
raise SystemError, \
418444
"Failed to import class %s from module %s" % \
419445
(name, module)
420-
else:
421-
klass = env[name]
422-
if type(klass) != ClassType:
423-
raise SystemError, \
424-
"imported object %s from module %s is not a class" % \
425-
(name, module)
426-
value = apply(klass, args)
427-
self.stack.append(value)
428-
dispatch[INST] = load_inst
446+
klass = env[name]
447+
if type(klass) != ClassType:
448+
raise SystemError, \
449+
"Imported object %s from module %s is not a class" % \
450+
(name, module)
451+
return klass
429452

430453
def load_pop(self):
431-
del self.stack[-1]
454+
del self.stack[-1]
432455
dispatch[POP] = load_pop
433456

434457
def load_dup(self):
@@ -482,6 +505,28 @@ def load_stop(self):
482505
dispatch[STOP] = load_stop
483506

484507

508+
# Shorthands
509+
510+
def dump(object, file):
511+
Pickler(file).dump(object)
512+
513+
def dumps(object):
514+
import StringIO
515+
file = StringIO.StringIO()
516+
Pickler(file).dump(object)
517+
return file.getvalue()
518+
519+
def load(file):
520+
return Unpickler(file).load()
521+
522+
def loads(str):
523+
import StringIO
524+
file = StringIO.StringIO(str)
525+
return Unpickler(file).load()
526+
527+
528+
# The rest is used for testing only
529+
485530
class C:
486531
def __cmp__(self, other):
487532
return cmp(self.__dict__, other.__dict__)

0 commit comments

Comments
 (0)