Skip to content

Commit

Permalink
Merge pull request #169 from zopefoundation/issue168
Browse files Browse the repository at this point in the history
Fix setting class attributes on BTree subclasses.
  • Loading branch information
jamadden authored May 27, 2021
2 parents ce25a40 + f48f0d3 commit b03c2f2
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 16 deletions.
5 changes: 4 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
4.9.1 (unreleased)
==================

- Nothing changed yet.
- Fix setting unknown class attributes on subclasses of BTrees when
using the C extension. This prevented subclasses from being
decorated with ``@component.adapter()``. See `issue 168
<https://github.com/zopefoundation/BTrees/issues/168>`_.


4.9.0 (2021-05-26)
Expand Down
16 changes: 1 addition & 15 deletions src/BTrees/BTreeTemplate.c
Original file line number Diff line number Diff line change
Expand Up @@ -2532,21 +2532,7 @@ BTreeType_setattro(PyTypeObject* type, PyObject* name, PyObject* value)
}
return 0;
}
PyErr_Format(
PyExc_TypeError,
#ifndef PY3K
/* Python 2 doesn't have %R. Both branches otherwise match */
/* what the standard type object would produce, distinguished */
/* by the BTrees prefix. */
"BTrees: can't set attribute of built-in/extension type '%s'",
type->tp_name
#else
"BTrees: cannot set attribute %R of immutable type '%s'",
name,
type->tp_name
#endif
);
return -1;
return PyType_Type.tp_setattro((PyObject*)type, name, value);
}

static PyTypeObject BTreeTypeType = {
Expand Down
16 changes: 16 additions & 0 deletions src/BTrees/tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,22 @@ def setUp(self):
super(Base, self).setUp()
_skip_if_pure_py_and_py_test(self)

def testSubclassesCanHaveAttributes(self):
# https://github.com/zopefoundation/BTrees/issues/168
class Subclass(self._getTargetClass()):
pass
Subclass.foo = 1
self.assertIn('foo', Subclass.__dict__)
self.assertNotIn('foo', self._getTargetClass().__dict__)

@skipOnPurePython
def testCannotSetArbitraryAttributeOnBase(self):
if 'Py' in self._getTargetClass().__name__:
# pure-python classes can have arbitrary attributes
self.skipTest("No on Pure Python.")
with self.assertRaises(TypeError):
self._getTargetClass().foo = 1

def testProvidesInterface(self):
from zope.interface import providedBy
from zope.interface.common.sequence import IMinimalSequence
Expand Down

0 comments on commit b03c2f2

Please sign in to comment.