Skip to content

Commit

Permalink
Allow ConfigParser or a io.IO[Any] on log_config (#1976)
Browse files Browse the repository at this point in the history
* Enabled to pass log_config as ConfigParser instance or a file object

* Rebase correctly

---------

Co-authored-by: Marcelo Trylesinski <marcelotryle@gmail.com>
  • Loading branch information
antonymayi and Kludex authored Apr 13, 2024
1 parent 35fedee commit 12c9ee3
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 9 deletions.
12 changes: 9 additions & 3 deletions tests/test_config.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import annotations

import configparser
import io
import json
import logging
import os
Expand Down Expand Up @@ -369,14 +371,18 @@ def test_log_config_yaml(
mocked_logging_config_module.dictConfig.assert_called_once_with(logging_config)


def test_log_config_file(mocked_logging_config_module: MagicMock) -> None:
@pytest.mark.parametrize("config_file", ["log_config.ini", configparser.ConfigParser(), io.StringIO()])
def test_log_config_file(
mocked_logging_config_module: MagicMock,
config_file: str | configparser.RawConfigParser | typing.IO[Any],
) -> None:
"""
Test that one can load a configparser config from disk.
"""
config = Config(app=asgi_app, log_config="log_config")
config = Config(app=asgi_app, log_config=config_file)
config.load()

mocked_logging_config_module.fileConfig.assert_called_once_with("log_config", disable_existing_loggers=False)
mocked_logging_config_module.fileConfig.assert_called_once_with(config_file, disable_existing_loggers=False)


@pytest.fixture(params=[0, 1])
Expand Down
9 changes: 5 additions & 4 deletions uvicorn/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
import socket
import ssl
import sys
from configparser import RawConfigParser
from pathlib import Path
from typing import Any, Awaitable, Callable, Literal
from typing import IO, Any, Awaitable, Callable, Literal

import click

Expand Down Expand Up @@ -189,7 +190,7 @@ def __init__(
ws_per_message_deflate: bool = True,
lifespan: LifespanType = "auto",
env_file: str | os.PathLike[str] | None = None,
log_config: dict[str, Any] | str | None = LOGGING_CONFIG,
log_config: dict[str, Any] | str | RawConfigParser | IO[Any] | None = LOGGING_CONFIG,
log_level: str | int | None = None,
access_log: bool = True,
use_colors: bool | None = None,
Expand Down Expand Up @@ -362,11 +363,11 @@ def configure_logging(self) -> None:
self.log_config["formatters"]["default"]["use_colors"] = self.use_colors
self.log_config["formatters"]["access"]["use_colors"] = self.use_colors
logging.config.dictConfig(self.log_config)
elif self.log_config.endswith(".json"):
elif isinstance(self.log_config, str) and self.log_config.endswith(".json"):
with open(self.log_config) as file:
loaded_config = json.load(file)
logging.config.dictConfig(loaded_config)
elif self.log_config.endswith((".yaml", ".yml")):
elif isinstance(self.log_config, str) and self.log_config.endswith((".yaml", ".yml")):
# Install the PyYAML package or the uvicorn[standard] optional
# dependencies to enable this functionality.
import yaml
Expand Down
5 changes: 3 additions & 2 deletions uvicorn/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
import platform
import ssl
import sys
from typing import Any, Callable
from configparser import RawConfigParser
from typing import IO, Any, Callable

import click

Expand Down Expand Up @@ -481,7 +482,7 @@ def run(
reload_delay: float = 0.25,
workers: int | None = None,
env_file: str | os.PathLike[str] | None = None,
log_config: dict[str, Any] | str | None = LOGGING_CONFIG,
log_config: dict[str, Any] | str | RawConfigParser | IO[Any] | None = LOGGING_CONFIG,
log_level: str | int | None = None,
access_log: bool = True,
proxy_headers: bool = True,
Expand Down

0 comments on commit 12c9ee3

Please sign in to comment.