From c3936c0d79d79aced25ceba8beff0c91a6b5c2ed Mon Sep 17 00:00:00 2001 From: Bouke Haarsma Date: Sat, 2 Nov 2013 10:28:22 +0100 Subject: [PATCH] Fixed #9523 -- Restart runserver after translation MO files change Thanks to Krzysztof Kulewski for the initial patch. --- AUTHORS | 1 + django/utils/autoreload.py | 21 ++++++++-- docs/ref/django-admin.txt | 8 +++- docs/releases/1.7.txt | 3 ++ .../locale/nl/LC_MESSAGES/django.mo | Bin 0 -> 367 bytes .../locale/nl/LC_MESSAGES/django.po | 17 ++++++++ tests/utils_tests/test_autoreload.py | 37 ++++++++++++++++++ 7 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 tests/utils_tests/locale/nl/LC_MESSAGES/django.mo create mode 100644 tests/utils_tests/locale/nl/LC_MESSAGES/django.po create mode 100644 tests/utils_tests/test_autoreload.py diff --git a/AUTHORS b/AUTHORS index 6e208cd369..5ad1569e27 100644 --- a/AUTHORS +++ b/AUTHORS @@ -369,6 +369,7 @@ answer newbie questions, and generally made Django that much better: knox David Krauth Kevin Kubasik + Krzysztof Kulewski kurtiss@meetro.com Vladimir Kuzma Denis Kuzmichyov diff --git a/django/utils/autoreload.py b/django/utils/autoreload.py index 75d794e80d..66ffd0db4d 100644 --- a/django/utils/autoreload.py +++ b/django/utils/autoreload.py @@ -28,13 +28,13 @@ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import datetime import os import signal import sys import time import traceback +from django.conf import settings from django.core.signals import request_finished try: from django.utils.six.moves import _thread as thread @@ -86,13 +86,28 @@ _win = (sys.platform == "win32") _error_files = [] - def gen_filenames(): """ - Yields a generator over filenames referenced in sys.modules. + Yields a generator over filenames referenced in sys.modules and translation + files. """ filenames = [filename.__file__ for filename in sys.modules.values() if hasattr(filename, '__file__')] + + # Add the names of the .mo files that can be generated + # by compilemessages management command to the list of files watched. + basedirs = [os.path.join(os.path.dirname(os.path.dirname(__file__)), + 'conf', 'locale'), + 'locale'] + basedirs.extend(settings.LOCALE_PATHS) + basedirs = [os.path.abspath(basedir) for basedir in basedirs + if os.path.isdir(basedir)] + for basedir in basedirs: + for dirpath, dirnames, locale_filenames in os.walk(basedir): + for filename in locale_filenames: + if filename.endswith('.mo'): + filenames.append(os.path.join(dirpath, filename)) + for filename in filenames + _error_files: if not filename: continue diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt index 6bb03347c9..c301c5f094 100644 --- a/docs/ref/django-admin.txt +++ b/docs/ref/django-admin.txt @@ -791,8 +791,12 @@ Django.) The development server automatically reloads Python code for each request, as needed. You don't need to restart the server for code changes to take effect. -However, some actions like adding files or compiling translation files don't -trigger a restart, so you'll have to restart the server in these cases. +However, some actions like adding files don't trigger a restart, so you'll +have to restart the server in these cases. + +.. versionchanged:: 1.7 + + Compiling translation files now also restarts the development server. If you are using Linux and install `pyinotify`_, kernel signals will be used to autoreload the server (rather than polling file modification timestamps each diff --git a/docs/releases/1.7.txt b/docs/releases/1.7.txt index 9a7ff41cf7..7218bcec22 100644 --- a/docs/releases/1.7.txt +++ b/docs/releases/1.7.txt @@ -346,6 +346,9 @@ Management Commands * The :djadmin:`runserver` command now uses ``inotify`` Linux kernel signals for autoreloading if ``pyinotify`` is installed. +* The :djadmin:`runserver` command is now restarted when a translation file is + changed. + Models ^^^^^^ diff --git a/tests/utils_tests/locale/nl/LC_MESSAGES/django.mo b/tests/utils_tests/locale/nl/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..3ead8f2a31f4d9ae95232417fb5fe2d929134705 GIT binary patch literal 367 zcmYL^K~KUk7=|%=+R?Lz9=z#?ExHI533C*(*Z~=Xdxbh{uq9nF_(S}A{uaMo;7y)1 zX`g<5`*(Tq+rpe7SI9MTj@%+mx=4(NJzN{-n7MbKdL1C!z)JhtILpaANnewRAS+QU zve`5$^v?MJd0m+eyzHwQO2jCez8Xsoa-xxHWC(t3i}!xj21_wP}<(8??nYes)+k=tH>MZI!W4Wc{Iht;6%O Z97FfyHC^7d2VvK4V{FAq_sxW;^$*^IVHW@Z literal 0 HcmV?d00001 diff --git a/tests/utils_tests/locale/nl/LC_MESSAGES/django.po b/tests/utils_tests/locale/nl/LC_MESSAGES/django.po new file mode 100644 index 0000000000..6633f12b39 --- /dev/null +++ b/tests/utils_tests/locale/nl/LC_MESSAGES/django.po @@ -0,0 +1,17 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-09-15 19:15+0200\n" +"PO-Revision-Date: 2010-05-12 12:41-0300\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" diff --git a/tests/utils_tests/test_autoreload.py b/tests/utils_tests/test_autoreload.py new file mode 100644 index 0000000000..3843ecafb4 --- /dev/null +++ b/tests/utils_tests/test_autoreload.py @@ -0,0 +1,37 @@ +import os + +from django import conf +from django.test import TestCase, override_settings +from django.utils.autoreload import gen_filenames + +LOCALE_PATH = os.path.join(os.path.dirname(__file__), 'locale') + + +class TestFilenameGenerator(TestCase): + def test_django_locales(self): + """ + Test that gen_filenames() also yields the built-in django locale files. + """ + filenames = list(gen_filenames()) + locales = [] + + basedir = os.path.join(os.path.dirname(conf.__file__), 'locale') + for dirpath, dirnames, locale_filenames in os.walk(basedir): + for filename in locale_filenames: + if filename.endswith('.mo'): + locales.append(os.path.join(dirpath, filename)) + + self.assertTrue(len(locales) > 10) # assume a few available locales + for filename in locales: + self.assertIn(filename, filenames) + + @override_settings( + LOCALE_PATHS=(LOCALE_PATH,) + ) + def test_app_locales(self): + """ + Test that gen_filenames also yields from LOCALE_PATHS. + """ + filenames = list(gen_filenames()) + self.assertIn(os.path.join(LOCALE_PATH, 'nl', 'LC_MESSAGES', 'django.mo'), + filenames)