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

Skip to content

Commit e276339

Browse files
committed
Implement an idea by Paul Rubin:
Change pickling format for bools to use a backwards compatible encoding. This means you can pickle True or False on Python 2.3 and Python 2.2 or before will read it back as 1 or 0. The code used for pickling bools before would create pickles that could not be read in previous Python versions.
1 parent d15a0a0 commit e276339

3 files changed

Lines changed: 29 additions & 29 deletions

File tree

Lib/pickle.py

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ def __init__(self, value):
101101
EMPTY_TUPLE = ')'
102102
SETITEMS = 'u'
103103
BINFLOAT = 'G'
104-
TRUE = 'Z'
105-
FALSE = 'z'
104+
TRUE = 'I01\n'
105+
FALSE = 'I00\n'
106106

107107

108108
__all__.extend([x for x in dir() if re.match("[A-Z][A-Z0-9_]+$",x)])
@@ -639,20 +639,18 @@ def load_none(self):
639639
self.append(None)
640640
dispatch[NONE] = load_none
641641

642-
def load_false(self):
643-
self.append(False)
644-
dispatch[FALSE] = load_false
645-
646-
def load_true(self):
647-
self.append(True)
648-
dispatch[TRUE] = load_true
649-
650642
def load_int(self):
651643
data = self.readline()
652-
try:
653-
self.append(int(data))
654-
except ValueError:
655-
self.append(long(data))
644+
if data == FALSE[1:]:
645+
val = False
646+
elif data == TRUE[1:]:
647+
val = True
648+
else:
649+
try:
650+
val = int(data)
651+
except ValueError:
652+
val = long(data)
653+
self.append(val)
656654
dispatch[INT] = load_int
657655

658656
def load_binint(self):

Lib/test/test_bool.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,5 +224,11 @@ class C(bool):
224224
veris(cPickle.loads(pickle.dumps(True)), True)
225225
veris(cPickle.loads(pickle.dumps(False)), False)
226226

227+
# Test for specific backwards-compatible pickle values
228+
vereq(pickle.dumps(True), "I01\n.")
229+
vereq(pickle.dumps(False), "I00\n.")
230+
vereq(cPickle.dumps(True), "I01\n.")
231+
vereq(cPickle.dumps(False), "I00\n.")
232+
227233
if verbose:
228234
print "All OK"

Modules/cPickle.c

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ LONG Long (unbounded) integer; repr(i), then newline.
7777
#define TUPLE 't'
7878
#define EMPTY_TUPLE ')'
7979
#define SETITEMS 'u'
80-
#define TRUE 'Z'
81-
#define FALSE 'z'
80+
#define TRUE "I01\n"
81+
#define FALSE "I00\n"
8282

8383

8484
static char MARKv = MARK;
@@ -936,10 +936,11 @@ save_none(Picklerobject *self, PyObject *args)
936936
static int
937937
save_bool(Picklerobject *self, PyObject *args)
938938
{
939-
static char buf[2] = {FALSE, TRUE};
939+
static char *buf[2] = {FALSE, TRUE};
940+
static char len[2] = {sizeof(FALSE)-1, sizeof(TRUE)-1};
940941
long l = PyInt_AS_LONG((PyIntObject *)args);
941942

942-
if ((*self->write_func)(self, buf + l, 1) < 0)
943+
if ((*self->write_func)(self, buf[l], len[l]) < 0)
943944
return -1;
944945

945946
return 0;
@@ -2655,7 +2656,12 @@ load_int(Unpicklerobject *self)
26552656
}
26562657
}
26572658
else {
2658-
if (!( py_int = PyInt_FromLong(l))) goto finally;
2659+
if (len == 3 && (l == 0 || l == 1)) {
2660+
if (!( py_int = PyBool_FromLong(l))) goto finally;
2661+
}
2662+
else {
2663+
if (!( py_int = PyInt_FromLong(l))) goto finally;
2664+
}
26592665
}
26602666

26612667
free(s);
@@ -3763,16 +3769,6 @@ load(Unpicklerobject *self)
37633769
break;
37643770
continue;
37653771

3766-
case FALSE:
3767-
if (load_false(self) < 0)
3768-
break;
3769-
continue;
3770-
3771-
case TRUE:
3772-
if (load_true(self) < 0)
3773-
break;
3774-
continue;
3775-
37763772
case BININT:
37773773
if (load_binint(self) < 0)
37783774
break;

0 commit comments

Comments
 (0)