Refs #29817 -- Removed settings.FILE_CHARSET per deprecation timeline.

This commit is contained in:
Mariusz Felisiak 2019-09-05 16:25:30 +02:00
parent b47bb4c4a7
commit 3d716467a9
10 changed files with 6 additions and 93 deletions

View File

@ -9,23 +9,14 @@ for a list of all possible variables.
import importlib import importlib
import os import os
import time import time
import traceback
import warnings
from pathlib import Path from pathlib import Path
import django
from django.conf import global_settings from django.conf import global_settings
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.utils.deprecation import RemovedInDjango31Warning
from django.utils.functional import LazyObject, empty from django.utils.functional import LazyObject, empty
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE" ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
FILE_CHARSET_DEPRECATED_MSG = (
'The FILE_CHARSET setting is deprecated. Starting with Django 3.1, all '
'files read from disk must be UTF-8 encoded.'
)
class SettingsReference(str): class SettingsReference(str):
""" """
@ -114,20 +105,6 @@ class LazySettings(LazyObject):
"""Return True if the settings have already been configured.""" """Return True if the settings have already been configured."""
return self._wrapped is not empty return self._wrapped is not empty
@property
def FILE_CHARSET(self):
stack = traceback.extract_stack()
# Show a warning if the setting is used outside of Django.
# Stack index: -1 this line, -2 the caller.
filename, _line_number, _function_name, _text = stack[-2]
if not filename.startswith(os.path.dirname(django.__file__)):
warnings.warn(
FILE_CHARSET_DEPRECATED_MSG,
RemovedInDjango31Warning,
stacklevel=2,
)
return self.__getattr__('FILE_CHARSET')
class Settings: class Settings:
def __init__(self, settings_module): def __init__(self, settings_module):
@ -160,9 +137,6 @@ class Settings:
if not self.SECRET_KEY: if not self.SECRET_KEY:
raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.") raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.")
if self.is_overridden('FILE_CHARSET'):
warnings.warn(FILE_CHARSET_DEPRECATED_MSG, RemovedInDjango31Warning)
if hasattr(time, 'tzset') and self.TIME_ZONE: if hasattr(time, 'tzset') and self.TIME_ZONE:
# When we can, attempt to validate the timezone. If we can't find # When we can, attempt to validate the timezone. If we can't find
# this file, no check happens and it's harmless. # this file, no check happens and it's harmless.
@ -206,8 +180,6 @@ class UserSettingsHolder:
def __setattr__(self, name, value): def __setattr__(self, name, value):
self._deleted.discard(name) self._deleted.discard(name)
if name == 'FILE_CHARSET':
warnings.warn(FILE_CHARSET_DEPRECATED_MSG, RemovedInDjango31Warning)
super().__setattr__(name, value) super().__setattr__(name, value)
def __delattr__(self, name): def __delattr__(self, name):

View File

@ -171,9 +171,6 @@ MANAGERS = ADMINS
# manually specified. It's used to construct the Content-Type header. # manually specified. It's used to construct the Content-Type header.
DEFAULT_CHARSET = 'utf-8' DEFAULT_CHARSET = 'utf-8'
# Encoding of files read from disk (template and initial SQL files).
FILE_CHARSET = 'utf-8'
# Email address that error messages come from. # Email address that error messages come from.
SERVER_EMAIL = 'root@localhost' SERVER_EMAIL = 'root@localhost'

View File

@ -285,7 +285,7 @@ class HashedFilesMixin:
# ..to apply each replacement pattern to the content # ..to apply each replacement pattern to the content
if name in adjustable_paths: if name in adjustable_paths:
old_hashed_name = hashed_name old_hashed_name = hashed_name
content = original_file.read().decode(settings.FILE_CHARSET) content = original_file.read().decode('utf-8')
for extension, patterns in self._patterns.items(): for extension, patterns in self._patterns.items():
if matches_patterns(path, (extension,)): if matches_patterns(path, (extension,)):
for pattern, template in patterns: for pattern, template in patterns:

View File

@ -102,8 +102,7 @@ class BuildFile:
if not self.is_templatized: if not self.is_templatized:
return return
encoding = settings.FILE_CHARSET if self.command.settings_available else 'utf-8' with open(self.path, encoding='utf-8') as fp:
with open(self.path, encoding=encoding) as fp:
src_data = fp.read() src_data = fp.read()
if self.domain == 'djangojs': if self.domain == 'djangojs':

View File

@ -20,7 +20,7 @@ class DjangoTemplates(BaseEngine):
options = params.pop('OPTIONS').copy() options = params.pop('OPTIONS').copy()
options.setdefault('autoescape', True) options.setdefault('autoescape', True)
options.setdefault('debug', settings.DEBUG) options.setdefault('debug', settings.DEBUG)
options.setdefault('file_charset', settings.FILE_CHARSET) options.setdefault('file_charset', 'utf-8')
libraries = options.get('libraries', {}) libraries = options.get('libraries', {})
options['libraries'] = self.get_templatetag_libraries(libraries) options['libraries'] = self.get_templatetag_libraries(libraries)
super().__init__(params) super().__init__(params)

View File

@ -1,6 +1,5 @@
import string import string
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.template import Origin, TemplateDoesNotExist from django.template import Origin, TemplateDoesNotExist
from django.utils.html import conditional_escape from django.utils.html import conditional_escape
@ -28,7 +27,7 @@ class TemplateStrings(BaseEngine):
tried = [] tried = []
for template_file in self.iter_template_filenames(template_name): for template_file in self.iter_template_filenames(template_name):
try: try:
with open(template_file, encoding=settings.FILE_CHARSET) as fp: with open(template_file, encoding='utf-8') as fp:
template_code = fp.read() template_code = fp.read()
except FileNotFoundError: except FileNotFoundError:
tried.append(( tried.append((

View File

@ -86,7 +86,6 @@ def reset_template_engines(**kwargs):
if kwargs['setting'] in { if kwargs['setting'] in {
'TEMPLATES', 'TEMPLATES',
'DEBUG', 'DEBUG',
'FILE_CHARSET',
'INSTALLED_APPS', 'INSTALLED_APPS',
}: }:
from django.template import engines from django.template import engines

View File

@ -1414,21 +1414,6 @@ Default: ``None``
Specifies a timeout in seconds for blocking operations like the connection Specifies a timeout in seconds for blocking operations like the connection
attempt. attempt.
.. setting:: FILE_CHARSET
``FILE_CHARSET``
----------------
Default: ``'utf-8'``
The character encoding used to decode any files read from disk. This includes
template files, static files, and translation catalogs.
.. deprecated:: 2.2
This setting is deprecated. Starting with Django 3.1, files read from disk
must be UTF-8 encoded.
.. setting:: FILE_UPLOAD_HANDLERS .. setting:: FILE_UPLOAD_HANDLERS
``FILE_UPLOAD_HANDLERS`` ``FILE_UPLOAD_HANDLERS``

View File

@ -232,3 +232,5 @@ to remove usage of these features.
* ``django.contrib.postgres.fields.FloatRangeField`` and * ``django.contrib.postgres.fields.FloatRangeField`` and
``django.contrib.postgres.forms.FloatRangeField`` are removed. ``django.contrib.postgres.forms.FloatRangeField`` are removed.
* The ``FILE_CHARSET`` setting is removed.

View File

@ -1,40 +0,0 @@
import sys
from types import ModuleType
from django.conf import FILE_CHARSET_DEPRECATED_MSG, Settings, settings
from django.test import SimpleTestCase, ignore_warnings
from django.utils.deprecation import RemovedInDjango31Warning
class DeprecationTests(SimpleTestCase):
msg = FILE_CHARSET_DEPRECATED_MSG
def test_override_settings_warning(self):
with self.assertRaisesMessage(RemovedInDjango31Warning, self.msg):
with self.settings(FILE_CHARSET='latin1'):
pass
def test_settings_init_warning(self):
settings_module = ModuleType('fake_settings_module')
settings_module.FILE_CHARSET = 'latin1'
settings_module.SECRET_KEY = 'ABC'
sys.modules['fake_settings_module'] = settings_module
try:
with self.assertRaisesMessage(RemovedInDjango31Warning, self.msg):
Settings('fake_settings_module')
finally:
del sys.modules['fake_settings_module']
def test_access_warning(self):
with self.assertRaisesMessage(RemovedInDjango31Warning, self.msg):
settings.FILE_CHARSET
# Works a second time.
with self.assertRaisesMessage(RemovedInDjango31Warning, self.msg):
settings.FILE_CHARSET
@ignore_warnings(category=RemovedInDjango31Warning)
def test_access(self):
with self.settings(FILE_CHARSET='latin1'):
self.assertEqual(settings.FILE_CHARSET, 'latin1')
# Works a second time.
self.assertEqual(settings.FILE_CHARSET, 'latin1')