mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	[1.11.x] Fixed #28487 -- Fixed runserver crash with non-Unicode system encodings on Python 2 + Windows.
This commit is contained in:
		| @@ -40,7 +40,7 @@ from django.conf import settings | |||||||
| from django.core.signals import request_finished | from django.core.signals import request_finished | ||||||
| from django.utils import six | from django.utils import six | ||||||
| from django.utils._os import npath | from django.utils._os import npath | ||||||
| from django.utils.encoding import force_bytes, get_system_encoding | from django.utils.encoding import get_system_encoding | ||||||
| from django.utils.six.moves import _thread as thread | from django.utils.six.moves import _thread as thread | ||||||
|  |  | ||||||
| # This import does nothing, but it's necessary to avoid some race conditions | # This import does nothing, but it's necessary to avoid some race conditions | ||||||
| @@ -290,8 +290,8 @@ def restart_with_reloader(): | |||||||
|             # Environment variables on Python 2 + Windows must be str. |             # Environment variables on Python 2 + Windows must be str. | ||||||
|             encoding = get_system_encoding() |             encoding = get_system_encoding() | ||||||
|             for key in new_environ.keys(): |             for key in new_environ.keys(): | ||||||
|                 str_key = force_bytes(key, encoding=encoding) |                 str_key = key.decode(encoding).encode('utf-8') | ||||||
|                 str_value = force_bytes(new_environ[key], encoding=encoding) |                 str_value = new_environ[key].decode(encoding).encode('utf-8') | ||||||
|                 del new_environ[key] |                 del new_environ[key] | ||||||
|                 new_environ[str_key] = str_value |                 new_environ[str_key] = str_value | ||||||
|         new_environ["RUN_MAIN"] = 'true' |         new_environ["RUN_MAIN"] = 'true' | ||||||
|   | |||||||
| @@ -32,3 +32,6 @@ Bugfixes | |||||||
|  |  | ||||||
| * Fixed a regression where ``SelectDateWidget`` localized the years in the | * Fixed a regression where ``SelectDateWidget`` localized the years in the | ||||||
|   select box (:ticket:`28530`). |   select box (:ticket:`28530`). | ||||||
|  |  | ||||||
|  | * Fixed a regression in 1.11.4 where ``runserver`` crashed with non-Unicode | ||||||
|  |   system encodings on Python 2 + Windows (:ticket:`28487`). | ||||||
|   | |||||||
| @@ -5,13 +5,14 @@ import os | |||||||
| import shutil | import shutil | ||||||
| import sys | import sys | ||||||
| import tempfile | import tempfile | ||||||
|  | import unittest | ||||||
| from importlib import import_module | from importlib import import_module | ||||||
|  |  | ||||||
| from django import conf | from django import conf | ||||||
| from django.contrib import admin | from django.contrib import admin | ||||||
| from django.test import SimpleTestCase, mock, override_settings | from django.test import SimpleTestCase, mock, override_settings | ||||||
| from django.test.utils import extend_sys_path | from django.test.utils import extend_sys_path | ||||||
| from django.utils import autoreload | from django.utils import autoreload, six | ||||||
| from django.utils._os import npath, upath | from django.utils._os import npath, upath | ||||||
| from django.utils.six.moves import _thread | from django.utils.six.moves import _thread | ||||||
| from django.utils.translation import trans_real | from django.utils.translation import trans_real | ||||||
| @@ -258,6 +259,13 @@ class ResetTranslationsTests(SimpleTestCase): | |||||||
|  |  | ||||||
| class TestRestartWithReloader(SimpleTestCase): | class TestRestartWithReloader(SimpleTestCase): | ||||||
|  |  | ||||||
|  |     def setUp(self): | ||||||
|  |         self._orig_environ = os.environ.copy() | ||||||
|  |  | ||||||
|  |     def tearDown(self): | ||||||
|  |         os.environ.clear() | ||||||
|  |         os.environ.update(self._orig_environ) | ||||||
|  |  | ||||||
|     def test_environment(self): |     def test_environment(self): | ||||||
|         """" |         """" | ||||||
|         With Python 2 on Windows, restart_with_reloader() coerces environment |         With Python 2 on Windows, restart_with_reloader() coerces environment | ||||||
| @@ -268,3 +276,24 @@ class TestRestartWithReloader(SimpleTestCase): | |||||||
|         os.environ['SPAM'] = 'spam' |         os.environ['SPAM'] = 'spam' | ||||||
|         with mock.patch.object(sys, 'argv', ['-c', 'pass']): |         with mock.patch.object(sys, 'argv', ['-c', 'pass']): | ||||||
|             autoreload.restart_with_reloader() |             autoreload.restart_with_reloader() | ||||||
|  |  | ||||||
|  |     @unittest.skipUnless(six.PY2 and sys.platform == 'win32', 'This is a Python 2 + Windows-specific issue.') | ||||||
|  |     def test_environment_decoding(self): | ||||||
|  |         """The system encoding is used for decoding.""" | ||||||
|  |         os.environ['SPAM'] = 'spam' | ||||||
|  |         os.environ['EGGS'] = b'\xc6u vi komprenas?' | ||||||
|  |         with mock.patch('locale.getdefaultlocale') as default_locale: | ||||||
|  |             # Latin-3 is the correct mapping. | ||||||
|  |             default_locale.return_value = ('eo', 'latin3') | ||||||
|  |             with mock.patch.object(sys, 'argv', ['-c', 'pass']): | ||||||
|  |                 autoreload.restart_with_reloader() | ||||||
|  |             # CP1252 interprets latin3's C circumflex as AE ligature. | ||||||
|  |             # It's incorrect but doesn't raise an error. | ||||||
|  |             default_locale.return_value = ('en_US', 'cp1252') | ||||||
|  |             with mock.patch.object(sys, 'argv', ['-c', 'pass']): | ||||||
|  |                 autoreload.restart_with_reloader() | ||||||
|  |             # Interpreting the string as UTF-8 is fatal. | ||||||
|  |             with self.assertRaises(UnicodeDecodeError): | ||||||
|  |                 default_locale.return_value = ('en_US', 'utf-8') | ||||||
|  |                 with mock.patch.object(sys, 'argv', ['-c', 'pass']): | ||||||
|  |                     autoreload.restart_with_reloader() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user