Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
da87e45a
Kaydet (Commit)
da87e45a
authored
Kas 07, 2015
tarafından
Serhiy Storchaka
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Issue #892902: Fixed pickling recursive objects.
üst
43415ba5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
145 additions
and
30 deletions
+145
-30
pickle.py
Lib/pickle.py
+7
-1
pickletester.py
Lib/test/pickletester.py
+101
-4
test_cpickle.py
Lib/test/test_cpickle.py
+14
-25
NEWS
Misc/NEWS
+2
-0
cPickle.c
Modules/cPickle.c
+21
-0
No files found.
Lib/pickle.py
Dosyayı görüntüle @
da87e45a
...
...
@@ -402,7 +402,13 @@ class Pickler:
write
(
REDUCE
)
if
obj
is
not
None
:
self
.
memoize
(
obj
)
# If the object is already in the memo, this means it is
# recursive. In this case, throw away everything we put on the
# stack, and fetch the object back from the memo.
if
id
(
obj
)
in
self
.
memo
:
write
(
POP
+
self
.
get
(
self
.
memo
[
id
(
obj
)][
0
]))
else
:
self
.
memoize
(
obj
)
# More new special cases (that work with older protocols as
# well): when __reduce__ returns a tuple with 4 or 5 items,
...
...
Lib/test/pickletester.py
Dosyayı görüntüle @
da87e45a
...
...
@@ -117,6 +117,18 @@ class E(C):
def
__getinitargs__
(
self
):
return
()
class
H
(
object
):
pass
# Hashable mutable key
class
K
(
object
):
def
__init__
(
self
,
value
):
self
.
value
=
value
def
__reduce__
(
self
):
# Shouldn't support the recursion itself
return
K
,
(
self
.
value
,)
import
__main__
__main__
.
C
=
C
C
.
__module__
=
"__main__"
...
...
@@ -124,6 +136,10 @@ __main__.D = D
D
.
__module__
=
"__main__"
__main__
.
E
=
E
E
.
__module__
=
"__main__"
__main__
.
H
=
H
H
.
__module__
=
"__main__"
__main__
.
K
=
K
K
.
__module__
=
"__main__"
class
myint
(
int
):
def
__init__
(
self
,
x
):
...
...
@@ -676,18 +692,21 @@ class AbstractPickleTests(unittest.TestCase):
for
proto
in
protocols
:
s
=
self
.
dumps
(
l
,
proto
)
x
=
self
.
loads
(
s
)
self
.
assertIsInstance
(
x
,
list
)
self
.
assertEqual
(
len
(
x
),
1
)
self
.
assert
True
(
x
is
x
[
0
]
)
self
.
assert
Is
(
x
[
0
],
x
)
def
test_recursive_tuple
(
self
):
def
test_recursive_tuple
_and_list
(
self
):
t
=
([],)
t
[
0
]
.
append
(
t
)
for
proto
in
protocols
:
s
=
self
.
dumps
(
t
,
proto
)
x
=
self
.
loads
(
s
)
self
.
assertIsInstance
(
x
,
tuple
)
self
.
assertEqual
(
len
(
x
),
1
)
self
.
assertIsInstance
(
x
[
0
],
list
)
self
.
assertEqual
(
len
(
x
[
0
]),
1
)
self
.
assert
True
(
x
is
x
[
0
][
0
]
)
self
.
assert
Is
(
x
[
0
][
0
],
x
)
def
test_recursive_dict
(
self
):
d
=
{}
...
...
@@ -695,8 +714,50 @@ class AbstractPickleTests(unittest.TestCase):
for
proto
in
protocols
:
s
=
self
.
dumps
(
d
,
proto
)
x
=
self
.
loads
(
s
)
self
.
assertIsInstance
(
x
,
dict
)
self
.
assertEqual
(
x
.
keys
(),
[
1
])
self
.
assertTrue
(
x
[
1
]
is
x
)
self
.
assertIs
(
x
[
1
],
x
)
def
test_recursive_dict_key
(
self
):
d
=
{}
k
=
K
(
d
)
d
[
k
]
=
1
for
proto
in
protocols
:
s
=
self
.
dumps
(
d
,
proto
)
x
=
self
.
loads
(
s
)
self
.
assertIsInstance
(
x
,
dict
)
self
.
assertEqual
(
len
(
x
.
keys
()),
1
)
self
.
assertIsInstance
(
x
.
keys
()[
0
],
K
)
self
.
assertIs
(
x
.
keys
()[
0
]
.
value
,
x
)
def
test_recursive_list_subclass
(
self
):
y
=
MyList
()
y
.
append
(
y
)
s
=
self
.
dumps
(
y
,
2
)
x
=
self
.
loads
(
s
)
self
.
assertIsInstance
(
x
,
MyList
)
self
.
assertEqual
(
len
(
x
),
1
)
self
.
assertIs
(
x
[
0
],
x
)
def
test_recursive_dict_subclass
(
self
):
d
=
MyDict
()
d
[
1
]
=
d
s
=
self
.
dumps
(
d
,
2
)
x
=
self
.
loads
(
s
)
self
.
assertIsInstance
(
x
,
MyDict
)
self
.
assertEqual
(
x
.
keys
(),
[
1
])
self
.
assertIs
(
x
[
1
],
x
)
def
test_recursive_dict_subclass_key
(
self
):
d
=
MyDict
()
k
=
K
(
d
)
d
[
k
]
=
1
s
=
self
.
dumps
(
d
,
2
)
x
=
self
.
loads
(
s
)
self
.
assertIsInstance
(
x
,
MyDict
)
self
.
assertEqual
(
len
(
x
.
keys
()),
1
)
self
.
assertIsInstance
(
x
.
keys
()[
0
],
K
)
self
.
assertIs
(
x
.
keys
()[
0
]
.
value
,
x
)
def
test_recursive_inst
(
self
):
i
=
C
()
...
...
@@ -721,6 +782,42 @@ class AbstractPickleTests(unittest.TestCase):
self
.
assertEqual
(
x
[
0
]
.
attr
.
keys
(),
[
1
])
self
.
assertTrue
(
x
[
0
]
.
attr
[
1
]
is
x
)
def
check_recursive_collection_and_inst
(
self
,
factory
):
h
=
H
()
y
=
factory
([
h
])
h
.
attr
=
y
for
proto
in
protocols
:
s
=
self
.
dumps
(
y
,
proto
)
x
=
self
.
loads
(
s
)
self
.
assertIsInstance
(
x
,
type
(
y
))
self
.
assertEqual
(
len
(
x
),
1
)
self
.
assertIsInstance
(
list
(
x
)[
0
],
H
)
self
.
assertIs
(
list
(
x
)[
0
]
.
attr
,
x
)
def
test_recursive_list_and_inst
(
self
):
self
.
check_recursive_collection_and_inst
(
list
)
def
test_recursive_tuple_and_inst
(
self
):
self
.
check_recursive_collection_and_inst
(
tuple
)
def
test_recursive_dict_and_inst
(
self
):
self
.
check_recursive_collection_and_inst
(
dict
.
fromkeys
)
def
test_recursive_set_and_inst
(
self
):
self
.
check_recursive_collection_and_inst
(
set
)
def
test_recursive_frozenset_and_inst
(
self
):
self
.
check_recursive_collection_and_inst
(
frozenset
)
def
test_recursive_list_subclass_and_inst
(
self
):
self
.
check_recursive_collection_and_inst
(
MyList
)
def
test_recursive_tuple_subclass_and_inst
(
self
):
self
.
check_recursive_collection_and_inst
(
MyTuple
)
def
test_recursive_dict_subclass_and_inst
(
self
):
self
.
check_recursive_collection_and_inst
(
MyDict
.
fromkeys
)
if
have_unicode
:
def
test_unicode
(
self
):
endcases
=
[
u''
,
u'<
\\
u>'
,
u'<
\\\u1234
>'
,
u'<
\n
>'
,
...
...
Lib/test/test_cpickle.py
Dosyayı görüntüle @
da87e45a
import
cPickle
import
cStringIO
import
io
import
functools
import
unittest
from
test.pickletester
import
(
AbstractUnpickleTests
,
AbstractPickleTests
,
...
...
@@ -151,31 +152,6 @@ class cPickleFastPicklerTests(AbstractPickleTests):
finally
:
self
.
close
(
f
)
def
test_recursive_list
(
self
):
self
.
assertRaises
(
ValueError
,
AbstractPickleTests
.
test_recursive_list
,
self
)
def
test_recursive_tuple
(
self
):
self
.
assertRaises
(
ValueError
,
AbstractPickleTests
.
test_recursive_tuple
,
self
)
def
test_recursive_inst
(
self
):
self
.
assertRaises
(
ValueError
,
AbstractPickleTests
.
test_recursive_inst
,
self
)
def
test_recursive_dict
(
self
):
self
.
assertRaises
(
ValueError
,
AbstractPickleTests
.
test_recursive_dict
,
self
)
def
test_recursive_multi
(
self
):
self
.
assertRaises
(
ValueError
,
AbstractPickleTests
.
test_recursive_multi
,
self
)
def
test_nonrecursive_deep
(
self
):
# If it's not cyclic, it should pickle OK even if the nesting
# depth exceeds PY_CPICKLE_FAST_LIMIT. That happens to be
...
...
@@ -187,6 +163,19 @@ class cPickleFastPicklerTests(AbstractPickleTests):
b
=
self
.
loads
(
self
.
dumps
(
a
))
self
.
assertEqual
(
a
,
b
)
for
name
in
dir
(
AbstractPickleTests
):
if
name
.
startswith
(
'test_recursive_'
):
func
=
getattr
(
AbstractPickleTests
,
name
)
if
'_subclass'
in
name
and
'_and_inst'
not
in
name
:
assert_args
=
RuntimeError
,
'maximum recursion depth exceeded'
else
:
assert_args
=
ValueError
,
"can't pickle cyclic objects"
def
wrapper
(
self
,
func
=
func
,
assert_args
=
assert_args
):
with
self
.
assertRaisesRegexp
(
*
assert_args
):
func
(
self
)
functools
.
update_wrapper
(
wrapper
,
func
)
setattr
(
cPickleFastPicklerTests
,
name
,
wrapper
)
class
cStringIOCPicklerFastTests
(
cStringIOMixin
,
cPickleFastPicklerTests
):
pass
...
...
Misc/NEWS
Dosyayı görüntüle @
da87e45a
...
...
@@ -46,6 +46,8 @@ Core and Builtins
Library
-------
- Issue #892902: Fixed pickling recursive objects.
- Issue #18010: Fix the pydoc GUI'
s
search
function
to
handle
exceptions
from
importing
packages
.
...
...
Modules/cPickle.c
Dosyayı görüntüle @
da87e45a
...
...
@@ -2533,6 +2533,27 @@ save_reduce(Picklerobject *self, PyObject *args, PyObject *fn, PyObject *ob)
/* Memoize. */
/* XXX How can ob be NULL? */
if
(
ob
!=
NULL
)
{
/* If the object is already in the memo, this means it is
recursive. In this case, throw away everything we put on the
stack, and fetch the object back from the memo. */
if
(
Py_REFCNT
(
ob
)
>
1
&&
!
self
->
fast
)
{
PyObject
*
py_ob_id
=
PyLong_FromVoidPtr
(
ob
);
if
(
!
py_ob_id
)
return
-
1
;
if
(
PyDict_GetItem
(
self
->
memo
,
py_ob_id
))
{
const
char
pop_op
=
POP
;
if
(
self
->
write_func
(
self
,
&
pop_op
,
1
)
<
0
||
get
(
self
,
py_ob_id
)
<
0
)
{
Py_DECREF
(
py_ob_id
);
return
-
1
;
}
Py_DECREF
(
py_ob_id
);
return
0
;
}
Py_DECREF
(
py_ob_id
);
if
(
PyErr_Occurred
())
return
-
1
;
}
if
(
state
&&
!
PyDict_Check
(
state
))
{
if
(
put2
(
self
,
ob
)
<
0
)
return
-
1
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment