Commit 6741dcfc authored by Jason Madden's avatar Jason Madden

HistoricalStorageAdapter forwards release() to its instance

Fixes #78.

Also adjust the base wrapper's __getattr__ to be faster (500 vs 711ns
in a benchmark of the common case) and behave the same on Python 2 vs
Python 3 with regards to exceptions, should a method be implemented as
an descriptor. In practice this probably makes no difference
whatsoever, it's just the same pattern used for forwarding
release.
parent 5056d49e
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
- Drop support for Python 3.3. - Drop support for Python 3.3.
- The ``HistoricalStorageAdapter`` forwards the ``release`` method to
its base instance. See `issue 78 <https://github.com/zopefoundation/ZODB/issues/788>`_.
5.2.4 (2017-05-17) 5.2.4 (2017-05-17)
================== ==================
......
...@@ -27,10 +27,9 @@ class Base(object): ...@@ -27,10 +27,9 @@ class Base(object):
def __getattr__(self, name): def __getattr__(self, name):
if name in self._copy_methods: if name in self._copy_methods:
if hasattr(self._storage, name): m = getattr(self._storage, name)
m = getattr(self._storage, name) setattr(self, name, m)
setattr(self, name, m) return m
return m
raise AttributeError(name) raise AttributeError(name)
...@@ -204,7 +203,12 @@ class HistoricalStorageAdapter(Base): ...@@ -204,7 +203,12 @@ class HistoricalStorageAdapter(Base):
return False return False
def release(self): def release(self):
pass try:
release = self._storage.release
except AttributeError:
pass
else:
release()
close = release close = release
......
##############################################################################
#
# Copyright (c) 2017 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
import unittest
from ZODB import mvccadapter
class TestBase(unittest.TestCase):
def test_getattr_does_not_hide_exceptions(self):
class TheException(Exception):
pass
class RaisesOnAccess(object):
@property
def thing(self):
raise TheException()
base = mvccadapter.Base(RaisesOnAccess())
base._copy_methods = ('thing',)
with self.assertRaises(TheException):
getattr(base, 'thing')
def test_getattr_raises_if_missing(self):
base = mvccadapter.Base(self)
base._copy_methods = ('thing',)
with self.assertRaises(AttributeError):
getattr(base, 'thing')
class TestHistoricalStorageAdapter(unittest.TestCase):
def test_forwards_release(self):
class Base(object):
released = False
def release(self):
self.released = True
base = Base()
adapter = mvccadapter.HistoricalStorageAdapter(base, None)
adapter.release()
self.assertTrue(base.released)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment