Fixed #21714 -- Moved logging configuration to global setup()

Thanks Aymeric Augustin for the report and the review.
This commit is contained in:
Claude Paroz 2013-12-31 12:28:01 +01:00
parent 1d23d766ab
commit b8e3373f45
5 changed files with 36 additions and 41 deletions

View File

@ -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)

View File

@ -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):

View File

@ -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.

View File

@ -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

View File

@ -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)