diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 9387927ec..01dab140d 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,7 +4,8 @@ Changelog 1.4.4 (xx.xx.2016) ~~~~~~~~~~~~~~~~~~ -* The `wagtailuserbar` template tag now gracefully handles situations where the `request` object is not in the template context (Matt Westcott) + * Fix: The `wagtailuserbar` template tag now gracefully handles situations where the `request` object is not in the template context (Matt Westcott) + * Fix: Meta classes on StreamField blocks now handle multiple inheritance correctly (Tim Heap) 1.4.3 (04.04.2016) diff --git a/docs/releases/1.4.4.rst b/docs/releases/1.4.4.rst index 3322d47d8..ed942b102 100644 --- a/docs/releases/1.4.4.rst +++ b/docs/releases/1.4.4.rst @@ -13,4 +13,5 @@ What's changed Bug fixes ~~~~~~~~~ -* The ``wagtailuserbar`` template tag now gracefully handles situations where the ``request`` object is not in the template context (Matt Westcott) + * The ``wagtailuserbar`` template tag now gracefully handles situations where the ``request`` object is not in the template context (Matt Westcott) + * Meta classes on StreamField blocks now handle multiple inheritance correctly (Tim Heap) diff --git a/wagtail/wagtailcore/blocks/base.py b/wagtail/wagtailcore/blocks/base.py index 366eb3670..593646567 100644 --- a/wagtail/wagtailcore/blocks/base.py +++ b/wagtail/wagtailcore/blocks/base.py @@ -30,9 +30,11 @@ class BaseBlock(type): cls = super(BaseBlock, mcs).__new__(mcs, name, bases, attrs) - base_meta_class = getattr(cls, '_meta_class', None) - bases = tuple(cls for cls in [meta_class, base_meta_class] if cls) or () - cls._meta_class = type(str(name + 'Meta'), bases + (object, ), {}) + # Get all the Meta classes from all the bases + meta_class_bases = [meta_class] + [getattr(base, '_meta_class', None) + for base in bases] + meta_class_bases = tuple(filter(bool, meta_class_bases)) + cls._meta_class = type(str(name + 'Meta'), meta_class_bases, {}) return cls @@ -43,7 +45,7 @@ class Block(six.with_metaclass(BaseBlock, object)): TEMPLATE_VAR = 'value' - class Meta: + class Meta(object): label = None icon = "placeholder" classname = None diff --git a/wagtail/wagtailcore/tests/test_blocks.py b/wagtail/wagtailcore/tests/test_blocks.py index ec429be0e..07e5b5199 100644 --- a/wagtail/wagtailcore/tests/test_blocks.py +++ b/wagtail/wagtailcore/tests/test_blocks.py @@ -454,7 +454,10 @@ class TestMeta(unittest.TestCase): block = HeadingBlock(template='subheading.html') self.assertEqual(block.meta.template, 'subheading.html') - def test_meta_multiple_inheritance(self): + def test_meta_nested_inheritance(self): + """ + Check that having a multi-level inheritance chain works + """ class HeadingBlock(blocks.CharBlock): class Meta: template = 'heading.html' @@ -468,6 +471,39 @@ class TestMeta(unittest.TestCase): self.assertEqual(block.meta.template, 'subheading.html') self.assertEqual(block.meta.test, 'Foo') + def test_meta_multi_inheritance(self): + """ + Check that multi-inheritance and Meta classes work together + """ + class LeftBlock(blocks.CharBlock): + class Meta: + template = 'template.html' + clash = 'the band' + label = 'Left block' + + class RightBlock(blocks.CharBlock): + class Meta: + default = 'hello' + clash = 'the album' + label = 'Right block' + + class ChildBlock(LeftBlock, RightBlock): + class Meta: + label = 'Child block' + + block = ChildBlock() + # These should be directly inherited from the LeftBlock/RightBlock + self.assertEqual(block.meta.template, 'template.html') + self.assertEqual(block.meta.default, 'hello') + + # This should be inherited from the LeftBlock, solving the collision, + # as LeftBlock comes first + self.assertEqual(block.meta.clash, 'the band') + + # This should come from ChildBlock itself, ignoring the label on + # LeftBlock/RightBlock + self.assertEqual(block.meta.label, 'Child block') + class TestStructBlock(SimpleTestCase): def test_initialisation(self):