diff --git a/zinnia/admin/category.py b/zinnia/admin/category.py index 3c6cf3617..8d6cb1169 100644 --- a/zinnia/admin/category.py +++ b/zinnia/admin/category.py @@ -2,7 +2,7 @@ from django.contrib import admin from django.urls import NoReverseMatch from django.utils.html import format_html -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from zinnia.admin.forms import CategoryAdminForm diff --git a/zinnia/admin/entry.py b/zinnia/admin/entry.py index b00696e0e..6f1cfddee 100644 --- a/zinnia/admin/entry.py +++ b/zinnia/admin/entry.py @@ -10,8 +10,8 @@ from django.utils.html import conditional_escape from django.utils.html import format_html from django.utils.html import format_html_join -from django.utils.translation import ugettext_lazy as _ -from django.utils.translation import ungettext_lazy +from django.utils.translation import gettext_lazy as _ +from django.utils.translation import ngettext_lazy from zinnia import settings from zinnia.admin.filters import AuthorListFilter @@ -87,7 +87,7 @@ def get_title(self, entry): entry.pingback_count + entry.trackback_count) if reaction_count: - return ungettext_lazy( + return ngettext_lazy( '%(title)s (%(reactions)i reaction)', '%(title)s (%(reactions)i reactions)', reaction_count) % \ {'title': title, diff --git a/zinnia/admin/fields.py b/zinnia/admin/fields.py index 6475bd569..9abb53511 100644 --- a/zinnia/admin/fields.py +++ b/zinnia/admin/fields.py @@ -1,6 +1,6 @@ """Fields for Zinnia admin""" from django import forms -from django.utils.encoding import smart_text +from django.utils.encoding import smart_str class MPTTModelChoiceIterator(forms.models.ModelChoiceIterator): @@ -33,7 +33,7 @@ def label_from_instance(self, obj): Create labels which represent the tree level of each node when generating option labels. """ - label = smart_text(obj) + label = smart_str(obj) prefix = self.level_indicator * getattr(obj, obj._mptt_meta.level_attr) if prefix: return '%s %s' % (prefix, label) diff --git a/zinnia/admin/filters.py b/zinnia/admin/filters.py index 6790609f1..26a8655eb 100644 --- a/zinnia/admin/filters.py +++ b/zinnia/admin/filters.py @@ -1,9 +1,9 @@ """Filters for Zinnia admin""" from django.contrib.admin import SimpleListFilter from django.db.models import Count -from django.utils.encoding import smart_text -from django.utils.translation import ugettext_lazy as _ -from django.utils.translation import ungettext_lazy +from django.utils.encoding import smart_str +from django.utils.translation import gettext_lazy as _ +from django.utils.translation import ngettext_lazy from zinnia.models.author import Author from zinnia.models.category import Category @@ -25,11 +25,11 @@ def lookups(self, request, model_admin): '-count_entries_published', '-pk') for active_object in active_objects: yield ( - str(active_object.pk), ungettext_lazy( + str(active_object.pk), ngettext_lazy( '%(item)s (%(count)i entry)', '%(item)s (%(count)i entries)', active_object.count_entries_published) % { - 'item': smart_text(active_object), + 'item': smart_str(active_object), 'count': active_object.count_entries_published}) def queryset(self, request, queryset): diff --git a/zinnia/admin/forms.py b/zinnia/admin/forms.py index 83263a264..49784d14a 100644 --- a/zinnia/admin/forms.py +++ b/zinnia/admin/forms.py @@ -1,7 +1,7 @@ """Forms for Zinnia admin""" from django import forms from django.contrib.admin.widgets import RelatedFieldWidgetWrapper -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from mptt.forms import TreeNodeChoiceField diff --git a/zinnia/admin/widgets.py b/zinnia/admin/widgets.py index 5867a0fbc..25a0a0aae 100644 --- a/zinnia/admin/widgets.py +++ b/zinnia/admin/widgets.py @@ -5,7 +5,7 @@ from django.contrib.admin import widgets from django.contrib.staticfiles.storage import staticfiles_storage from django.forms import Media -from django.utils.encoding import force_text +from django.utils.encoding import force_str from django.utils.safestring import mark_safe from tagging.models import Tag @@ -47,7 +47,7 @@ def optgroups(self, name, value, attrs=None): for subvalue, sublabel in choices: selected = ( - force_text(subvalue) in value and + force_str(subvalue) in value and (has_selected is False or self.allow_multiple_selected) ) if selected is True and has_selected is False: diff --git a/zinnia/apps.py b/zinnia/apps.py index 78674151e..7c1c6260e 100644 --- a/zinnia/apps.py +++ b/zinnia/apps.py @@ -1,6 +1,6 @@ """Apps for Zinnia""" from django.apps import AppConfig -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ class ZinniaConfig(AppConfig): diff --git a/zinnia/breadcrumbs.py b/zinnia/breadcrumbs.py index 4f04ff49e..5846945e9 100644 --- a/zinnia/breadcrumbs.py +++ b/zinnia/breadcrumbs.py @@ -7,7 +7,7 @@ from django.utils.dateformat import DateFormat from django.utils.timezone import is_aware from django.utils.timezone import localtime -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ class Crumb(object): diff --git a/zinnia/comparison.py b/zinnia/comparison.py index 793e35da6..45193b897 100644 --- a/zinnia/comparison.py +++ b/zinnia/comparison.py @@ -4,7 +4,6 @@ from django.contrib.sites.models import Site from django.core.cache import InvalidCacheBackendError from django.core.cache import caches -from django.utils import six from django.utils.functional import cached_property from django.utils.html import strip_tags @@ -94,7 +93,7 @@ def raw_dataset(self): for item in queryset: item = list(item) item_pk = item.pop(0) - datas = ' '.join(map(six.text_type, item)) + datas = ' '.join(map(str, item)) dataset[item_pk] = self.raw_clean(datas) return dataset diff --git a/zinnia/feeds.py b/zinnia/feeds.py index 168276f65..5dd45b121 100644 --- a/zinnia/feeds.py +++ b/zinnia/feeds.py @@ -13,9 +13,9 @@ from django.template.defaultfilters import slugify from django.urls import NoReverseMatch from django.urls import reverse -from django.utils.encoding import smart_text +from django.utils.encoding import smart_str from django.utils.feedgenerator import Atom1Feed -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ import django_comments as comments @@ -260,14 +260,14 @@ def get_title(self, obj): Title of the feed. """ return _('Entries for the author %(object)s') % { - 'object': smart_text(obj.__str__())} + 'object': smart_str(obj.__str__())} def description(self, obj): """ Description of the feed. """ return _('The last entries by %(object)s') % { - 'object': smart_text(obj.__str__())} + 'object': smart_str(obj.__str__())} class TagEntries(EntryFeed): diff --git a/zinnia/flags.py b/zinnia/flags.py index 29b970388..aa089f277 100644 --- a/zinnia/flags.py +++ b/zinnia/flags.py @@ -1,6 +1,7 @@ """Comment flags for Zinnia""" +from functools import lru_cache + from django.contrib.auth import get_user_model -from django.utils.lru_cache import lru_cache from zinnia.settings import COMMENT_FLAG_USER_ID diff --git a/zinnia/markups.py b/zinnia/markups.py index 584fd8953..5c528a8a2 100644 --- a/zinnia/markups.py +++ b/zinnia/markups.py @@ -5,7 +5,7 @@ import warnings from django.utils.encoding import force_bytes -from django.utils.encoding import force_text +from django.utils.encoding import force_str from django.utils.html import linebreaks from zinnia.settings import MARKDOWN_EXTENSIONS @@ -24,7 +24,7 @@ def textile(value): RuntimeWarning) return value - return textile.textile(force_text(value)) + return textile.textile(force_str(value)) def markdown(value, extensions=MARKDOWN_EXTENSIONS): @@ -41,7 +41,7 @@ def markdown(value, extensions=MARKDOWN_EXTENSIONS): RuntimeWarning) return value - return markdown.markdown(force_text(value), extensions=extensions) + return markdown.markdown(force_str(value), extensions=extensions) def restructuredtext(value, settings=RESTRUCTUREDTEXT_SETTINGS): @@ -58,7 +58,7 @@ def restructuredtext(value, settings=RESTRUCTUREDTEXT_SETTINGS): parts = publish_parts(source=force_bytes(value), writer_name='html4css1', settings_overrides=settings) - return force_text(parts['fragment']) + return force_str(parts['fragment']) def html_format(value): diff --git a/zinnia/models/author.py b/zinnia/models/author.py index cd9a7c782..c70f82695 100644 --- a/zinnia/models/author.py +++ b/zinnia/models/author.py @@ -3,7 +3,6 @@ from django.conf import settings from django.db import models from django.urls import reverse -from django.utils.encoding import python_2_unicode_compatible from zinnia.managers import EntryRelatedPublishedManager from zinnia.managers import entries_published @@ -28,7 +27,6 @@ class Meta: abstract = True -@python_2_unicode_compatible class Author(safe_get_user_model(), AuthorPublishedManager): """ diff --git a/zinnia/models/category.py b/zinnia/models/category.py index 2959367e0..95c7907fb 100644 --- a/zinnia/models/category.py +++ b/zinnia/models/category.py @@ -1,8 +1,7 @@ """Category model for Zinnia""" from django.db import models from django.urls import reverse -from django.utils.encoding import python_2_unicode_compatible -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from mptt.managers import TreeManager from mptt.models import MPTTModel @@ -12,7 +11,6 @@ from zinnia.managers import entries_published -@python_2_unicode_compatible class Category(MPTTModel): """ Simple model for categorizing entries. diff --git a/zinnia/models_bases/entry.py b/zinnia/models_bases/entry.py index 52a3252bc..2d9d2d09c 100644 --- a/zinnia/models_bases/entry.py +++ b/zinnia/models_bases/entry.py @@ -7,10 +7,9 @@ from django.template.defaultfilters import slugify from django.urls import reverse from django.utils import timezone -from django.utils.encoding import python_2_unicode_compatible from django.utils.html import strip_tags from django.utils.text import Truncator -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ import django_comments as comments from django_comments.models import CommentFlag @@ -34,7 +33,6 @@ from zinnia.url_shortener import get_url_shortener -@python_2_unicode_compatible class CoreEntry(models.Model): """ Abstract core entry model class providing diff --git a/zinnia/moderator.py b/zinnia/moderator.py index 674a27439..4cc5be103 100644 --- a/zinnia/moderator.py +++ b/zinnia/moderator.py @@ -6,7 +6,7 @@ from django.template import loader from django.utils.translation import activate from django.utils.translation import get_language -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django_comments.moderation import CommentModerator diff --git a/zinnia/preview.py b/zinnia/preview.py index e76b61217..d795c2734 100644 --- a/zinnia/preview.py +++ b/zinnia/preview.py @@ -3,8 +3,6 @@ from bs4 import BeautifulSoup -from django.utils import six -from django.utils.encoding import python_2_unicode_compatible from django.utils.functional import cached_property from django.utils.html import strip_tags from django.utils.text import Truncator @@ -14,7 +12,6 @@ from zinnia.settings import PREVIEW_SPLITTERS -@python_2_unicode_compatible class HTMLPreview(object): """ Build an HTML preview of an HTML content. @@ -52,7 +49,7 @@ def __str__(self): """ Method used to render the preview in templates. """ - return six.text_type(self.preview) + return str(self.preview) def build_preview(self): """ diff --git a/zinnia/search.py b/zinnia/search.py index ca4285214..8fe2f944d 100644 --- a/zinnia/search.py +++ b/zinnia/search.py @@ -1,6 +1,5 @@ """Search module with complex query parsing for Zinnia""" from django.db.models import Q -from django.utils import six from pyparsing import CaselessLiteral from pyparsing import Combine @@ -31,7 +30,7 @@ def create_q(token): query = getattr(token, 'query', '') wildcards = None - if isinstance(query, six.string_types): # Unicode -> Quoted string + if isinstance(query, str): # Unicode -> Quoted string search = query else: # List -> No quoted string (possible wildcards) if len(query) == 1: diff --git a/zinnia/templatetags/zinnia.py b/zinnia/templatetags/zinnia.py index 0da549af7..5ea2aa947 100644 --- a/zinnia/templatetags/zinnia.py +++ b/zinnia/templatetags/zinnia.py @@ -13,7 +13,7 @@ from django.template.defaultfilters import stringfilter from django.template.loader import select_template from django.utils import timezone -from django.utils.encoding import smart_text +from django.utils.encoding import smart_str from django.utils.html import conditional_escape from django.utils.safestring import mark_safe @@ -225,8 +225,8 @@ def get_recent_comments(number=5, template='zinnia/tags/comments_recent.html'): """ Return the most recent comments. """ - # Using map(smart_text... fix bug related to issue #8554 - entry_published_pks = map(smart_text, + # Using map(smart_str... fix bug related to issue #8554 + entry_published_pks = map(smart_str, Entry.published.values_list('id', flat=True)) content_type = ContentType.objects.get_for_model(Entry) @@ -247,7 +247,7 @@ def get_recent_linkbacks(number=5, """ Return the most recent linkbacks. """ - entry_published_pks = map(smart_text, + entry_published_pks = map(smart_str, Entry.published.values_list('id', flat=True)) content_type = ContentType.objects.get_for_model(Entry) @@ -400,7 +400,7 @@ def widont(value, autoescape=None): def replace(matchobj): return ' %s' % matchobj.group(1) - value = END_PUNCTUATION_WIDONT_REGEXP.sub(replace, esc(smart_text(value))) + value = END_PUNCTUATION_WIDONT_REGEXP.sub(replace, esc(smart_str(value))) value = WIDONT_REGEXP.sub(replace, value) value = DOUBLE_SPACE_PUNCTUATION_WIDONT_REGEXP.sub(replace, value) diff --git a/zinnia/tests/test_admin_fields.py b/zinnia/tests/test_admin_fields.py index 07fc9aa61..8733bd08b 100644 --- a/zinnia/tests/test_admin_fields.py +++ b/zinnia/tests/test_admin_fields.py @@ -1,6 +1,6 @@ """Test cases for Zinnia's admin fields""" from django.test import TestCase -from django.utils.encoding import smart_text +from django.utils.encoding import smart_str from zinnia.admin.fields import MPTTModelChoiceIterator from zinnia.admin.fields import MPTTModelMultipleChoiceField @@ -23,7 +23,7 @@ def prepare_value(self, value): return value.pk def label_from_instance(self, obj): - return smart_text(obj) + return smart_str(obj) field = FakeField() iterator = MPTTModelChoiceIterator(field) diff --git a/zinnia/tests/test_feeds.py b/zinnia/tests/test_feeds.py index 7c8dde256..36a14fff6 100644 --- a/zinnia/tests/test_feeds.py +++ b/zinnia/tests/test_feeds.py @@ -10,7 +10,7 @@ from django.test import TestCase from django.test.utils import override_settings from django.utils import timezone -from django.utils.encoding import smart_text +from django.utils.encoding import smart_str from django.utils.feedgenerator import Atom1Feed from django.utils.feedgenerator import DefaultFeed from django.utils.translation import activate @@ -229,7 +229,7 @@ def test_category_entries(self): def test_category_title_non_ascii(self): self.create_published_entry() - self.category.title = smart_text('Catégorie') + self.category.title = smart_str('Catégorie') self.category.save() feed = CategoryEntries() self.assertEqual(feed.get_title(self.category), @@ -252,16 +252,16 @@ def test_author_entries(self): self.author.__str__()) def test_author_title_non_ascii(self): - self.author.first_name = smart_text('Léon') + self.author.first_name = smart_str('Léon') self.author.last_name = 'Bloom' self.author.save() self.create_published_entry() feed = AuthorEntries() self.assertEqual(feed.get_title(self.author), - smart_text('Entries for the author %s' % + smart_str('Entries for the author %s' % self.author.__str__())) self.assertEqual(feed.description(self.author), - smart_text('The last entries by %s' % + smart_str('The last entries by %s' % self.author.__str__())) def test_tag_entries(self): @@ -278,7 +278,7 @@ def test_tag_entries(self): def test_tag_title_non_ascii(self): entry = self.create_published_entry() - tag_unicode = smart_text('accentué') + tag_unicode = smart_str('accentué') entry.tags = tag_unicode entry.save() feed = TagEntries() diff --git a/zinnia/tests/test_pingback.py b/zinnia/tests/test_pingback.py index a05e544fe..e38eb62af 100644 --- a/zinnia/tests/test_pingback.py +++ b/zinnia/tests/test_pingback.py @@ -1,4 +1,5 @@ """Test cases for Zinnia's PingBack API""" +from io import BytesIO from urllib.error import HTTPError from urllib.parse import urlsplit from xmlrpc.client import ServerProxy @@ -9,7 +10,6 @@ from django.contrib.sites.models import Site from django.test import TestCase from django.test.utils import override_settings -from django.utils import six from django.utils import timezone import django_comments as comments @@ -54,7 +54,7 @@ def fake_urlopen(self, url): if not netloc: raise if self.site.domain == netloc: - response = six.BytesIO(self.client.get(url).content) + response = BytesIO(self.client.get(url).content) return response raise HTTPError(url, 404, 'unavailable url', {}, None) diff --git a/zinnia/tests/test_views.py b/zinnia/tests/test_views.py index 4443c0bde..8fa58e246 100644 --- a/zinnia/tests/test_views.py +++ b/zinnia/tests/test_views.py @@ -8,7 +8,7 @@ from django.test import TestCase from django.test.utils import override_settings from django.utils import timezone -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ import django_comments as comments diff --git a/zinnia/tests/utils.py b/zinnia/tests/utils.py index ec1898b92..99f0a0184 100644 --- a/zinnia/tests/utils.py +++ b/zinnia/tests/utils.py @@ -1,6 +1,7 @@ """Utils for Zinnia's tests""" import functools from datetime import datetime as original_datetime +from io import BytesIO from unittest import SkipTest from unittest import skipIf from urllib.parse import parse_qs @@ -11,7 +12,6 @@ from django.template import Origin from django.template.loaders.base import Loader from django.test.client import Client -from django.utils import six from django.utils import timezone @@ -29,7 +29,7 @@ def request(self, host, handler, request_body, verbose=0): response = self.client.post(handler, request_body, content_type="text/xml") - res = six.BytesIO(response.content) + res = BytesIO(response.content) setattr(res, 'getheader', lambda *args: '') # For Python >= 2.7 res.seek(0) return self.parse_response(res) diff --git a/zinnia/urls/__init__.py b/zinnia/urls/__init__.py index 788d0d008..7a9c81c0a 100644 --- a/zinnia/urls/__init__.py +++ b/zinnia/urls/__init__.py @@ -1,7 +1,7 @@ """Defaults urls for the Zinnia project""" from django.conf.urls import include from django.conf.urls import url -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext_lazy from zinnia.settings import TRANSLATED_URLS @@ -11,7 +11,7 @@ def i18n_url(url, translate=TRANSLATED_URLS): Translate or not an URL part. """ if translate: - return ugettext_lazy(url) + return gettext_lazy(url) return url diff --git a/zinnia/views/mixins/entry_preview.py b/zinnia/views/mixins/entry_preview.py index 790344d0c..217d2d443 100644 --- a/zinnia/views/mixins/entry_preview.py +++ b/zinnia/views/mixins/entry_preview.py @@ -1,6 +1,6 @@ """Preview mixins for Zinnia views""" from django.http import Http404 -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ class EntryPreviewMixin(object): diff --git a/zinnia/views/search.py b/zinnia/views/search.py index 6ed506387..720f38276 100644 --- a/zinnia/views/search.py +++ b/zinnia/views/search.py @@ -1,5 +1,5 @@ """Views for Zinnia entries search""" -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django.views.generic.list import ListView from zinnia.models.entry import Entry diff --git a/zinnia/views/tags.py b/zinnia/views/tags.py index 653b0ffa2..d54ce90cd 100644 --- a/zinnia/views/tags.py +++ b/zinnia/views/tags.py @@ -1,7 +1,7 @@ """Views for Zinnia tags""" from django.http import Http404 from django.template.defaultfilters import slugify -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django.views.generic.list import BaseListView from django.views.generic.list import ListView diff --git a/zinnia/xmlrpc/metaweblog.py b/zinnia/xmlrpc/metaweblog.py index d12f7731a..bd12c8d6e 100644 --- a/zinnia/xmlrpc/metaweblog.py +++ b/zinnia/xmlrpc/metaweblog.py @@ -9,7 +9,6 @@ from django.core.files.storage import default_storage from django.template.defaultfilters import slugify from django.urls import reverse -from django.utils import six from django.utils import timezone from django.utils.translation import gettext as _ @@ -130,7 +129,7 @@ def post_structure(entry, site): """ author = entry.authors.all()[0] return {'title': entry.title, - 'description': six.text_type(entry.html_content), + 'description': str(entry.html_content), 'link': '%s://%s%s' % (PROTOCOL, site.domain, entry.get_absolute_url()), # Basic Extensions diff --git a/zinnia/xmlrpc/pingback.py b/zinnia/xmlrpc/pingback.py index fa867efdd..c67a8c924 100644 --- a/zinnia/xmlrpc/pingback.py +++ b/zinnia/xmlrpc/pingback.py @@ -10,9 +10,8 @@ from django.contrib.sites.models import Site from django.urls import Resolver404 from django.urls import resolve -from django.utils import six from django.utils.html import strip_tags -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ import django_comments as comments @@ -44,7 +43,7 @@ def generate_pingback_content(soup, target, max_length, trunc_char='...'): """ link = soup.find('a', href=target) - content = strip_tags(six.text_type(link.findParent())) + content = strip_tags(str(link.findParent())) index = content.index(link.string) if len(content) > max_length: @@ -111,7 +110,7 @@ def pingback_ping(source, target): return TARGET_IS_NOT_PINGABLE soup = BeautifulSoup(document, 'html.parser') - title = six.text_type(soup.find('title')) + title = str(soup.find('title')) title = title and strip_tags(title) or _('No title') description = generate_pingback_content(soup, target, PINGBACK_CONTENT_LENGTH)