Skip to content

Commit

Permalink
Checkpoint on ZODB under PyPy: 25 failures, 25 errors (needs my persi…
Browse files Browse the repository at this point in the history
…stent fork). Many of them are printing differences, some have to do with the Python persistent implementation, especially PickleCache
  • Loading branch information
jamadden committed Apr 7, 2015
1 parent 1a40a7e commit f865508
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 9 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -17,3 +17,4 @@ coverage.xml
dist
testing.log
.eggs/
.dir-locals.el
9 changes: 5 additions & 4 deletions src/ZODB/Connection.py
Expand Up @@ -328,10 +328,10 @@ def close(self, primary=True):
# get back here.
else:
self.opened = None

am = self._db._activity_monitor
if am is not None:
am.closedConnection(self)
am.closedConnection(self)

def db(self):
"""Returns a handle to the database this connection belongs to."""
Expand Down Expand Up @@ -1020,9 +1020,10 @@ def _cache_items(self):
items = self._cache.lru_items()
# fine everything. some on the lru list, some not
everything = self._cache.cache_data
# remove those items that are on the lru list
# remove those items that are on the lru list (which may not actually
# be in the full cache, under the Python implementation)
for k,v in items:
del everything[k]
everything.pop(k, None)
# return a list of [ghosts....not recently used.....recently used]
return list(everything.items()) + items

Expand Down
8 changes: 7 additions & 1 deletion src/ZODB/DB.py
Expand Up @@ -530,7 +530,13 @@ def f(con, detail=detail):
def cacheExtremeDetail(self):
detail = []
conn_no = [0] # A mutable reference to a counter
def f(con, detail=detail, rc=sys.getrefcount, conn_no=conn_no):
try:
rc = sys.getrefcount
except AttributeError:
# sys.getrefcount is a CPython implementation detail
# not required to exist on, e.g., PyPy. Here we fake it.
rc = lambda o: 4
def f(con, detail=detail, rc=rc, conn_no=conn_no):
conn_no[0] += 1
cn = conn_no[0]
for oid, ob in con._cache_items():
Expand Down
10 changes: 9 additions & 1 deletion src/ZODB/broken.py
Expand Up @@ -23,6 +23,14 @@
from ZODB._compat import IMPORT_MAPPING
from ZODB._compat import NAME_MAPPING

# Add our magic names to the Python implementation of persistence
# so that it won't try to re-activate the broken object.
import persistent.persistence
persistent.persistence.SPECIAL_NAMES += ('__Broken_newargs__',
'__Broken_initargs__',
#'__Broken_state__',
'__reduce__',
'__getstate__')

broken_cache = {}

Expand Down Expand Up @@ -308,7 +316,7 @@ class PersistentBroken(Broken, persistent.Persistent):
>>> a.__reduce__() # doctest: +NORMALIZE_WHITESPACE
Traceback (most recent call last):
...
BrokenModified:
BrokenModified:
<persistent broken not.there.Atall instance '\x00\x00\x00\x00****'>
but you can get their state:
Expand Down
4 changes: 4 additions & 0 deletions src/ZODB/serialize.py
Expand Up @@ -483,6 +483,10 @@ def find_global(modulename, name):
return factory(conn, modulename, name)

unpickler.find_global = find_global
try:
unpickler.find_class = find_global # PyPy, zodbpickle, the non-c-accelerated version
except AttributeError:
pass

return unpickler

Expand Down
2 changes: 1 addition & 1 deletion src/ZODB/tests/testBroken.py
Expand Up @@ -67,7 +67,7 @@ def test_integration():
>>> conn3 = db.open()
>>> a3 = conn3.root()['a']
>>> a3 # doctest: +NORMALIZE_WHITESPACE
<persistent broken ZODB.not.there.Atall instance
<persistent broken ZODB.not.there.Atall instance
'\x00\x00\x00\x00\x00\x00\x00\x01'>
>>> a3.__Broken_state__
Expand Down
9 changes: 7 additions & 2 deletions src/ZODB/tests/testCache.py
Expand Up @@ -32,6 +32,7 @@
import ZODB
import ZODB.MappingStorage
import ZODB.tests.util
from ZODB.tests.util import PYPY

PY2 = sys.version_info[0] == 2

Expand Down Expand Up @@ -190,6 +191,7 @@ def testClassItems(self):

class LRUCacheTests(CacheTestBase):

@unittest.skipIf(PYPY, "Implementation details of the PickleCache")
def testLRU(self):
# verify the LRU behavior of the cache
dataset_size = 5
Expand Down Expand Up @@ -339,7 +341,10 @@ def testBogusObject(self):
def add(key, obj):
self.cache[key] = obj

nones = sys.getrefcount(None)
# getrefcount is an implementation detail of CPython,
# not present under PyPy/Jython
rc = getattr(sys, 'getrefcount', lambda x: 1)
nones = rc(None)

key = p64(2)
# value isn't persistent
Expand Down Expand Up @@ -369,7 +374,7 @@ def add(key, obj):
# structure that adds a new reference to None for each executed
# line of code, which interferes with this test. So check it
# only if we're running without coverage tracing.
self.assertEqual(sys.getrefcount(None), nones)
self.assertEqual(rc(None), nones)

def testTwoCaches(self):
jar2 = StubDataManager()
Expand Down
15 changes: 15 additions & 0 deletions src/ZODB/tests/util.py
Expand Up @@ -18,6 +18,7 @@
import atexit
import os
import persistent
import platform
import re
import sys
import tempfile
Expand Down Expand Up @@ -184,3 +185,17 @@ def faux_time():

time.time = faux_time


py_impl = getattr(platform, 'python_implementation', lambda: None)
PYPY = py_impl() == 'PyPy'

if not hasattr(unittest, 'skipIf'):
def skipIf(condition, reason):
if condition:
def skip(f):
return lambda self: None
return skip

def run(f):
return f
return run

0 comments on commit f865508

Please sign in to comment.