From b8e3373f458aa363d59c61b58be390a5a1156467 Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Tue, 31 Dec 2013 12:28:01 +0100 Subject: [PATCH] Fixed #21714 -- Moved logging configuration to global setup() Thanks Aymeric Augustin for the report and the review. --- django/__init__.py | 9 +++++++-- django/conf/__init__.py | 27 --------------------------- django/utils/log.py | 21 +++++++++++++++++++++ docs/topics/logging.txt | 8 +++----- tests/logging_tests/tests.py | 12 +++++------- 5 files changed, 36 insertions(+), 41 deletions(-) diff --git a/django/__init__.py b/django/__init__.py index 69be8c9984..14c941601a 100644 --- a/django/__init__.py +++ b/django/__init__.py @@ -9,8 +9,13 @@ def get_version(*args, **kwargs): def setup(): - # Configure the settings (this happens as a side effect of accessing - # INSTALLED_APPS or any other setting) and populate the app registry. + """ + Configure the settings (this happens as a side effect of accessing the + first setting), configure logging and populate the app registry. + """ from django.apps import apps from django.conf import settings + from django.utils.log import configure_logging + + configure_logging(settings.LOGGING_CONFIG, settings.LOGGING) apps.populate(settings.INSTALLED_APPS) diff --git a/django/conf/__init__.py b/django/conf/__init__.py index 3449368cb0..e10d4b1afb 100644 --- a/django/conf/__init__.py +++ b/django/conf/__init__.py @@ -7,16 +7,12 @@ a list of all possible variables. """ import importlib -import logging import os -import sys import time # Needed for Windows -import warnings from django.conf import global_settings from django.core.exceptions import ImproperlyConfigured from django.utils.functional import LazyObject, empty -from django.utils.module_loading import import_by_path from django.utils import six ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE" @@ -44,34 +40,12 @@ class LazySettings(LazyObject): % (desc, ENVIRONMENT_VARIABLE)) self._wrapped = Settings(settings_module) - self._configure_logging() def __getattr__(self, name): if self._wrapped is empty: self._setup(name) return getattr(self._wrapped, name) - def _configure_logging(self): - """ - Setup logging from LOGGING_CONFIG and LOGGING settings. - """ - if not sys.warnoptions: - # Route warnings through python logging - logging.captureWarnings(True) - # Allow DeprecationWarnings through the warnings filters - warnings.simplefilter("default", DeprecationWarning) - - if self.LOGGING_CONFIG: - from django.utils.log import DEFAULT_LOGGING - # First find the logging configuration function ... - logging_config_func = import_by_path(self.LOGGING_CONFIG) - - logging_config_func(DEFAULT_LOGGING) - - # ... then invoke it with the logging settings - if self.LOGGING: - logging_config_func(self.LOGGING) - def configure(self, default_settings=global_settings, **options): """ Called to manually configure the settings. The 'default_settings' @@ -84,7 +58,6 @@ class LazySettings(LazyObject): for name, value in options.items(): setattr(holder, name, value) self._wrapped = holder - self._configure_logging() @property def configured(self): diff --git a/django/utils/log.py b/django/utils/log.py index 488632882c..cf778b619b 100644 --- a/django/utils/log.py +++ b/django/utils/log.py @@ -1,8 +1,11 @@ import logging +import sys +import warnings from django.conf import settings from django.core import mail from django.core.mail import get_connection +from django.utils.module_loading import import_by_path from django.views.debug import ExceptionReporter, get_exception_reporter_filter # Imports kept for backwards-compatibility in Django 1.7. @@ -61,6 +64,24 @@ DEFAULT_LOGGING = { } +def configure_logging(logging_config, logging_settings): + if not sys.warnoptions: + # Route warnings through python logging + logging.captureWarnings(True) + # Allow DeprecationWarnings through the warnings filters + warnings.simplefilter("default", DeprecationWarning) + + if logging_config: + # First find the logging configuration function ... + logging_config_func = import_by_path(logging_config) + + logging_config_func(DEFAULT_LOGGING) + + # ... then invoke it with the logging settings + if logging_settings: + logging_config_func(logging_settings) + + class AdminEmailHandler(logging.Handler): """An exception log handler that emails log entries to site admins. diff --git a/docs/topics/logging.txt b/docs/topics/logging.txt index d75875f2c8..03145fc41d 100644 --- a/docs/topics/logging.txt +++ b/docs/topics/logging.txt @@ -222,11 +222,9 @@ set to ``True`` (which is the default) the default configuration is completely overridden. Alternatively you can redefine some or all of the loggers by setting ``disable_existing_loggers`` to ``False``. -Logging is configured as soon as settings have been loaded -(either manually using :func:`~django.conf.settings.configure` or when at least -one setting is accessed). Since the loading of settings is one of the first -things that Django does, you can be certain that loggers are always ready for -use in your project code. +Logging is configured as part of the general Django ``setup()`` function. +Therefore, you can be certain that loggers are always ready for use in your +project code. .. _dictConfig format: http://docs.python.org/library/logging.config.html#configuration-dictionary-schema diff --git a/tests/logging_tests/tests.py b/tests/logging_tests/tests.py index a6791cfa76..f020bfddef 100644 --- a/tests/logging_tests/tests.py +++ b/tests/logging_tests/tests.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals import logging import warnings -from django.conf import LazySettings from django.core import mail from django.test import TestCase, RequestFactory, override_settings from django.test.utils import patch_logger @@ -342,15 +341,14 @@ def dictConfig(config): dictConfig.called = False -class SettingsConfigureLogging(TestCase): +class SetupConfigureLogging(TestCase): """ - Test that calling settings.configure() initializes the logging - configuration. + Test that calling django.setup() initializes the logging configuration. """ + @override_settings(LOGGING_CONFIG='logging_tests.tests.dictConfig') def test_configure_initializes_logging(self): - settings = LazySettings() - settings.configure( - LOGGING_CONFIG='logging_tests.tests.dictConfig') + from django import setup + setup() self.assertTrue(dictConfig.called)