Skip to content

Commit 011c562

Browse files
authored
Merge pull request #313 from zopefoundation/tseaver-312-osd_as_basetype
fix: ensure OSD is sublcassable
2 parents f688bb0 + 19774cd commit 011c562

File tree

5 files changed

+43
-27
lines changed

5 files changed

+43
-27
lines changed

CHANGES.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
Changes
33
=========
44

5-
7.1 (unreleased)
6-
================
5+
7.0.1 (unreleased)
6+
==================
77

8-
- Nothing changed yet.
8+
- Fix subclassability of ``ObjectSpecificationDescriptor`` (broken in 7.0).
9+
(`#312 <https://github.com/zopefoundation/zope.interface/issues/312>`_)
910

1011

1112
7.0 (2024-08-06)

src/zope/interface/_zope_interface_coptimizations.c

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,6 @@
5757
* #c.PyTypeObject.tp_weaklistoffset
5858
*/
5959
#define USE_EXPLICIT_WEAKREFLIST 0
60-
#define LEAFTYPE_FLAGS \
61-
Py_TPFLAGS_DEFAULT | \
62-
Py_TPFLAGS_MANAGED_WEAKREF | \
63-
Py_TPFLAGS_HAVE_GC
6460
#define BASETYPE_FLAGS \
6561
Py_TPFLAGS_DEFAULT | \
6662
Py_TPFLAGS_BASETYPE | \
@@ -74,9 +70,6 @@
7470
* #c.PyTypeObject.tp_weaklistoffset
7571
*/
7672
#define USE_EXPLICIT_WEAKREFLIST 1
77-
#define LEAFTYPE_FLAGS \
78-
Py_TPFLAGS_DEFAULT | \
79-
Py_TPFLAGS_HAVE_GC
8073
#define BASETYPE_FLAGS \
8174
Py_TPFLAGS_DEFAULT | \
8275
Py_TPFLAGS_BASETYPE | \
@@ -546,7 +539,7 @@ static PyType_Slot OSD_type_slots[] = {
546539
static PyType_Spec OSD_type_spec = {
547540
.name = OSD__name__,
548541
.basicsize = 0,
549-
.flags = LEAFTYPE_FLAGS,
542+
.flags = BASETYPE_FLAGS,
550543
.slots = OSD_type_slots
551544
};
552545

src/zope/interface/tests/__init__.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,16 @@
22

33

44
class OptimizationTestMixin:
5-
"""
6-
Helper for testing that C optimizations are used
7-
when appropriate.
5+
"""Mixin testing that C optimizations are used when appropriate.
86
"""
97

108
def _getTargetClass(self):
11-
"""
12-
Define this to return the implementation in use,
13-
without the 'Py' or 'Fallback' suffix.
9+
"""Return the implementation in use, without 'Py' or 'Fallback' suffix.
1410
"""
1511
raise NotImplementedError
1612

1713
def _getFallbackClass(self):
18-
"""
19-
Define this to return the fallback Python implementation.
14+
"""Return the fallback Python implementation.
2015
"""
2116
# Is there an algorithmic way to do this? The C
2217
# objects all come from the same module so I don't see how we can
@@ -33,6 +28,20 @@ def test_optimizations(self):
3328
self.assertIs(used, fallback)
3429

3530

31+
class SubclassableMixin:
32+
33+
def _getTargetClass(self):
34+
"""Return the implementation in use without 'Py' or 'Fallback' suffix.
35+
"""
36+
raise NotImplementedError
37+
38+
def test_can_subclass(self):
39+
klass = self._getTargetClass()
40+
41+
class Derived(klass): # no raise
42+
pass
43+
44+
3645
class MissingSomeAttrs:
3746
"""
3847
Helper for tests that raises a specific exception

src/zope/interface/tests/test_declarations.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
from zope.interface.tests import MissingSomeAttrs
1919
from zope.interface.tests import OptimizationTestMixin
20+
from zope.interface.tests import SubclassableMixin
2021
from zope.interface.tests.test_interface import \
2122
NameAndModuleComparisonTestsMixin
2223

@@ -1803,8 +1804,11 @@ class Bar(Foo):
18031804
self.assertRaises(AttributeError, getattr, bar, '__provides__')
18041805

18051806

1806-
class ClassProvidesBaseTests(OptimizationTestMixin,
1807-
ClassProvidesBaseFallbackTests):
1807+
class ClassProvidesBaseTests(
1808+
OptimizationTestMixin,
1809+
ClassProvidesBaseFallbackTests,
1810+
SubclassableMixin,
1811+
):
18081812
# Repeat tests for C optimizations
18091813

18101814
def _getTargetClass(self):
@@ -2632,7 +2636,9 @@ def __provides__(self):
26322636

26332637
class ObjectSpecificationDescriptorTests(
26342638
ObjectSpecificationDescriptorFallbackTests,
2635-
OptimizationTestMixin):
2639+
OptimizationTestMixin,
2640+
SubclassableMixin,
2641+
):
26362642
# Repeat tests for C optimizations
26372643

26382644
def _getTargetClass(self):

src/zope/interface/tests/test_interface.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from zope.interface.tests import CleanUp
3535
from zope.interface.tests import MissingSomeAttrs
3636
from zope.interface.tests import OptimizationTestMixin
37+
from zope.interface.tests import SubclassableMixin
3738

3839

3940
_marker = object()
@@ -216,8 +217,11 @@ def _implementedBy(obj):
216217
self.assertFalse(sb.implementedBy(object()))
217218

218219

219-
class SpecificationBaseTests(GenericSpecificationBaseTests,
220-
OptimizationTestMixin):
220+
class SpecificationBaseTests(
221+
GenericSpecificationBaseTests,
222+
OptimizationTestMixin,
223+
SubclassableMixin,
224+
):
221225
# Tests that use the C implementation
222226

223227
def _getTargetClass(self):
@@ -436,9 +440,12 @@ def test___call___w_no_conform_catches_only_AttributeError(self):
436440
)
437441

438442

439-
class InterfaceBaseTests(InterfaceBaseTestsMixin,
440-
OptimizationTestMixin,
441-
unittest.TestCase):
443+
class InterfaceBaseTests(
444+
InterfaceBaseTestsMixin,
445+
OptimizationTestMixin,
446+
SubclassableMixin,
447+
unittest.TestCase,
448+
):
442449
# Tests that work with the C implementation
443450
def _getTargetClass(self):
444451
from zope.interface.interface import InterfaceBase

0 commit comments

Comments
 (0)