Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
persistent
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
persistent
Commits
7bd85c18
Commit
7bd85c18
authored
Mar 21, 2015
by
David Glick
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Intern keys in `__setstate__`
Refs zopefoundation/persistent#15
parent
7a57ed9b
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
43 additions
and
3 deletions
+43
-3
CHANGES.rst
CHANGES.rst
+3
-0
persistent/_compat.h
persistent/_compat.h
+4
-0
persistent/_compat.py
persistent/_compat.py
+3
-0
persistent/cPersistence.c
persistent/cPersistence.c
+16
-2
persistent/persistence.py
persistent/persistence.py
+3
-1
persistent/tests/test_persistence.py
persistent/tests/test_persistence.py
+14
-0
No files found.
CHANGES.rst
View file @
7bd85c18
...
...
@@ -4,6 +4,9 @@
4.0.9 (unreleased)
------------------
- Intern keys of object state in `__setstate__` to reduce memory usage
when unpickling multiple objects with the same attributes.
- Add support for PyPy3.
- 100% branch coverage.
...
...
persistent/_compat.h
View file @
7bd85c18
...
...
@@ -23,6 +23,8 @@
#ifdef PY3K
#define INTERN PyUnicode_InternFromString
#define INTERN_INPLACE PyUnicode_InternInPlace
#define NATIVE_CHECK_EXACT PyUnicode_CheckExact
#define NATIVE_FROM_STRING_AND_SIZE PyUnicode_FromStringAndSize
#define Py_TPFLAGS_HAVE_RICHCOMPARE 0
...
...
@@ -34,6 +36,8 @@
#else
#define INTERN PyString_InternFromString
#define INTERN_INPLACE PyString_InternInPlace
#define NATIVE_CHECK_EXACT PyString_CheckExact
#define NATIVE_FROM_STRING_AND_SIZE PyString_FromStringAndSize
#define INT_FROM_LONG(x) PyInt_FromLong(x)
...
...
persistent/_compat.py
View file @
7bd85c18
...
...
@@ -18,6 +18,7 @@ if sys.version_info[0] > 2: #pragma NO COVER
import
copyreg
as
copy_reg
from
collections
import
UserDict
as
IterableUserDict
from
collections
import
UserList
from
sys
import
intern
def
_u
(
s
):
return
s
...
...
@@ -52,3 +53,5 @@ else: #pragma NO COVER
PYTHON3
=
False
PYTHON2
=
True
intern
=
intern
persistent/cPersistence.c
View file @
7bd85c18
...
...
@@ -534,6 +534,8 @@ pickle___setstate__(PyObject *self, PyObject *state)
if
(
state
!=
Py_None
)
{
PyObject
**
dict
;
PyObject
*
d_key
,
*
d_value
;
Py_ssize_t
i
;
dict
=
_PyObject_GetDictPtr
(
self
);
...
...
@@ -552,8 +554,20 @@ pickle___setstate__(PyObject *self, PyObject *state)
}
PyDict_Clear
(
*
dict
);
if
(
PyDict_Update
(
*
dict
,
state
)
<
0
)
return
NULL
;
i
=
0
;
while
(
PyDict_Next
(
state
,
&
i
,
&
d_key
,
&
d_value
))
{
/* normally the keys for instance attributes are
interned. we should try to do that here. */
Py_INCREF
(
d_key
);
if
(
NATIVE_CHECK_EXACT
(
d_key
))
INTERN_INPLACE
(
&
d_key
);
if
(
PyObject_SetItem
(
*
dict
,
d_key
,
d_value
)
<
0
)
{
Py_DECREF
(
d_key
);
return
NULL
;
}
Py_DECREF
(
d_key
);
}
}
if
(
slots
&&
pickle_setattrs_from_dict
(
self
,
slots
)
<
0
)
...
...
persistent/persistence.py
View file @
7bd85c18
...
...
@@ -25,6 +25,7 @@ from persistent.interfaces import SERIAL_TYPE
from
persistent.timestamp
import
TimeStamp
from
persistent.timestamp
import
_ZERO
from
persistent._compat
import
copy_reg
from
persistent._compat
import
intern
_INITIAL_SERIAL
=
_ZERO
...
...
@@ -313,7 +314,8 @@ class Persistent(object):
if
idict
is
None
:
raise
TypeError
(
'No instance dict'
)
idict
.
clear
()
idict
.
update
(
inst_dict
)
for
k
,
v
in
inst_dict
.
items
():
idict
[
intern
(
k
)]
=
v
slotnames
=
self
.
_slotnames
()
if
slotnames
:
for
k
,
v
in
slots
.
items
():
...
...
persistent/tests/test_persistence.py
View file @
7bd85c18
...
...
@@ -863,6 +863,20 @@ class _Persistent_Base(object):
self
.
assertEqual
(
inst
.
baz
,
'bam'
)
self
.
assertEqual
(
inst
.
qux
,
'spam'
)
def
test___setstate___interns_dict_keys
(
self
):
class
Derived
(
self
.
_getTargetClass
()):
pass
inst1
=
Derived
()
inst2
=
Derived
()
key1
=
'key'
key2
=
'ke'
;
key2
+=
'y'
# construct in a way that won't intern the literal
self
.
assertFalse
(
key1
is
key2
)
inst1
.
__setstate__
({
key1
:
1
})
inst2
.
__setstate__
({
key2
:
2
})
key1
=
list
(
inst1
.
__dict__
.
keys
())[
0
]
key2
=
list
(
inst2
.
__dict__
.
keys
())[
0
]
self
.
assertTrue
(
key1
is
key2
)
def
test___reduce__
(
self
):
from
persistent._compat
import
copy_reg
inst
=
self
.
_makeOne
()
...
...
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