1
0
mirror of https://github.com/django/django.git synced 2024-12-22 17:16:24 +00:00

Fixed #36010 -- Avoided touching mo files while checking writability.

This commit is contained in:
Claude Paroz 2024-12-20 23:26:22 +01:00
parent fcd9d08379
commit 3b349fd134
2 changed files with 12 additions and 10 deletions

View File

@ -2,6 +2,7 @@ import codecs
import concurrent.futures import concurrent.futures
import glob import glob
import os import os
import tempfile
from pathlib import Path from pathlib import Path
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
@ -16,12 +17,10 @@ def has_bom(fn):
) )
def is_writable(path): def is_dir_writable(path):
# Known side effect: updating file access/modified time to current time if
# it is writable.
try: try:
with open(path, "a"): with tempfile.NamedTemporaryFile(dir=path):
os.utime(path, None) pass
except OSError: except OSError:
return False return False
return True return True
@ -172,7 +171,7 @@ class Command(BaseCommand):
continue continue
# Check writability on first location # Check writability on first location
if i == 0 and not is_writable(mo_path): if i == 0 and not is_dir_writable(mo_path.parent):
self.stderr.write( self.stderr.write(
"The po files under %s are in a seemingly not writable " "The po files under %s are in a seemingly not writable "
"location. mo files will not be updated/created." % dirpath "location. mo files will not be updated/created." % dirpath

View File

@ -43,9 +43,9 @@ class PoFileTests(MessageCompilationTests):
def test_no_write_access(self): def test_no_write_access(self):
mo_file_en = Path(self.MO_FILE_EN) mo_file_en = Path(self.MO_FILE_EN)
err_buffer = StringIO() err_buffer = StringIO()
# Put file in read-only mode. # Put parent directory in read-only mode.
old_mode = mo_file_en.stat().st_mode old_mode = mo_file_en.parent.stat().st_mode
mo_file_en.chmod(stat.S_IREAD) mo_file_en.parent.chmod(stat.S_IRUSR | stat.S_IXUSR)
# Ensure .po file is more recent than .mo file. # Ensure .po file is more recent than .mo file.
mo_file_en.with_suffix(".po").touch() mo_file_en.with_suffix(".po").touch()
try: try:
@ -57,7 +57,7 @@ class PoFileTests(MessageCompilationTests):
) )
self.assertIn("not writable location", err_buffer.getvalue()) self.assertIn("not writable location", err_buffer.getvalue())
finally: finally:
mo_file_en.chmod(old_mode) mo_file_en.parent.chmod(old_mode)
def test_no_compile_when_unneeded(self): def test_no_compile_when_unneeded(self):
mo_file_en = Path(self.MO_FILE_EN) mo_file_en = Path(self.MO_FILE_EN)
@ -258,6 +258,9 @@ class CompilationErrorHandling(MessageCompilationTests):
# po file contains wrong po formatting. # po file contains wrong po formatting.
with self.assertRaises(CommandError): with self.assertRaises(CommandError):
call_command("compilemessages", locale=["ja"], verbosity=0) call_command("compilemessages", locale=["ja"], verbosity=0)
# It should still fail a second time.
with self.assertRaises(CommandError):
call_command("compilemessages", locale=["ja"], verbosity=0)
def test_msgfmt_error_including_non_ascii(self): def test_msgfmt_error_including_non_ascii(self):
# po file contains invalid msgstr content (triggers non-ascii error content). # po file contains invalid msgstr content (triggers non-ascii error content).