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
ba3c0022
Commit
ba3c0022
authored
Apr 08, 2015
by
Jason Madden
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
100% coverage for picklecache.
parent
e3a9b13a
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
136 additions
and
12 deletions
+136
-12
persistent/picklecache.py
persistent/picklecache.py
+11
-12
persistent/tests/test_picklecache.py
persistent/tests/test_picklecache.py
+125
-0
No files found.
persistent/picklecache.py
View file @
ba3c0022
...
...
@@ -22,9 +22,11 @@ from persistent.interfaces import IPickleCache
from
persistent.interfaces
import
OID_TYPE
from
persistent.interfaces
import
UPTODATE
from
persistent
import
Persistent
from
persistent.persistence
import
_estimated_size_in_24_bits
# Tests may modify this to add additional types
_CACHEABLE_TYPES
=
(
type
,
Persistent
)
_SWEEPABLE_TYPES
=
(
Persistent
,)
class
RingNode
(
object
):
# 32 byte fixed size wrapper.
...
...
@@ -38,7 +40,7 @@ def _sweeping_ring(f):
def
locked
(
self
,
*
args
,
**
kwargs
):
self
.
_is_sweeping_ring
=
True
try
:
f
(
self
,
*
args
,
**
kwargs
)
return
f
(
self
,
*
args
,
**
kwargs
)
finally
:
self
.
_is_sweeping_ring
=
False
return
locked
...
...
@@ -114,7 +116,7 @@ class PickleCache(object):
raise
ValueError
(
'A different object already has the same oid'
)
# Match the C impl: it requires a jar
jar
=
getattr
(
value
,
'_p_jar'
,
None
)
if
jar
is
None
and
type
(
value
)
is
not
type
:
if
jar
is
None
and
not
isinstance
(
value
,
type
)
:
raise
ValueError
(
"Cached object jar missing"
)
# It also requires that it cannot be cached more than one place
existing_cache
=
getattr
(
jar
,
'_cache'
,
None
)
...
...
@@ -162,7 +164,7 @@ class PickleCache(object):
# accessess during sweeping, such as with an
# overridden _p_deactivate, don't mutate the ring
# because that could leave it inconsistent
return
return
False
# marker return for tests
node
=
self
.
ring
.
next
while
node
is
not
self
.
ring
and
node
.
object
.
_p_oid
!=
oid
:
node
=
node
.
next
...
...
@@ -220,12 +222,14 @@ class PickleCache(object):
target2
=
size
-
1
-
(
size
//
self
.
drain_resistance
)
if
target2
<
target
:
target
=
target2
self
.
_sweep
(
target
,
self
.
cache_size_bytes
)
# return value for testing
return
self
.
_sweep
(
target
,
self
.
cache_size_bytes
)
def
full_sweep
(
self
,
target
=
None
):
""" See IPickleCache.
"""
self
.
_sweep
(
0
)
# return value for testing
return
self
.
_sweep
(
0
)
minimize
=
full_sweep
...
...
@@ -355,8 +359,8 @@ class PickleCache(object):
if
(
self
.
_persistent_deactivate_ran
# Test-cases sneak in non-Persistent objects, sigh, so naturally
# they don't cooperate (without this check a bunch of test_picklecache
#breaks)
or
not
isinstance
(
node
.
object
,
Persistent
)):
#
breaks)
or
not
isinstance
(
node
.
object
,
_SWEEPABLE_TYPES
)):
ejected
+=
1
self
.
__remove_from_ring
(
node
)
node
=
node
.
next
...
...
@@ -394,8 +398,3 @@ class PickleCache(object):
node
.
object
=
None
node
.
prev
.
next
,
node
.
next
.
prev
=
node
.
next
,
node
.
prev
self
.
non_ghost_count
-=
1
def
_estimated_size_in_24_bits
(
value
):
if
value
>
1073741696
:
return
16777215
return
(
value
//
64
)
+
1
persistent/tests/test_picklecache.py
View file @
ba3c0022
...
...
@@ -858,6 +858,131 @@ class PickleCacheTests(unittest.TestCase):
self
.
assertEqual
(
typ
,
'DummyPersistent'
)
self
.
assertEqual
(
state
,
GHOST
)
def
test_init_with_cacheless_jar
(
self
):
# Sometimes ZODB tests pass objects that don't
# have a _cache
class
Jar
(
object
):
was_set
=
False
def
__setattr__
(
self
,
name
,
value
):
if
name
==
'_cache'
:
object
.
__setattr__
(
self
,
'was_set'
,
True
)
raise
AttributeError
(
name
)
jar
=
Jar
()
self
.
_makeOne
(
jar
)
self
.
assertTrue
(
jar
.
was_set
)
def
test_setting_non_persistent_item
(
self
):
cache
=
self
.
_makeOne
()
try
:
cache
[
None
]
=
object
()
except
TypeError
as
e
:
self
.
assertEqual
(
str
(
e
),
"Cache values must be persistent objects."
)
else
:
self
.
fail
(
"Should raise TypeError"
)
def
test_setting_without_jar
(
self
):
cache
=
self
.
_makeOne
()
p
=
self
.
_makePersist
(
jar
=
None
)
try
:
cache
[
p
.
_p_oid
]
=
p
except
ValueError
as
e
:
self
.
assertEqual
(
str
(
e
),
"Cached object jar missing"
)
else
:
self
.
fail
(
"Should raise ValueError"
)
def
test_setting_already_cached
(
self
):
cache1
=
self
.
_makeOne
()
p
=
self
.
_makePersist
(
jar
=
cache1
.
jar
)
cache1
[
p
.
_p_oid
]
=
p
cache2
=
self
.
_makeOne
()
try
:
cache2
[
p
.
_p_oid
]
=
p
except
ValueError
as
e
:
self
.
assertEqual
(
str
(
e
),
"Object already in another cache"
)
else
:
self
.
fail
(
"Should raise value error"
)
def
test_cannot_update_mru_while_already_locked
(
self
):
cache
=
self
.
_makeOne
()
cache
.
_is_sweeping_ring
=
True
updated
=
cache
.
mru
(
None
)
self
.
assertFalse
(
updated
)
def
test_update_object_size_estimation_simple
(
self
):
cache
=
self
.
_makeOne
()
p
=
self
.
_makePersist
(
jar
=
cache
.
jar
)
cache
[
p
.
_p_oid
]
=
p
# It accesses the private version directory to bypass
# the bit conversion
# Note that the _p_estimated_size is set *after*
# the update call is made in ZODB's serialize
p
.
_Persistent__size
=
0
cache
.
update_object_size_estimation
(
p
.
_p_oid
,
2
)
self
.
assertEqual
(
cache
.
total_estimated_size
,
64
)
# A missing object does nothing
cache
.
update_object_size_estimation
(
None
,
2
)
self
.
assertEqual
(
cache
.
total_estimated_size
,
64
)
def
test_cache_size
(
self
):
size
=
42
cache
=
self
.
_makeOne
(
target_size
=
size
)
self
.
assertEqual
(
cache
.
cache_size
,
size
)
cache
.
cache_size
=
64
self
.
assertEqual
(
cache
.
cache_size
,
64
)
def
test_sweep_empty
(
self
):
cache
=
self
.
_makeOne
()
self
.
assertEqual
(
cache
.
incrgc
(),
0
)
def
test_sweep_of_non_deactivating_object
(
self
):
cache
=
self
.
_makeOne
()
p
=
self
.
_makePersist
(
jar
=
cache
.
jar
)
p
.
_p_state
=
0
# non-ghost, get in the ring
cache
[
p
.
_p_oid
]
=
p
def
bad_deactivate
():
"Doesn't call super, for it's own reasons, so can't be ejected"
return
p
.
_p_deactivate
=
bad_deactivate
import
persistent.picklecache
sweep_types
=
persistent
.
picklecache
.
_SWEEPABLE_TYPES
try
:
persistent
.
picklecache
.
_SWEEPABLE_TYPES
=
DummyPersistent
self
.
assertEqual
(
cache
.
full_sweep
(),
0
)
persistent
.
picklecache
.
_SWEEPABLE_TYPES
=
sweep_types
del
p
.
_p_deactivate
self
.
assertEqual
(
cache
.
full_sweep
(),
1
)
finally
:
persistent
.
picklecache
.
_SWEEPABLE_TYPES
=
sweep_types
def
test_invalidate_not_in_cache
(
self
):
# A contrived test of corruption
cache
=
self
.
_makeOne
()
p
=
self
.
_makePersist
(
jar
=
cache
.
jar
)
p
.
_p_state
=
0
# non-ghost, get in the ring
cache
[
p
.
_p_oid
]
=
p
self
.
assertEqual
(
cache
.
ring
.
next
.
object
,
p
)
cache
.
ring
.
next
.
object
=
None
# Nothing to test, just that it doesn't break
cache
.
_invalidate
(
p
.
_p_oid
)
class
DummyPersistent
(
object
):
...
...
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