diff --git a/django/__init__.py b/django/__init__.py index 4da99681eef..ee35e129a10 100644 --- a/django/__init__.py +++ b/django/__init__.py @@ -14,12 +14,11 @@ def setup(set_prefix=True): from django.apps import apps from django.conf import settings from django.urls import set_script_prefix - from django.utils.encoding import force_text from django.utils.log import configure_logging configure_logging(settings.LOGGING_CONFIG, settings.LOGGING) if set_prefix: set_script_prefix( - '/' if settings.FORCE_SCRIPT_NAME is None else force_text(settings.FORCE_SCRIPT_NAME) + '/' if settings.FORCE_SCRIPT_NAME is None else settings.FORCE_SCRIPT_NAME ) apps.populate(settings.INSTALLED_APPS) diff --git a/django/contrib/admin/helpers.py b/django/contrib/admin/helpers.py index b30dce95d23..6c69496d3b6 100644 --- a/django/contrib/admin/helpers.py +++ b/django/contrib/admin/helpers.py @@ -10,7 +10,6 @@ from django.core.exceptions import ObjectDoesNotExist from django.db.models.fields.related import ManyToManyRel from django.forms.utils import flatatt from django.template.defaultfilters import capfirst, linebreaksbr -from django.utils.encoding import force_text from django.utils.html import conditional_escape, format_html from django.utils.safestring import mark_safe from django.utils.translation import gettext, gettext_lazy as _ @@ -135,7 +134,7 @@ class AdminField: def label_tag(self): classes = [] - contents = conditional_escape(force_text(self.field.label)) + contents = conditional_escape(self.field.label) if self.is_checkbox: classes.append('vCheckboxLabel') @@ -193,9 +192,7 @@ class AdminReadonlyField: if not self.is_first: attrs["class"] = "inline" label = self.field['label'] - return format_html('{}:', - flatatt(attrs), - capfirst(force_text(label))) + return format_html('{}:', flatatt(attrs), capfirst(label)) def contents(self): from django.contrib.admin.templatetags.admin_list import _boolean_icon @@ -213,7 +210,7 @@ class AdminReadonlyField: if hasattr(value, "__html__"): result_repr = value else: - result_repr = linebreaksbr(force_text(value)) + result_repr = linebreaksbr(value) else: if isinstance(f.remote_field, ManyToManyRel) and value is not None: result_repr = ", ".join(map(str, value.all())) diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index 5a5682a6cd8..c3801889f6b 100644 --- a/django/contrib/admin/options.py +++ b/django/contrib/admin/options.py @@ -1058,7 +1058,7 @@ class ModelAdmin(BaseModelAdmin): else: obj_repr = force_text(obj) msg_dict = { - 'name': force_text(opts.verbose_name), + 'name': opts.verbose_name, 'obj': obj_repr, } # Here, we distinguish between different save types by checking for @@ -1150,7 +1150,7 @@ class ModelAdmin(BaseModelAdmin): preserved_filters = self.get_preserved_filters(request) msg_dict = { - 'name': force_text(opts.verbose_name), + 'name': opts.verbose_name, 'obj': format_html('{}', urlquote(request.path), obj), } if "_continue" in request.POST: @@ -1320,8 +1320,8 @@ class ModelAdmin(BaseModelAdmin): self.message_user( request, _('The %(name)s "%(obj)s" was deleted successfully.') % { - 'name': force_text(opts.verbose_name), - 'obj': force_text(obj_display), + 'name': opts.verbose_name, + 'obj': obj_display, }, messages.SUCCESS, ) @@ -1394,7 +1394,7 @@ class ModelAdmin(BaseModelAdmin): and return a redirect to the admin index page. """ msg = _("""%(name)s with ID "%(key)s" doesn't exist. Perhaps it was deleted?""") % { - 'name': force_text(opts.verbose_name), + 'name': opts.verbose_name, 'key': unquote(object_id), } self.message_user(request, msg, messages.WARNING) @@ -1478,7 +1478,7 @@ class ModelAdmin(BaseModelAdmin): context = dict( self.admin_site.each_context(request), - title=(_('Add %s') if add else _('Change %s')) % force_text(opts.verbose_name), + title=(_('Add %s') if add else _('Change %s')) % opts.verbose_name, adminform=adminForm, object_id=object_id, original=obj, @@ -1620,7 +1620,6 @@ class ModelAdmin(BaseModelAdmin): ) % { 'count': changecount, 'name': model_ngettext(opts, changecount), - 'obj': force_text(obj), } self.message_user(request, msg, messages.SUCCESS) @@ -1768,7 +1767,7 @@ class ModelAdmin(BaseModelAdmin): context = dict( self.admin_site.each_context(request), - title=_('Change history: %s') % force_text(obj), + title=_('Change history: %s') % obj, action_list=action_list, module_name=capfirst(force_text(opts.verbose_name_plural)), object=obj, diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py index 2fd0922c5ec..613db7d90db 100644 --- a/django/contrib/admin/templatetags/admin_list.py +++ b/django/contrib/admin/templatetags/admin_list.py @@ -281,7 +281,7 @@ def items_for_result(cl, result, form): result_repr = mark_safe(force_text(bf.errors) + force_text(bf)) yield format_html('{}', row_class, result_repr) if form and not form[cl.model._meta.pk.name].is_hidden: - yield format_html('{}', force_text(form[cl.model._meta.pk.name])) + yield format_html('{}', form[cl.model._meta.pk.name]) class ResultList(list): @@ -308,7 +308,7 @@ def result_hidden_fields(cl): if cl.formset: for res, form in zip(cl.result_list, cl.formset.forms): if form[cl.model._meta.pk.name].is_hidden: - yield mark_safe(force_text(form[cl.model._meta.pk.name])) + yield mark_safe(form[cl.model._meta.pk.name]) @register.inclusion_tag("admin/change_list_results.html") diff --git a/django/contrib/admin/utils.py b/django/contrib/admin/utils.py index 9a89f4c5784..4d39693e5dd 100644 --- a/django/contrib/admin/utils.py +++ b/django/contrib/admin/utils.py @@ -11,7 +11,7 @@ from django.db.models.sql.constants import QUERY_TERMS from django.forms.utils import pretty_name from django.urls import NoReverseMatch, reverse from django.utils import formats, timezone -from django.utils.encoding import force_text, smart_text +from django.utils.encoding import force_text from django.utils.html import format_html from django.utils.text import capfirst from django.utils.translation import ngettext, override as translation_override @@ -136,8 +136,7 @@ def get_deleted_objects(objs, opts, user, admin_site, using): has_admin = obj.__class__ in admin_site._registry opts = obj._meta - no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), - force_text(obj)) + no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), obj) if has_admin: try: @@ -249,8 +248,8 @@ def model_format_dict(obj): else: opts = obj return { - 'verbose_name': force_text(opts.verbose_name), - 'verbose_name_plural': force_text(opts.verbose_name_plural) + 'verbose_name': opts.verbose_name, + 'verbose_name_plural': opts.verbose_name_plural, } @@ -384,7 +383,7 @@ def help_text_for_field(name, model): else: if hasattr(field, 'help_text'): help_text = field.help_text - return smart_text(help_text) + return help_text def display_for_field(value, field, empty_value_display): diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py index 9fb65a24534..6d89ead6ca8 100644 --- a/django/contrib/admin/views/main.py +++ b/django/contrib/admin/views/main.py @@ -16,7 +16,6 @@ from django.core.exceptions import ( from django.core.paginator import InvalidPage from django.db import models from django.urls import reverse -from django.utils.encoding import force_text from django.utils.http import urlencode from django.utils.translation import gettext @@ -79,7 +78,7 @@ class ChangeList: title = gettext('Select %s') else: title = gettext('Select %s to change') - self.title = title % force_text(self.opts.verbose_name) + self.title = title % self.opts.verbose_name self.pk_attname = self.lookup_opts.pk.attname def get_filters_params(self, params=None): diff --git a/django/contrib/auth/admin.py b/django/contrib/auth/admin.py index 2b432d75d23..3661d226a75 100644 --- a/django/contrib/auth/admin.py +++ b/django/contrib/auth/admin.py @@ -14,7 +14,6 @@ from django.http import Http404, HttpResponseRedirect from django.template.response import TemplateResponse from django.urls import reverse from django.utils.decorators import method_decorator -from django.utils.encoding import force_text from django.utils.html import escape from django.utils.translation import gettext, gettext_lazy as _ from django.views.decorators.csrf import csrf_protect @@ -135,7 +134,7 @@ class UserAdmin(admin.ModelAdmin): user = self.get_object(request, unquote(id)) if user is None: raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % { - 'name': force_text(self.model._meta.verbose_name), + 'name': self.model._meta.verbose_name, 'key': escape(id), }) if request.method == 'POST': diff --git a/django/contrib/auth/base_user.py b/django/contrib/auth/base_user.py index 63f083b908e..34dd6ac2f2f 100644 --- a/django/contrib/auth/base_user.py +++ b/django/contrib/auth/base_user.py @@ -10,7 +10,6 @@ from django.contrib.auth.hashers import ( ) from django.db import models from django.utils.crypto import get_random_string, salted_hmac -from django.utils.encoding import force_text from django.utils.translation import gettext_lazy as _ @@ -142,4 +141,4 @@ class AbstractBaseUser(models.Model): @classmethod def normalize_username(cls, username): - return unicodedata.normalize('NFKC', force_text(username)) + return unicodedata.normalize('NFKC', username) if username else username diff --git a/django/contrib/auth/views.py b/django/contrib/auth/views.py index ae52f5414dc..4635ff81d75 100644 --- a/django/contrib/auth/views.py +++ b/django/contrib/auth/views.py @@ -19,7 +19,6 @@ from django.template.response import TemplateResponse from django.urls import reverse, reverse_lazy from django.utils.decorators import method_decorator from django.utils.deprecation import RemovedInDjango21Warning -from django.utils.encoding import force_text from django.utils.http import is_safe_url, urlsafe_base64_decode from django.utils.translation import gettext_lazy as _ from django.views.decorators.cache import never_cache @@ -303,7 +302,7 @@ def password_reset_confirm(request, uidb64=None, token=None, post_reset_redirect = resolve_url(post_reset_redirect) try: # urlsafe_base64_decode() decodes to bytestring - uid = force_text(urlsafe_base64_decode(uidb64)) + uid = urlsafe_base64_decode(uidb64).decode() user = UserModel._default_manager.get(pk=uid) except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist): user = None @@ -447,7 +446,7 @@ class PasswordResetConfirmView(PasswordContextMixin, FormView): def get_user(self, uidb64): try: # urlsafe_base64_decode() decodes to bytestring - uid = force_text(urlsafe_base64_decode(uidb64)) + uid = urlsafe_base64_decode(uidb64).decode() user = UserModel._default_manager.get(pk=uid) except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist): user = None diff --git a/django/contrib/staticfiles/management/commands/collectstatic.py b/django/contrib/staticfiles/management/commands/collectstatic.py index 5e710e9d340..81382066a9c 100644 --- a/django/contrib/staticfiles/management/commands/collectstatic.py +++ b/django/contrib/staticfiles/management/commands/collectstatic.py @@ -7,7 +7,6 @@ from django.contrib.staticfiles.storage import staticfiles_storage from django.core.files.storage import FileSystemStorage from django.core.management.base import BaseCommand, CommandError from django.core.management.color import no_style -from django.utils.encoding import force_text from django.utils.functional import cached_property @@ -234,9 +233,9 @@ class Command(BaseCommand): for f in files: fpath = os.path.join(path, f) if self.dry_run: - self.log("Pretending to delete '%s'" % force_text(fpath), level=1) + self.log("Pretending to delete '%s'" % fpath, level=1) else: - self.log("Deleting '%s'" % force_text(fpath), level=1) + self.log("Deleting '%s'" % fpath, level=1) try: full_path = self.storage.path(fpath) except NotImplementedError: diff --git a/django/contrib/staticfiles/management/commands/findstatic.py b/django/contrib/staticfiles/management/commands/findstatic.py index 067b229f6df..4b7df327d09 100644 --- a/django/contrib/staticfiles/management/commands/findstatic.py +++ b/django/contrib/staticfiles/management/commands/findstatic.py @@ -2,7 +2,6 @@ import os from django.contrib.staticfiles import finders from django.core.management.base import LabelCommand -from django.utils.encoding import force_text class Command(LabelCommand): @@ -20,18 +19,17 @@ class Command(LabelCommand): def handle_label(self, path, **options): verbosity = options['verbosity'] result = finders.find(path, all=options['all']) - path = force_text(path) if verbosity >= 2: searched_locations = ( "\nLooking in the following locations:\n %s" % - "\n ".join(force_text(location) for location in finders.searched_locations) + "\n ".join(finders.searched_locations) ) else: searched_locations = '' if result: if not isinstance(result, (list, tuple)): result = [result] - result = (force_text(os.path.realpath(path)) for path in result) + result = (os.path.realpath(path) for path in result) if verbosity >= 1: file_list = '\n '.join(result) return ("Found '%s' here:\n %s%s" % diff --git a/django/contrib/staticfiles/storage.py b/django/contrib/staticfiles/storage.py index ac430df40d6..19f33f351f0 100644 --- a/django/contrib/staticfiles/storage.py +++ b/django/contrib/staticfiles/storage.py @@ -14,7 +14,7 @@ from django.core.cache import ( from django.core.exceptions import ImproperlyConfigured from django.core.files.base import ContentFile from django.core.files.storage import FileSystemStorage, get_storage_class -from django.utils.encoding import force_bytes, force_text +from django.utils.encoding import force_bytes from django.utils.functional import LazyObject @@ -308,7 +308,7 @@ class HashedFilesMixin: self.delete(hashed_name) saved_name = self._save(hashed_name, content_file) - hashed_name = force_text(self.clean_name(saved_name)) + hashed_name = self.clean_name(saved_name) # If the file hash stayed the same, this file didn't change if old_hashed_name == hashed_name: substitutions = False @@ -320,7 +320,7 @@ class HashedFilesMixin: if not hashed_file_exists: processed = True saved_name = self._save(hashed_name, original_file) - hashed_name = force_text(self.clean_name(saved_name)) + hashed_name = self.clean_name(saved_name) # and then set the cache accordingly hashed_files[hash_key] = hashed_name diff --git a/django/core/files/base.py b/django/core/files/base.py index 90b75b18cb0..ff0a289dead 100644 --- a/django/core/files/base.py +++ b/django/core/files/base.py @@ -2,7 +2,6 @@ import os from io import BytesIO, StringIO, UnsupportedOperation from django.core.files.utils import FileProxyMixin -from django.utils.encoding import force_text class File(FileProxyMixin): @@ -17,7 +16,7 @@ class File(FileProxyMixin): self.mode = file.mode def __str__(self): - return force_text(self.name or '') + return self.name or '' def __repr__(self): return "<%s: %s>" % (self.__class__.__name__, self or "None") diff --git a/django/core/files/storage.py b/django/core/files/storage.py index b3bb2dc5890..ff51d89cfa9 100644 --- a/django/core/files/storage.py +++ b/django/core/files/storage.py @@ -11,7 +11,7 @@ from django.utils import timezone from django.utils._os import safe_join from django.utils.crypto import get_random_string from django.utils.deconstruct import deconstructible -from django.utils.encoding import filepath_to_uri, force_text +from django.utils.encoding import filepath_to_uri from django.utils.functional import LazyObject, cached_property from django.utils.module_loading import import_string from django.utils.text import get_valid_filename @@ -288,7 +288,7 @@ class FileSystemStorage(Storage): os.chmod(full_path, self.file_permissions_mode) # Store filenames with forward slashes, even on Windows. - return force_text(name.replace('\\', '/')) + return name.replace('\\', '/') def delete(self, name): assert name, "The name argument is not allowed to be empty." diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py index 56633fd89e5..2ec6269bead 100644 --- a/django/core/handlers/wsgi.py +++ b/django/core/handlers/wsgi.py @@ -8,7 +8,7 @@ from django.core import signals from django.core.handlers import base from django.http import HttpRequest, QueryDict, parse_cookie from django.urls import set_script_prefix -from django.utils.encoding import force_text, repercent_broken_unicode +from django.utils.encoding import repercent_broken_unicode from django.utils.functional import cached_property _slashes_re = re.compile(br'/+') @@ -173,7 +173,7 @@ def get_script_name(environ): set (to anything). """ if settings.FORCE_SCRIPT_NAME is not None: - return force_text(settings.FORCE_SCRIPT_NAME) + return settings.FORCE_SCRIPT_NAME # If Apache's mod_rewrite had a whack at the URL, Apache set either # SCRIPT_URL or REDIRECT_URL to the full resource URL before applying any diff --git a/django/core/management/commands/createcachetable.py b/django/core/management/commands/createcachetable.py index f80fa8834e6..8f9482d3901 100644 --- a/django/core/management/commands/createcachetable.py +++ b/django/core/management/commands/createcachetable.py @@ -6,7 +6,6 @@ from django.db import ( DEFAULT_DB_ALIAS, connections, models, router, transaction, ) from django.db.utils import DatabaseError -from django.utils.encoding import force_text class Command(BaseCommand): @@ -101,7 +100,7 @@ class Command(BaseCommand): except DatabaseError as e: raise CommandError( "Cache table '%s' could not be created.\nThe error was: %s." % - (tablename, force_text(e))) + (tablename, e)) for statement in index_output: curs.execute(statement) diff --git a/django/core/management/commands/inspectdb.py b/django/core/management/commands/inspectdb.py index 09939f28dab..e335901973e 100644 --- a/django/core/management/commands/inspectdb.py +++ b/django/core/management/commands/inspectdb.py @@ -5,7 +5,6 @@ from collections import OrderedDict from django.core.management.base import BaseCommand, CommandError from django.db import DEFAULT_DB_ALIAS, connections from django.db.models.constants import LOOKUP_SEP -from django.utils.encoding import force_text class Command(BaseCommand): @@ -79,7 +78,7 @@ class Command(BaseCommand): table_description = connection.introspection.get_table_description(cursor, table_name) except Exception as e: yield "# Unable to inspect table '%s'" % table_name - yield "# The error was: %s" % force_text(e) + yield "# The error was: %s" % e continue yield '' diff --git a/django/core/management/commands/loaddata.py b/django/core/management/commands/loaddata.py index 1b685e87679..bf55ea55290 100644 --- a/django/core/management/commands/loaddata.py +++ b/django/core/management/commands/loaddata.py @@ -17,7 +17,6 @@ from django.db import ( DEFAULT_DB_ALIAS, DatabaseError, IntegrityError, connections, router, transaction, ) -from django.utils.encoding import force_text from django.utils.functional import cached_property try: @@ -177,7 +176,7 @@ class Command(BaseCommand): 'app_label': obj.object._meta.app_label, 'object_name': obj.object._meta.object_name, 'pk': obj.object.pk, - 'error_msg': force_text(e) + 'error_msg': e, },) raise if objects and show_progress: diff --git a/django/core/management/commands/runserver.py b/django/core/management/commands/runserver.py index 0ef6b5c4acd..3d54df2a6bb 100644 --- a/django/core/management/commands/runserver.py +++ b/django/core/management/commands/runserver.py @@ -11,7 +11,6 @@ from django.core.servers.basehttp import ( WSGIServer, get_internal_wsgi_application, run, ) from django.utils import autoreload -from django.utils.encoding import force_text naiveip_re = re.compile(r"""^(?: @@ -151,7 +150,7 @@ class Command(BaseCommand): try: error_text = ERRORS[e.errno] except KeyError: - error_text = force_text(e) + error_text = e self.stderr.write("Error: %s" % error_text) # Need to use an OS exit because sys.exit doesn't work in a thread os._exit(1) diff --git a/django/core/validators.py b/django/core/validators.py index f55918c8ba7..ebc3f8958c4 100644 --- a/django/core/validators.py +++ b/django/core/validators.py @@ -108,7 +108,6 @@ class URLValidator(RegexValidator): self.schemes = schemes def __call__(self, value): - value = force_text(value) # Check first if the scheme is valid scheme = value.split('://')[0].lower() if scheme not in self.schemes: @@ -188,8 +187,6 @@ class EmailValidator: self.domain_whitelist = whitelist def __call__(self, value): - value = force_text(value) - if not value or '@' not in value: raise ValidationError(self.message, code=self.code) diff --git a/django/db/backends/mysql/introspection.py b/django/db/backends/mysql/introspection.py index 42a47d2dada..9e72bdc1f87 100644 --- a/django/db/backends/mysql/introspection.py +++ b/django/db/backends/mysql/introspection.py @@ -9,7 +9,6 @@ from django.db.backends.base.introspection import ( from django.db.models.indexes import Index from django.utils.datastructures import OrderedSet from django.utils.deprecation import RemovedInDjango21Warning -from django.utils.encoding import force_text FieldInfo = namedtuple('FieldInfo', FieldInfo._fields + ('extra',)) InfoLine = namedtuple('InfoLine', 'col_name data_type max_len num_prec num_scale extra column_default') @@ -79,7 +78,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): fields = [] for line in cursor.description: - col_name = force_text(line[0]) + col_name = line[0] fields.append( FieldInfo(*( (col_name,) + diff --git a/django/db/backends/postgresql/introspection.py b/django/db/backends/postgresql/introspection.py index 7e7091a613f..0ec3bf76806 100644 --- a/django/db/backends/postgresql/introspection.py +++ b/django/db/backends/postgresql/introspection.py @@ -5,7 +5,6 @@ from django.db.backends.base.introspection import ( ) from django.db.models.indexes import Index from django.utils.deprecation import RemovedInDjango21Warning -from django.utils.encoding import force_text class DatabaseIntrospection(BaseDatabaseIntrospection): @@ -79,11 +78,8 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): field_map = {line[0]: line[1:] for line in cursor.fetchall()} cursor.execute("SELECT * FROM %s LIMIT 1" % self.connection.ops.quote_name(table_name)) return [ - FieldInfo(*( - (force_text(line[0]),) + - line[1:6] + - (field_map[force_text(line[0])][0] == 'YES', field_map[force_text(line[0])][1]) - )) for line in cursor.description + FieldInfo(*(line[0:6] + (field_map[line.name][0] == 'YES', field_map[line.name][1]))) + for line in cursor.description ] def get_relations(self, cursor, table_name): diff --git a/django/db/backends/sqlite3/creation.py b/django/db/backends/sqlite3/creation.py index 5dc7d5831bb..9a1b288bf2c 100644 --- a/django/db/backends/sqlite3/creation.py +++ b/django/db/backends/sqlite3/creation.py @@ -4,14 +4,13 @@ import sys from django.core.exceptions import ImproperlyConfigured from django.db.backends.base.creation import BaseDatabaseCreation -from django.utils.encoding import force_text class DatabaseCreation(BaseDatabaseCreation): @staticmethod def is_in_memory_db(database_name): - return database_name == ':memory:' or 'mode=memory' in force_text(database_name) + return database_name == ':memory:' or 'mode=memory' in database_name def _get_test_db_name(self): test_database_name = self.connection.settings_dict['TEST']['NAME'] diff --git a/django/db/migrations/state.py b/django/db/migrations/state.py index a84c43ff85d..e47e1d0e8ee 100644 --- a/django/db/migrations/state.py +++ b/django/db/migrations/state.py @@ -10,7 +10,6 @@ from django.db.models.fields.proxy import OrderWrt from django.db.models.fields.related import RECURSIVE_RELATIONSHIP_CONSTANT from django.db.models.options import DEFAULT_NAMES, normalize_together from django.db.models.utils import make_model_tuple -from django.utils.encoding import force_text from django.utils.functional import cached_property from django.utils.module_loading import import_string from django.utils.version import get_docs_version @@ -363,7 +362,7 @@ class ModelState: def __init__(self, app_label, name, fields, options=None, bases=None, managers=None): self.app_label = app_label - self.name = force_text(name) + self.name = name self.fields = fields self.options = options or {} self.options.setdefault('indexes', []) @@ -411,7 +410,7 @@ class ModelState: continue if isinstance(field, OrderWrt): continue - name = force_text(field.name, strings_only=True) + name = field.name try: fields.append((name, field.clone())) except TypeError as e: @@ -422,7 +421,7 @@ class ModelState: )) if not exclude_rels: for field in model._meta.local_many_to_many: - name = force_text(field.name, strings_only=True) + name = field.name try: fields.append((name, field.clone())) except TypeError as e: @@ -489,8 +488,7 @@ class ModelState: manager_names = set() default_manager_shim = None for manager in model._meta.managers: - manager_name = force_text(manager.name) - if manager_name in manager_names: + if manager.name in manager_names: # Skip overridden managers. continue elif manager.use_in_migrations: @@ -506,8 +504,8 @@ class ModelState: default_manager_shim = new_manager else: continue - manager_names.add(manager_name) - managers.append((manager_name, new_manager)) + manager_names.add(manager.name) + managers.append((manager.name, new_manager)) # Ignore a shimmed default manager called objects if it's the only one. if managers == [('objects', default_manager_shim)]: @@ -528,7 +526,6 @@ class ModelState: # Sort all managers by their creation counter sorted_managers = sorted(self.managers, key=lambda v: v[1].creation_counter) for mgr_name, manager in sorted_managers: - mgr_name = force_text(mgr_name) as_manager, manager_path, qs_path, args, kwargs = manager.deconstruct() if as_manager: qs_class = import_string(qs_path) diff --git a/django/db/migrations/writer.py b/django/db/migrations/writer.py index 3407dcfafdd..aa296db8c58 100644 --- a/django/db/migrations/writer.py +++ b/django/db/migrations/writer.py @@ -7,7 +7,6 @@ from django.apps import apps from django.db import migrations from django.db.migrations.loader import MigrationLoader from django.db.migrations.serializer import serializer_factory -from django.utils.encoding import force_text from django.utils.inspect import get_func_args from django.utils.module_loading import module_dir from django.utils.timezone import now @@ -161,8 +160,6 @@ class MigrationWriter: dependencies.append(" migrations.swappable_dependency(settings.%s)," % dependency[1]) imports.add("from django.conf import settings") else: - # No need to output bytestrings for dependencies - dependency = tuple(force_text(s) for s in dependency) dependencies.append(" %s," % self.serialize(dependency)[0]) items["dependencies"] = "\n".join(dependencies) + "\n" if dependencies else "" diff --git a/django/db/models/base.py b/django/db/models/base.py index efc8b1862f5..03375911d4e 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -885,7 +885,7 @@ class Model(metaclass=ModelBase): raise ValueError("get_next/get_previous cannot be used on unsaved objects.") op = 'gt' if is_next else 'lt' order = '' if is_next else '-' - param = force_text(getattr(self, field.attname)) + param = getattr(self, field.attname) q = Q(**{'%s__%s' % (field.name, op): param}) q = q | Q(**{field.name: param, 'pk__%s' % op: self.pk}) qs = self.__class__._default_manager.using(self._state.db).filter(**kwargs).filter(q).order_by( diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 8532959350b..79a983b8fa7 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -438,12 +438,7 @@ class Field(RegisterLookupMixin): if path.startswith("django.db.models.fields"): path = path.replace("django.db.models.fields", "django.db.models") # Return basic info - other fields should override this. - return ( - force_text(self.name, strings_only=True), - path, - [], - keywords, - ) + return (self.name, path, [], keywords) def clone(self): """ diff --git a/django/db/models/fields/files.py b/django/db/models/fields/files.py index bf0b1682c5f..92e710299f4 100644 --- a/django/db/models/fields/files.py +++ b/django/db/models/fields/files.py @@ -9,7 +9,6 @@ from django.core.files.storage import default_storage from django.core.validators import validate_image_file_extension from django.db.models import signals from django.db.models.fields import Field -from django.utils.encoding import force_text from django.utils.translation import gettext_lazy as _ @@ -302,7 +301,7 @@ class FileField(Field): if callable(self.upload_to): filename = self.upload_to(instance, filename) else: - dirname = force_text(datetime.datetime.now().strftime(self.upload_to)) + dirname = datetime.datetime.now().strftime(self.upload_to) filename = posixpath.join(dirname, filename) return self.storage.generate_filename(filename) diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index c2e6f6bffa3..684f88e8b6a 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -12,7 +12,6 @@ from django.db.models.constants import LOOKUP_SEP from django.db.models.deletion import CASCADE, SET_DEFAULT, SET_NULL from django.db.models.query_utils import PathInfo from django.db.models.utils import make_model_tuple -from django.utils.encoding import force_text from django.utils.functional import cached_property, curry from django.utils.translation import gettext_lazy as _ @@ -300,7 +299,7 @@ class RelatedField(Field): else: related_name = self.opts.default_related_name if related_name: - related_name = force_text(related_name) % { + related_name = related_name % { 'class': cls.__name__.lower(), 'model_name': cls._meta.model_name.lower(), 'app_label': cls._meta.app_label.lower() @@ -308,7 +307,7 @@ class RelatedField(Field): self.remote_field.related_name = related_name if self.remote_field.related_query_name: - related_query_name = force_text(self.remote_field.related_query_name) % { + related_query_name = self.remote_field.related_query_name % { 'class': cls.__name__.lower(), 'app_label': cls._meta.app_label.lower(), } diff --git a/django/forms/boundfield.py b/django/forms/boundfield.py index cb256fc76bd..9c0cd6e4273 100644 --- a/django/forms/boundfield.py +++ b/django/forms/boundfield.py @@ -108,13 +108,12 @@ class BoundField: 'It will be mandatory in Django 2.1.' % widget.__class__, RemovedInDjango21Warning, stacklevel=2, ) - html = widget.render( + return widget.render( name=name, value=self.value(), attrs=attrs, **kwargs ) - return force_text(html) def as_text(self, attrs=None, **kwargs): """ diff --git a/django/forms/forms.py b/django/forms/forms.py index 85f68e56eb2..caf4617c22d 100644 --- a/django/forms/forms.py +++ b/django/forms/forms.py @@ -225,14 +225,14 @@ class BaseForm: label = '' if field.help_text: - help_text = help_text_html % force_text(field.help_text) + help_text = help_text_html % field.help_text else: help_text = '' output.append(normal_row % { - 'errors': force_text(bf_errors), - 'label': force_text(label), - 'field': str(bf), + 'errors': bf_errors, + 'label': label, + 'field': bf, 'help_text': help_text, 'html_class_attr': html_class_attr, 'css_classes': css_classes, @@ -240,7 +240,7 @@ class BaseForm: }) if top_errors: - output.insert(0, error_row % force_text(top_errors)) + output.insert(0, error_row % top_errors) if hidden_fields: # Insert any hidden fields in the last row. str_hidden = ''.join(hidden_fields) diff --git a/django/forms/utils.py b/django/forms/utils.py index 8811c8efbb3..e3151c9390c 100644 --- a/django/forms/utils.py +++ b/django/forms/utils.py @@ -4,7 +4,6 @@ from collections import UserList from django.conf import settings from django.core.exceptions import ValidationError # backwards compatibility from django.utils import timezone -from django.utils.encoding import force_text from django.utils.html import escape, format_html, format_html_join, html_safe from django.utils.translation import gettext_lazy as _ @@ -60,7 +59,7 @@ class ErrorDict(dict): return '' return format_html( '
    {}
', - format_html_join('', '
  • {}{}
  • ', ((k, force_text(v)) for k, v in self.items())) + format_html_join('', '
  • {}{}
  • ', self.items()) ) def as_text(self): @@ -110,7 +109,7 @@ class ErrorList(UserList, list): return format_html( '
      {}
    ', self.error_class, - format_html_join('', '
  • {}
  • ', ((force_text(e),) for e in self)) + format_html_join('', '
  • {}
  • ', ((e,) for e in self)) ) def as_text(self): @@ -132,7 +131,7 @@ class ErrorList(UserList, list): error = self.data[i] if isinstance(error, ValidationError): return list(error)[0] - return force_text(error) + return error def __reduce_ex__(self, *args, **kwargs): # The `list` reduce function returns an iterator as the fourth element diff --git a/django/utils/functional.py b/django/utils/functional.py index 055e511912c..92be506f3b7 100644 --- a/django/utils/functional.py +++ b/django/utils/functional.py @@ -166,8 +166,7 @@ def lazystr(text): """ Shortcut for the common case of a lazy callable that returns str. """ - from django.utils.encoding import force_text # Avoid circular import - return lazy(force_text, str)(text) + return lazy(str, str)(text) def keep_lazy(*resultclasses): diff --git a/django/utils/text.py b/django/utils/text.py index 97cd42e7a26..0336b3fe795 100644 --- a/django/utils/text.py +++ b/django/utils/text.py @@ -38,8 +38,6 @@ def wrap(text, width): Don't wrap long words, thus the output text may have lines longer than ``width``. """ - text = force_text(text) - def _generator(): for line in text.splitlines(True): # True keeps trailing linebreaks max_width = min((line.endswith('\n') and width + 1 or width), width) @@ -71,7 +69,6 @@ class Truncator(SimpleLazyObject): truncate = pgettext( 'String to return when truncating text', '%(truncated_text)s...') - truncate = force_text(truncate) if '%(truncated_text)s' in truncate: return truncate % {'truncated_text': text} # The truncation text didn't contain the %(truncated_text)s string diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py index ef92359c04a..b747f3aed1e 100644 --- a/django/utils/translation/trans_real.py +++ b/django/utils/translation/trans_real.py @@ -14,7 +14,6 @@ from django.conf.locale import LANG_INFO from django.core.exceptions import AppRegistryNotReady from django.core.signals import setting_changed from django.dispatch import receiver -from django.utils.encoding import force_text from django.utils.safestring import SafeData, mark_safe from django.utils.translation import LANGUAGE_SESSION_KEY @@ -327,8 +326,7 @@ def pgettext(context, message): result = gettext(msg_with_ctxt) if CONTEXT_SEPARATOR in result: # Translation not found - # force str, because the lazy version expects str. - result = force_text(message) + result = message return result diff --git a/django/views/generic/dates.py b/django/views/generic/dates.py index bc276b75dbc..3081c76d454 100644 --- a/django/views/generic/dates.py +++ b/django/views/generic/dates.py @@ -5,7 +5,6 @@ from django.core.exceptions import ImproperlyConfigured from django.db import models from django.http import Http404 from django.utils import timezone -from django.utils.encoding import force_text from django.utils.functional import cached_property from django.utils.translation import gettext as _ from django.views.generic.base import View @@ -326,7 +325,7 @@ class BaseDateListView(MultipleObjectMixin, DateMixin, View): is_empty = len(qs) == 0 if paginate_by is None else not qs.exists() if is_empty: raise Http404(_("No %(verbose_name_plural)s available") % { - 'verbose_name_plural': force_text(qs.model._meta.verbose_name_plural) + 'verbose_name_plural': qs.model._meta.verbose_name_plural, }) return qs @@ -353,9 +352,11 @@ class BaseDateListView(MultipleObjectMixin, DateMixin, View): else: date_list = queryset.dates(date_field, date_type, ordering) if date_list is not None and not date_list and not allow_empty: - name = force_text(queryset.model._meta.verbose_name_plural) - raise Http404(_("No %(verbose_name_plural)s available") % - {'verbose_name_plural': name}) + raise Http404( + _("No %(verbose_name_plural)s available") % { + 'verbose_name_plural': queryset.model._meta.verbose_name_plural, + } + ) return date_list diff --git a/tests/mail/tests.py b/tests/mail/tests.py index 63737b34625..a9d98856504 100644 --- a/tests/mail/tests.py +++ b/tests/mail/tests.py @@ -635,8 +635,6 @@ class MailTests(HeadersCheckMixin, SimpleTestCase): # Simple ASCII address - string form self.assertEqual(sanitize_address('to@example.com', 'ascii'), 'to@example.com') self.assertEqual(sanitize_address('to@example.com', 'utf-8'), 'to@example.com') - # Bytestrings are transformed to normal strings. - self.assertEqual(sanitize_address(b'to@example.com', 'utf-8'), 'to@example.com') # Simple ASCII address - tuple form self.assertEqual( diff --git a/tests/migrations/test_state.py b/tests/migrations/test_state.py index badd45a5aae..fe9c4fd03ad 100644 --- a/tests/migrations/test_state.py +++ b/tests/migrations/test_state.py @@ -359,7 +359,7 @@ class StateTests(SimpleTestCase): # The ordering we really want is objects, mgr1, mgr2 ('default', base_mgr), ('food_mgr2', mgr2), - (b'food_mgr1', mgr1), + ('food_mgr1', mgr1), ] )) diff --git a/tests/model_fields/models.py b/tests/model_fields/models.py index 134d200be94..f6e94a841e7 100644 --- a/tests/model_fields/models.py +++ b/tests/model_fields/models.py @@ -30,7 +30,7 @@ def get_foo(): class Bar(models.Model): b = models.CharField(max_length=10) - a = models.ForeignKey(Foo, models.CASCADE, default=get_foo, related_name=b'bars') + a = models.ForeignKey(Foo, models.CASCADE, default=get_foo, related_name='bars') class Whiz(models.Model): diff --git a/tests/postgres_tests/test_hstore.py b/tests/postgres_tests/test_hstore.py index 2c6f93f1f64..09d2de10170 100644 --- a/tests/postgres_tests/test_hstore.py +++ b/tests/postgres_tests/test_hstore.py @@ -42,8 +42,8 @@ class SimpleTests(HStoreTestCase): self.assertEqual(reloaded.field, value) def test_key_val_cast_to_string(self): - value = {'a': 1, 'b': 'B', 2: 'c', 'ï': 'ê', b'x': b'test'} - expected_value = {'a': '1', 'b': 'B', '2': 'c', 'ï': 'ê', 'x': 'test'} + value = {'a': 1, 'b': 'B', 2: 'c', 'ï': 'ê'} + expected_value = {'a': '1', 'b': 'B', '2': 'c', 'ï': 'ê'} instance = HStoreModel.objects.create(field=value) instance = HStoreModel.objects.get() diff --git a/tests/string_lookup/tests.py b/tests/string_lookup/tests.py index 22b0c6b9cfa..a8e39dbb6c5 100644 --- a/tests/string_lookup/tests.py +++ b/tests/string_lookup/tests.py @@ -51,9 +51,6 @@ class StringLookupTests(TestCase): fx.save() self.assertEqual(Foo.objects.get(friend__contains='\xe7'), fx) - # We can also do the above query using UTF-8 strings. - self.assertEqual(Foo.objects.get(friend__contains=b'\xc3\xa7'), fx) - def test_queries_on_textfields(self): """ Regression tests for #5087 diff --git a/tests/utils_tests/test_text.py b/tests/utils_tests/test_text.py index 465db554da9..ed189cd2e9a 100644 --- a/tests/utils_tests/test_text.py +++ b/tests/utils_tests/test_text.py @@ -157,11 +157,6 @@ class TestUtilsText(SimpleTestCase): self.assertEqual(text.normalize_newlines(""), "") self.assertEqual(text.normalize_newlines(lazystr("abc\ndef\rghi\r\n")), "abc\ndef\nghi\n") - def test_normalize_newlines_bytes(self): - """normalize_newlines should be able to handle bytes too""" - normalized = text.normalize_newlines(b"abc\ndef\rghi\r\n") - self.assertEqual(normalized, "abc\ndef\nghi\n") - def test_phone2numeric(self): numeric = text.phone2numeric('0800 flowers') self.assertEqual(numeric, '0800 3569377')