Explorar el Código

Refs #27795 -- Removed unneeded force_text calls

Thanks Tim Graham for the review.
Claude Paroz hace 8 años
padre
commit
8346680e1c
Se han modificado 42 ficheros con 75 adiciones y 132 borrados
  1. 1 2
      django/__init__.py
  2. 3 6
      django/contrib/admin/helpers.py
  3. 7 8
      django/contrib/admin/options.py
  4. 2 2
      django/contrib/admin/templatetags/admin_list.py
  5. 5 6
      django/contrib/admin/utils.py
  6. 1 2
      django/contrib/admin/views/main.py
  7. 1 2
      django/contrib/auth/admin.py
  8. 1 2
      django/contrib/auth/base_user.py
  9. 2 3
      django/contrib/auth/views.py
  10. 2 3
      django/contrib/staticfiles/management/commands/collectstatic.py
  11. 2 4
      django/contrib/staticfiles/management/commands/findstatic.py
  12. 3 3
      django/contrib/staticfiles/storage.py
  13. 1 2
      django/core/files/base.py
  14. 2 2
      django/core/files/storage.py
  15. 2 2
      django/core/handlers/wsgi.py
  16. 1 2
      django/core/management/commands/createcachetable.py
  17. 1 2
      django/core/management/commands/inspectdb.py
  18. 1 2
      django/core/management/commands/loaddata.py
  19. 1 2
      django/core/management/commands/runserver.py
  20. 0 3
      django/core/validators.py
  21. 1 2
      django/db/backends/mysql/introspection.py
  22. 2 6
      django/db/backends/postgresql/introspection.py
  23. 1 2
      django/db/backends/sqlite3/creation.py
  24. 6 9
      django/db/migrations/state.py
  25. 0 3
      django/db/migrations/writer.py
  26. 1 1
      django/db/models/base.py
  27. 1 6
      django/db/models/fields/__init__.py
  28. 1 2
      django/db/models/fields/files.py
  29. 2 3
      django/db/models/fields/related.py
  30. 1 2
      django/forms/boundfield.py
  31. 5 5
      django/forms/forms.py
  32. 3 4
      django/forms/utils.py
  33. 1 2
      django/utils/functional.py
  34. 0 3
      django/utils/text.py
  35. 1 3
      django/utils/translation/trans_real.py
  36. 6 5
      django/views/generic/dates.py
  37. 0 2
      tests/mail/tests.py
  38. 1 1
      tests/migrations/test_state.py
  39. 1 1
      tests/model_fields/models.py
  40. 2 2
      tests/postgres_tests/test_hstore.py
  41. 0 3
      tests/string_lookup/tests.py
  42. 0 5
      tests/utils_tests/test_text.py

+ 1 - 2
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)

+ 3 - 6
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('<label{}>{}:</label>',
-                           flatatt(attrs),
-                           capfirst(force_text(label)))
+        return format_html('<label{}>{}:</label>', 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()))

+ 7 - 8
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('<a href="{}">{}</a>', 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,

+ 2 - 2
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('<td{}>{}</td>', row_class, result_repr)
     if form and not form[cl.model._meta.pk.name].is_hidden:
-        yield format_html('<td>{}</td>', force_text(form[cl.model._meta.pk.name]))
+        yield format_html('<td>{}</td>', 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")

+ 5 - 6
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):

+ 1 - 2
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):

+ 1 - 2
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':

+ 1 - 2
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

+ 2 - 3
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

+ 2 - 3
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:

+ 2 - 4
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" %

+ 3 - 3
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

+ 1 - 2
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")

+ 2 - 2
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."

+ 2 - 2
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

+ 1 - 2
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)
 

+ 1 - 2
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 ''

+ 1 - 2
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:

+ 1 - 2
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)

+ 0 - 3
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)
 

+ 1 - 2
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,) +

+ 2 - 6
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):

+ 1 - 2
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']

+ 6 - 9
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)

+ 0 - 3
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 ""
 

+ 1 - 1
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(

+ 1 - 6
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):
         """

+ 1 - 2
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)
 

+ 2 - 3
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(),
                 }

+ 1 - 2
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):
         """

+ 5 - 5
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)

+ 3 - 4
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(
             '<ul class="errorlist">{}</ul>',
-            format_html_join('', '<li>{}{}</li>', ((k, force_text(v)) for k, v in self.items()))
+            format_html_join('', '<li>{}{}</li>', self.items())
         )
 
     def as_text(self):
@@ -110,7 +109,7 @@ class ErrorList(UserList, list):
         return format_html(
             '<ul class="{}">{}</ul>',
             self.error_class,
-            format_html_join('', '<li>{}</li>', ((force_text(e),) for e in self))
+            format_html_join('', '<li>{}</li>', ((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

+ 1 - 2
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):

+ 0 - 3
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

+ 1 - 3
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
 
 

+ 6 - 5
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
 

+ 0 - 2
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(

+ 1 - 1
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),
             ]
         ))
 

+ 1 - 1
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):

+ 2 - 2
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()

+ 0 - 3
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

+ 0 - 5
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')