start work on 1.8 / remove deprecated features (#3058)

* Version bump to start work on Wagtail 1.8

* Remove features deprecated in Wagtail 1.8
pull/3055/head^2
Matt Westcott 2016-10-07 16:02:04 +01:00 zatwierdzone przez GitHub
rodzic b658b44e1b
commit a3ba533afb
17 zmienionych plików z 38 dodań i 332 usunięć

Wyświetl plik

@ -1,6 +1,10 @@
Changelog
=========
1.8 (xx.xx.xxxx) - IN DEVELOPMENT
~~~~~~~~~~~~~~~~
1.7 (xx.xx.xxxx) - IN DEVELOPMENT
~~~~~~~~~~~~~~~~

Wyświetl plik

@ -39,7 +39,7 @@ then add the following to your settings::
WAGTAILSEARCH_BACKENDS = {
'default': {
'BACKEND': 'wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch',
'BACKEND': 'wagtail.wagtailsearch.backends.elasticsearch',
'INDEX': '{{ project_name }}',
},
}

Wyświetl plik

@ -0,0 +1,23 @@
==========================================
Wagtail 1.8 release notes - IN DEVELOPMENT
==========================================
.. contents::
:local:
:depth: 1
What's new
==========
Minor features
~~~~~~~~~~~~~~
Bug fixes
~~~~~~~~~
Upgrade considerations
======================

Wyświetl plik

@ -4,6 +4,7 @@ Release notes
.. toctree::
:maxdepth: 1
1.8
1.7
1.6.3
1.6.2

Wyświetl plik

@ -4,7 +4,7 @@ from wagtail.utils.version import get_semver_version, get_version
# major.minor.patch.release.number
# release must be one of alpha, beta, rc, or final
VERSION = (1, 7, 0, 'alpha', 0)
VERSION = (1, 8, 0, 'alpha', 0)
__version__ = get_version(VERSION)

Wyświetl plik

@ -1,2 +1,2 @@
Django>=1.10,<1.11
wagtail==1.7a0
wagtail==1.8a0

Wyświetl plik

@ -1,12 +1,12 @@
from __future__ import absolute_import, unicode_literals
class RemovedInWagtail18Warning(DeprecationWarning):
class RemovedInWagtail19Warning(DeprecationWarning):
pass
removed_in_next_version_warning = RemovedInWagtail18Warning
removed_in_next_version_warning = RemovedInWagtail19Warning
class RemovedInWagtail19Warning(PendingDeprecationWarning):
class RemovedInWagtail110Warning(PendingDeprecationWarning):
pass

Wyświetl plik

@ -1,39 +0,0 @@
from __future__ import absolute_import, unicode_literals
import warnings
from django.contrib.contenttypes.models import ContentType
from django.db.models import Count
from taggit.models import Tag
from wagtail.utils.deprecation import RemovedInWagtail18Warning
from wagtail.wagtailsearch import index
class TagSearchable(index.Indexed):
"""
Mixin to provide a 'search' method, searching on the 'title' field and tags,
for models that provide those things.
"""
search_fields = [
index.SearchField('title', partial_match=True, boost=10),
index.RelatedFields('tags', [
index.SearchField('name', partial_match=True, boost=10),
]),
]
@classmethod
def popular_tags(cls):
content_type = ContentType.objects.get_for_model(cls)
return Tag.objects.filter(
taggit_taggeditem_items__content_type=content_type
).annotate(
item_count=Count('taggit_taggeditem_items')
).order_by('-item_count')[:10]
warnings.warn(
"The wagtail.wagtailadmin.taggable module is deprecated.",
category=RemovedInWagtail18Warning, stacklevel=2
)

Wyświetl plik

@ -1,9 +1,6 @@
from __future__ import absolute_import, unicode_literals
import collections
import inspect
import sys
import warnings
from importlib import import_module
from django import forms
@ -15,8 +12,6 @@ from django.utils.encoding import force_text, python_2_unicode_compatible
from django.utils.safestring import mark_safe
from django.utils.text import capfirst
from wagtail.utils.deprecation import RemovedInWagtail18Warning
# unicode_literals ensures that any render / __str__ methods returning HTML via calls to mark_safe / format_html
# return a SafeText, not SafeBytes; necessary so that it doesn't get re-encoded when the template engine
# calls force_text, which would cause it to lose its 'safe' flag
@ -25,24 +20,6 @@ from wagtail.utils.deprecation import RemovedInWagtail18Warning
__all__ = ['BaseBlock', 'Block', 'BoundBlock', 'DeclarativeSubBlocksMetaclass', 'BlockWidget', 'BlockField']
def accepts_context(func):
"""
Helper function used by _render_with_context and _render_basic_with_context. Return true
if the callable 'func' accepts a 'context' keyword argument
"""
if sys.version_info >= (3, 3):
signature = inspect.signature(func)
try:
signature.bind_partial(context=None)
return True
except TypeError:
return False
else:
# Fall back on inspect.getargspec, available on Python 2.7 but deprecated since 3.5
argspec = inspect.getargspec(func)
return ('context' in argspec.args) or (argspec.keywords is not None)
# =========================================
# Top-level superclasses and helper objects
# =========================================
@ -244,39 +221,6 @@ class Block(six.with_metaclass(BaseBlock, object)):
self.TEMPLATE_VAR: value,
}
def _render_with_context(self, value, context=None):
"""
Temporary hack to accommodate Block subclasses created for Wagtail <1.6 which
have overridden `render` with the type signature:
def render(self, value)
and will therefore fail when passed a `context` kwarg.
In Wagtail 1.8, when support for context-less `render` methods is dropped,
this method will be deleted (and calls to it replaced with a direct call to `render`).
"""
if accepts_context(self.render):
# this render method can receive a 'context' kwarg, so we're good
return self.render(value, context=context)
else:
# this render method needs updating for Wagtail >=1.6 -
# output a deprecation warning
# find the specific parent class that defines `render` by stepping through the MRO,
# falling back on type(self) if it can't be found for some reason
class_with_render_method = next(
(cls for cls in type(self).__mro__ if 'render' in cls.__dict__),
type(self)
)
warnings.warn(
"The render method on %s needs to be updated to accept an optional 'context' "
"keyword argument" % class_with_render_method,
category=RemovedInWagtail18Warning
)
# fall back on a call to 'render' without the context kwarg
return self.render(value)
def render(self, value, context=None):
"""
Return a text rendering of 'value', suitable for display on templates. By default, this will
@ -285,7 +229,7 @@ class Block(six.with_metaclass(BaseBlock, object)):
"""
template = getattr(self.meta, 'template', None)
if not template:
return self._render_basic_with_context(value, context=context)
return self.render_basic(value, context=context)
if context is None:
new_context = self.get_context(value)
@ -295,39 +239,6 @@ class Block(six.with_metaclass(BaseBlock, object)):
return mark_safe(render_to_string(template, new_context))
def _render_basic_with_context(self, value, context=None):
"""
Temporary hack to accommodate Block subclasses created for Wagtail <1.6 which
have overridden `render_basic` with the type signature:
def render_basic(self, value)
and will therefore fail when passed a `context` kwarg.
In Wagtail 1.8, when support for context-less `render_basic` methods is dropped,
this method will be deleted (and calls to it replaced with a direct call to `render_basic`).
"""
if accepts_context(self.render_basic):
# this render_basic method can receive a 'context' kwarg, so we're good
return self.render_basic(value, context=context)
else:
# this render_basic method needs updating for Wagtail >=1.6 -
# output a deprecation warning
# find the specific parent class that defines `render_basic` by stepping through the MRO,
# falling back on type(self) if it can't be found for some reason
class_with_render_basic_method = next(
(cls for cls in type(self).__mro__ if 'render_basic' in cls.__dict__),
type(self)
)
warnings.warn(
"The render_basic method on %s needs to be updated to accept an optional 'context' "
"keyword argument" % class_with_render_basic_method,
category=RemovedInWagtail18Warning
)
# fall back on a call to 'render_basic' without the context kwarg
return self.render_basic(value)
def render_basic(self, value, context=None):
"""
Return a text rendering of 'value', suitable for display on templates. render() will fall back on
@ -504,7 +415,7 @@ class BoundBlock(object):
return self.block.render_form(self.value, self.prefix, errors=self.errors)
def render(self, context=None):
return self.block._render_with_context(self.value, context=context)
return self.block.render(self.value, context=context)
def render_as_block(self, context=None):
"""
@ -514,7 +425,7 @@ class BoundBlock(object):
an unrelated method that just happened to have that name - for example, when called on a
PageChooserBlock it could end up calling page.render.
"""
return self.block._render_with_context(self.value, context=context)
return self.block.render(self.value, context=context)
def id_for_label(self):
return self.block.id_for_label(self.prefix)

Wyświetl plik

@ -147,7 +147,7 @@ class ListBlock(Block):
children = format_html_join(
'\n', '<li>{0}</li>',
[
(self.child_block._render_with_context(child_value, context=context),)
(self.child_block.render(child_value, context=context),)
for child_value in value
]
)

Wyświetl plik

@ -5,7 +5,6 @@ import base64
import collections
import json
import unittest
import warnings
from decimal import Decimal
# non-standard import name for ugettext_lazy, to prevent strings from being picked up for translation
@ -21,7 +20,6 @@ from django.utils.translation import ugettext_lazy as __
from wagtail.tests.testapp.blocks import LinkBlock as CustomLinkBlock
from wagtail.tests.testapp.blocks import SectionBlock
from wagtail.utils.deprecation import RemovedInWagtail18Warning
from wagtail.wagtailcore import blocks
from wagtail.wagtailcore.models import Page
from wagtail.wagtailcore.rich_text import RichText
@ -38,24 +36,6 @@ class FooStreamBlock(blocks.StreamBlock):
return value
class LegacyRenderMethodBlock(blocks.CharBlock):
"""
A block with a render method that doesn't accept a 'context' kwarg.
Support for these will be dropped in Wagtail 1.8
"""
def render(self, value):
return str(value).upper()
class LegacyRenderBasicMethodBlock(blocks.CharBlock):
"""
A block with a render_basic method that doesn't accept a 'context' kwarg.
Support for these will be dropped in Wagtail 1.8
"""
def render_basic(self, value):
return str(value).upper()
class TestFieldBlock(unittest.TestCase):
def test_charfield_render(self):
block = blocks.CharBlock()
@ -187,24 +167,6 @@ class TestFieldBlock(unittest.TestCase):
self.assertIn('pretty.css', ''.join(block.all_media().render_css()))
self.assertIn('animations.js', ''.join(block.all_media().render_js()))
def test_legacy_render_basic(self):
"""
LegacyRenderBasicMethodBlock defines a render_basic method that doesn't accept
a 'context' kwarg. Calling 'render' should gracefully handle this and return
the result of calling render_basic(value) (i.e. without passing context), but
generate a RemovedInWagtail18Warning.
"""
block = LegacyRenderBasicMethodBlock()
with warnings.catch_warnings(record=True) as ws:
warnings.simplefilter('always')
result = block.render('hello')
self.assertEqual(result, 'HELLO')
self.assertEqual(len(ws), 1)
self.assertIs(ws[0].category, RemovedInWagtail18Warning)
class TestIntegerBlock(unittest.TestCase):
def test_type(self):
@ -1255,25 +1217,6 @@ class TestListBlock(unittest.TestCase):
self.assertIn('<h1 lang="fr">Bonjour le monde!</h1>', html)
self.assertIn('<h1 lang="fr">Au revoir le monde!</h1>', html)
def test_child_with_legacy_render(self):
"""
If the child block has a legacy 'render' method that doesn't accept a 'context'
kwarg, ListBlock.render should use the result of calling render(child_value), but
generate a RemovedInWagtail18Warning.
"""
block = blocks.ListBlock(LegacyRenderBasicMethodBlock())
with warnings.catch_warnings(record=True) as ws:
warnings.simplefilter('always')
result = block.render(['hello', 'world'])
self.assertIn('<li>HELLO</li>', result)
self.assertIn('<li>WORLD</li>', result)
self.assertEqual(len(ws), 2)
self.assertIs(ws[0].category, RemovedInWagtail18Warning)
self.assertIs(ws[1].category, RemovedInWagtail18Warning)
def render_form(self):
class LinkBlock(blocks.StructBlock):
title = blocks.CharBlock()
@ -1648,39 +1591,6 @@ class TestStreamBlock(SimpleTestCase):
html = value.render_as_block()
self.assertIn('<div class="block-heading"><h1>Hello</h1></div>', html)
def test_render_child_with_legacy_render_method(self):
"""
StreamBlock should gracefully handle child blocks with a legacy 'render'
method (one which doesn't accept a 'context' kwarg), but output a
RemovedInWagtail18Warning
"""
block = blocks.StreamBlock([
('heading', LegacyRenderMethodBlock()),
('paragraph', blocks.CharBlock()),
])
value = block.to_python([
{'type': 'heading', 'value': 'Hello'}
])
with warnings.catch_warnings(record=True) as ws:
warnings.simplefilter('always')
result = block.render(value)
self.assertIn('<div class="block-heading">HELLO</div>', result)
self.assertEqual(len(ws), 1)
self.assertIs(ws[0].category, RemovedInWagtail18Warning)
# calling render_as_block() on value (a StreamValue instance)
# should be equivalent to block.render(value)
with warnings.catch_warnings(record=True) as ws:
warnings.simplefilter('always')
result = value.render_as_block()
self.assertIn('<div class="block-heading">HELLO</div>', result)
self.assertEqual(len(ws), 1)
self.assertIs(ws[0].category, RemovedInWagtail18Warning)
def test_render_passes_context_to_children(self):
block = blocks.StreamBlock([
('heading', blocks.CharBlock(template='tests/blocks/heading_block.html')),

Wyświetl plik

@ -4,21 +4,12 @@
import sys
from importlib import import_module
import warnings
from django.utils import six
from django.utils.module_loading import import_string
from django.core.exceptions import ImproperlyConfigured
from django.conf import settings
from wagtail.utils.deprecation import RemovedInWagtail18Warning
RENAMED_BACKENDS = {
'wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch': 'wagtail.wagtailsearch.backends.elasticsearch',
'wagtail.wagtailsearch.backends.db.DBSearch': 'wagtail.wagtailsearch.backends.db',
}
class InvalidSearchBackendError(ImproperlyConfigured):
pass
@ -35,22 +26,6 @@ def get_search_backend_config():
return search_backends
def _check_renamed(backend):
if backend in RENAMED_BACKENDS:
warnings.warn(
"The '%s' search backend path has changed to '%s'. Please update "
"the WAGTAILSEARCH_BACKENDS setting to use the new path." % (
backend,
RENAMED_BACKENDS[backend],
),
category=RemovedInWagtail18Warning, stacklevel=2
)
backend = RENAMED_BACKENDS[backend]
return backend
def import_backend(dotted_path):
"""
Theres two formats for the dotted_path.
@ -75,7 +50,6 @@ def import_backend(dotted_path):
def get_search_backend(backend='default', **kwargs):
backend = _check_renamed(backend)
search_backends = get_search_backend_config()
# Try to find the backend
@ -95,7 +69,6 @@ def get_search_backend(backend='default', **kwargs):
params = conf.copy()
params.update(kwargs)
backend = params.pop('BACKEND')
backend = _check_renamed(backend)
# Try to import the backend
try:

Wyświetl plik

@ -1,11 +1,8 @@
from __future__ import absolute_import, unicode_literals
import warnings
from django.db import models
from django.db.models.expressions import Value
from wagtail.utils.deprecation import RemovedInWagtail18Warning
from wagtail.wagtailsearch.backends.base import (
BaseSearchBackend, BaseSearchQuery, BaseSearchResults)
@ -114,16 +111,4 @@ class DatabaseSearchBackend(BaseSearchBackend):
pass # Not needed
class DBSearch(DatabaseSearchBackend):
def __init__(self, params):
warnings.warn(
"The wagtail.wagtailsearch.backends.db.DBSearch has "
"been moved to wagtail.wagtailsearch.backends.db.DatabaseSearchBackend",
category=RemovedInWagtail18Warning, stacklevel=2
)
super(DBSearch, self).__init__(params)
SearchBackend = DatabaseSearchBackend

Wyświetl plik

@ -1,7 +1,6 @@
from __future__ import absolute_import, unicode_literals
import json
import warnings
from django.db import models
from django.utils.crypto import get_random_string
@ -9,7 +8,6 @@ from django.utils.six.moves.urllib.parse import urlparse
from elasticsearch import Elasticsearch, NotFoundError
from elasticsearch.helpers import bulk
from wagtail.utils.deprecation import RemovedInWagtail18Warning
from wagtail.wagtailsearch.backends.base import (
BaseSearchBackend, BaseSearchQuery, BaseSearchResults)
from wagtail.wagtailsearch.index import (
@ -777,15 +775,4 @@ class ElasticsearchSearchBackend(BaseSearchBackend):
self.get_index_for_model(type(obj)).delete_item(obj)
class ElasticSearch(ElasticsearchSearchBackend):
def __init__(self, params):
warnings.warn(
"The wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch has "
"been moved to wagtail.wagtailsearch.backends.elasticsearch.ElasticsearchSearchBackend",
category=RemovedInWagtail18Warning, stacklevel=2
)
super(ElasticSearch, self).__init__(params)
SearchBackend = ElasticsearchSearchBackend

Wyświetl plik

@ -2,7 +2,6 @@ from __future__ import absolute_import, unicode_literals
import time
import unittest
import warnings
from django.conf import settings
from django.core import management
@ -12,7 +11,6 @@ from django.utils.six import StringIO
from wagtail.tests.search import models
from wagtail.tests.utils import WagtailTestUtils
from wagtail.utils.deprecation import RemovedInWagtail18Warning
from wagtail.wagtailsearch.backends import (
InvalidSearchBackendError, get_search_backend, get_search_backends)
from wagtail.wagtailsearch.backends.base import FieldError
@ -203,23 +201,6 @@ class TestBackendLoader(TestCase):
db = get_search_backend(backend='wagtail.wagtailsearch.backends.db.DatabaseSearchBackend')
self.assertIsInstance(db, DatabaseSearchBackend)
def test_import_old_name(self):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
db = get_search_backend(backend='wagtail.wagtailsearch.backends.db.DBSearch')
self.assertIsInstance(db, DatabaseSearchBackend)
self.assertEqual(len(w), 1)
self.assertIs(w[0].category, RemovedInWagtail18Warning)
self.assertEqual(
str(w[0].message),
"The 'wagtail.wagtailsearch.backends.db.DBSearch' search backend path has "
"changed to 'wagtail.wagtailsearch.backends.db'. Please update the "
"WAGTAILSEARCH_BACKENDS setting to use the new path."
)
def test_nonexistent_backend_import(self):
self.assertRaises(
InvalidSearchBackendError, get_search_backend, backend='wagtail.wagtailsearch.backends.doesntexist'

Wyświetl plik

@ -1,12 +1,10 @@
from __future__ import absolute_import, unicode_literals
import unittest
import warnings
from django.test import TestCase
from wagtail.tests.search import models
from wagtail.utils.deprecation import RemovedInWagtail18Warning
from .test_backends import BackendTests
@ -28,16 +26,3 @@ class TestDBBackend(BackendTests, TestCase):
for result in results:
# DB backend doesn't do scoring, so annotate_score should just add None
self.assertIsNone(result._score)
class TestOldNameDeprecationWarning(TestCase):
def test_old_name_deprecation(self):
from wagtail.wagtailsearch.backends.db import DBSearch
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
DBSearch({})
self.assertEqual(len(w), 1)
self.assertIs(w[0].category, RemovedInWagtail18Warning)

Wyświetl plik

@ -6,7 +6,6 @@ import json
import os
import time
import unittest
import warnings
import mock
from django.core import management
@ -16,7 +15,6 @@ from django.utils.six import StringIO
from elasticsearch.serializer import JSONSerializer
from wagtail.tests.search import models
from wagtail.utils.deprecation import RemovedInWagtail18Warning
from wagtail.wagtailsearch.backends import get_search_backend
from wagtail.wagtailsearch.backends.elasticsearch import ElasticsearchSearchBackend
@ -1095,16 +1093,3 @@ class TestAtomicRebuilder(TestCase):
# Index should be gone
self.assertFalse(self.es.indices.exists(current_index_name))
class TestOldNameDeprecationWarning(TestCase):
def test_old_name_deprecation(self):
from wagtail.wagtailsearch.backends.elasticsearch import ElasticSearch
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
ElasticSearch({})
self.assertEqual(len(w), 1)
self.assertIs(w[0].category, RemovedInWagtail18Warning)