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
829d155f
Commit
829d155f
authored
Apr 13, 2015
by
Jason Madden
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix a race condition adding items to the pickle cache; explicitly support Jython too.
parent
80e0c6ee
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
68 additions
and
18 deletions
+68
-18
CHANGES.rst
CHANGES.rst
+3
-1
persistent/picklecache.py
persistent/picklecache.py
+13
-1
persistent/tests/test_persistence.py
persistent/tests/test_persistence.py
+2
-1
persistent/tests/test_picklecache.py
persistent/tests/test_picklecache.py
+20
-2
persistent/tests/test_timestamp.py
persistent/tests/test_timestamp.py
+20
-4
setup.py
setup.py
+1
-0
tox.ini
tox.ini
+9
-9
No files found.
CHANGES.rst
View file @
829d155f
...
...
@@ -7,10 +7,12 @@
- The Python implementation of ``Persistent`` and ``PickleCache`` now
behave more similarly to the C implementation. In particular, the
Python version can now run the complete ZODB
unit test suite
.
Python version can now run the complete ZODB
and ZEO test suites
.
- Fix the hashcode of the Python ``TimeStamp`` on 32-bit platforms.
- Add support for Jython 2.7.
4.0.9 (2015-04-08)
------------------
...
...
persistent/picklecache.py
View file @
829d155f
...
...
@@ -46,6 +46,14 @@ _SWEEPABLE_TYPES = (Persistent,)
# Tests may modify this
_SWEEP_NEEDS_GC
=
not
hasattr
(
sys
,
'getrefcount'
)
# On Jython, we need to explicitly ask it to monitor
# objects if we want a more deterministic GC
if
hasattr
(
gc
,
'monitorObject'
):
#pragma: no cover
_gc_monitor
=
gc
.
monitorObject
else
:
def
_gc_monitor
(
o
):
pass
class
RingNode
(
object
):
# 32 byte fixed size wrapper.
__slots__
=
(
'object'
,
'next'
,
'prev'
)
...
...
@@ -134,7 +142,10 @@ class PickleCache(object):
# XXX
if
oid
in
self
.
persistent_classes
or
oid
in
self
.
data
:
if
self
.
data
[
oid
]
is
not
value
:
# Have to be careful here, a GC might have just run
# and cleaned up the object
existing_data
=
self
.
get
(
oid
)
if
existing_data
is
not
None
and
existing_data
is
not
value
:
# Raise the same type of exception as the C impl with the same
# message.
raise
ValueError
(
'A different object already has the same oid'
)
...
...
@@ -153,6 +164,7 @@ class PickleCache(object):
self
.
persistent_classes
[
oid
]
=
value
else
:
self
.
data
[
oid
]
=
value
_gc_monitor
(
value
)
self
.
mru
(
oid
)
def
__delitem__
(
self
,
oid
):
...
...
persistent/tests/test_persistence.py
View file @
829d155f
...
...
@@ -18,6 +18,7 @@ import platform
import
sys
py_impl
=
getattr
(
platform
,
'python_implementation'
,
lambda
:
None
)
_is_pypy3
=
py_impl
()
==
'PyPy'
and
sys
.
version_info
[
0
]
>
2
_is_jython
=
py_impl
()
==
'Jython'
#pylint: disable=R0904,W0212,E1101
...
...
@@ -932,7 +933,7 @@ class _Persistent_Base(object):
self
.
assertEqual
(
inst
.
baz
,
'bam'
)
self
.
assertEqual
(
inst
.
qux
,
'spam'
)
if
not
_is_pypy3
:
if
not
_is_pypy3
and
not
_is_jython
:
def
test___setstate___interns_dict_keys
(
self
):
class
Derived
(
self
.
_getTargetClass
()):
pass
...
...
persistent/tests/test_picklecache.py
View file @
829d155f
...
...
@@ -12,7 +12,8 @@
#
##############################################################################
import
unittest
import
gc
_is_jython
=
hasattr
(
gc
,
'getJythonGCFlags'
)
_marker
=
object
()
class
PickleCacheTests
(
unittest
.
TestCase
):
...
...
@@ -986,7 +987,22 @@ class PickleCacheTests(unittest.TestCase):
# Nothing to test, just that it doesn't break
cache
.
_invalidate
(
p
.
_p_oid
)
def
test_cache_garbage_collection_bytes_also_deactivates_object
(
self
):
if
_is_jython
:
def
with_deterministic_gc
(
f
):
def
test
(
self
):
old_flags
=
gc
.
getMonitorGlobal
()
gc
.
setMonitorGlobal
(
True
)
try
:
f
(
self
,
force_collect
=
True
)
finally
:
gc
.
setMonitorGlobal
(
old_flags
)
return
test
else
:
def
with_deterministic_gc
(
f
):
return
f
@
with_deterministic_gc
def
test_cache_garbage_collection_bytes_also_deactivates_object
(
self
,
force_collect
=
False
):
from
persistent.interfaces
import
UPTODATE
from
persistent._compat
import
_b
cache
=
self
.
_makeOne
()
...
...
@@ -1028,6 +1044,8 @@ class PickleCacheTests(unittest.TestCase):
# It also shrank the measured size of the cache;
# this would fail under PyPy if _SWEEP_NEEDS_GC was False
if
force_collect
:
gc
.
collect
()
self
.
assertEqual
(
len
(
cache
),
1
)
def
test_invalidate_persistent_class_calls_p_invalidate
(
self
):
...
...
persistent/tests/test_timestamp.py
View file @
829d155f
...
...
@@ -14,6 +14,11 @@
import
operator
import
unittest
import
platform
py_impl
=
getattr
(
platform
,
'python_implementation'
,
lambda
:
None
)
_is_jython
=
py_impl
()
==
'Jython'
class
Test__UTC
(
unittest
.
TestCase
):
def
_getTargetClass
(
self
):
...
...
@@ -271,26 +276,37 @@ class PyAndCComparisonTests(unittest.TestCase):
py
=
self
.
_makePy
(
*
self
.
now_ts_args
)
self
.
assertEqual
(
hash
(
py
),
bit_32_hash
)
persistent
.
timestamp
.
c_long
=
ctypes
.
c_int64
# call __hash__ directly to avoid interpreter truncation
# in hash() on 32-bit platforms
if
not
_is_jython
:
self
.
assertEqual
(
py
.
__hash__
(),
bit_64_hash
)
else
:
# Jython 2.7's ctypes module doesn't properly
# implement the 'value' attribute by truncating.
# (It does for native calls, but not visibly to Python).
# Therefore we get back the full python long. The actual
# hash() calls are correct, though, because the JVM uses
# 32-bit ints for its hashCode methods.
self
.
assertEqual
(
py
.
__hash__
(),
384009219096809580920179179233996861765753210540033L
)
finally
:
persistent
.
timestamp
.
c_long
=
orig_c_long
# These are *usually* aliases, but aren't required
# to be
if
orig_c_long
is
ctypes
.
c_int32
:
self
.
assertEqual
(
py
.
__hash__
(),
bit_32_hash
)
elif
orig_c_long
is
ctypes
.
c_int64
:
self
.
assertEqual
(
py
.
__hash__
(),
bit_64_hash
)
else
:
self
.
fail
(
"Unknown bitness"
)
def
test_hash_equal_constants
(
self
):
# The simple constants make it easier to diagnose
# a difference in algorithms
import
persistent.timestamp
import
ctypes
is_32_bit
=
persistent
.
timestamp
.
c_long
==
ctypes
.
c_int32
# We get 32-bit hash values of 32-bit platforms, or on the JVM
is_32_bit
=
persistent
.
timestamp
.
c_long
==
ctypes
.
c_int32
or
_is_jython
c
,
py
=
self
.
_make_C_and_Py
(
b'
\
x00
\
x00
\
x00
\
x00
\
x00
\
x00
\
x00
\
x00
'
)
self
.
assertEqual
(
hash
(
c
),
8
)
...
...
setup.py
View file @
829d155f
...
...
@@ -87,6 +87,7 @@ setup(name='persistent',
'Programming Language :: Python :: 3.4'
,
"Programming Language :: Python :: Implementation :: CPython"
,
"Programming Language :: Python :: Implementation :: PyPy"
,
"Programming Language :: Python :: Implementation :: Jython"
,
"Framework :: ZODB"
,
"Topic :: Database"
,
"Topic :: Software Development :: Libraries :: Python Modules"
,
...
...
tox.ini
View file @
829d155f
[tox]
envlist
=
# Jython
support pending 2.7 support, due 2012-07-15 or so. See:
#
http://fwierzbicki.blogspot.com/2012/03/adconion-to-fund-jython-27.html
# py26,py27,py
32,jython,pypy
,coverage,docs
# Jython
2.7rc2 does work, but unfortunately has an issue running
#
with Tox 1.9.2 (http://bugs.jython.org/issue2325)
# py26,py27,py
27-pure,pypy,py32,py33,py34,pypy3,jython
,coverage,docs
py26,py27,py27-pure,pypy,py32,py33,py34,pypy3,coverage,docs
[testenv]
...
...
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