Skip to content

Commit d4a1c39

Browse files
Make filename, stream, and handlers parameters of logging.basicConfig mutually-exclusive (#15435)
1 parent 2b2a93d commit d4a1c39

File tree

2 files changed

+48
-3
lines changed

2 files changed

+48
-3
lines changed

stdlib/@tests/test_cases/check_logging.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,27 @@ def record_factory(*args: Any, **kwargs: Any) -> logging.LogRecord:
2828
logging.handlers.QueueListener(queue.Queue())
2929
logging.handlers.QueueListener(queue.SimpleQueue())
3030
logging.handlers.QueueListener(multiprocessing.Queue())
31+
32+
# These all raise at runtime.
33+
logging.basicConfig(filename="foo.log", handlers=[]) # type: ignore
34+
logging.basicConfig(filemode="w", handlers=[]) # type: ignore
35+
logging.basicConfig(stream=None, handlers=[]) # type: ignore
36+
logging.basicConfig(filename="foo.log", stream=None) # type: ignore
37+
logging.basicConfig(filename=None, stream=None) # type: ignore
38+
# These are ok.
39+
logging.basicConfig()
40+
logging.basicConfig(handlers=[])
41+
logging.basicConfig(filename="foo.log", filemode="w")
42+
logging.basicConfig(filename="foo.log", filemode="w", handlers=None)
43+
logging.basicConfig(stream=None)
44+
logging.basicConfig(stream=None, handlers=None)
45+
# dubious but accepted, has same meaning as 'stream=None'.
46+
logging.basicConfig(filename=None)
47+
# These are technically accepted at runtime, but are forbidden in the stubs to help
48+
# prevent user mistakes. Passing 'filemode' / 'encoding' / 'errors' does nothing
49+
# if 'filename' is not specified.
50+
logging.basicConfig(stream=None, filemode="w") # type: ignore
51+
logging.basicConfig(stream=None, encoding="utf-8") # type: ignore
52+
logging.basicConfig(stream=None, errors="strict") # type: ignore
53+
logging.basicConfig(handlers=[], encoding="utf-8") # type: ignore
54+
logging.basicConfig(handlers=[], errors="strict") # type: ignore

stdlib/logging/__init__.pyi

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -576,20 +576,41 @@ if sys.version_info >= (3, 11):
576576
def getLevelNamesMapping() -> dict[str, int]: ...
577577

578578
def makeLogRecord(dict: Mapping[str, object]) -> LogRecord: ...
579+
@overload # handlers is non-None
579580
def basicConfig(
580581
*,
581-
filename: StrPath | None = None,
582+
format: str = ..., # default value depends on the value of `style`
583+
datefmt: str | None = None,
584+
style: _FormatStyle = "%",
585+
level: _Level | None = None,
586+
handlers: Iterable[Handler],
587+
force: bool | None = False,
588+
) -> None: ...
589+
@overload # handlers is None, filename is passed (but possibly None)
590+
def basicConfig(
591+
*,
592+
filename: StrPath | None,
582593
filemode: str = "a",
583594
format: str = ..., # default value depends on the value of `style`
584595
datefmt: str | None = None,
585596
style: _FormatStyle = "%",
586597
level: _Level | None = None,
587-
stream: SupportsWrite[str] | None = None,
588-
handlers: Iterable[Handler] | None = None,
598+
handlers: None = None,
589599
force: bool | None = False,
590600
encoding: str | None = None,
591601
errors: str | None = "backslashreplace",
592602
) -> None: ...
603+
@overload # handlers is None, filename is not passed
604+
def basicConfig(
605+
*,
606+
format: str = ..., # default value depends on the value of `style`
607+
datefmt: str | None = None,
608+
style: _FormatStyle = "%",
609+
level: _Level | None = None,
610+
stream: SupportsWrite[str] | None = None,
611+
handlers: None = None,
612+
force: bool | None = False,
613+
) -> None: ...
593614
def shutdown(handlerList: Sequence[Any] = ...) -> None: ... # handlerList is undocumented
594615
def setLoggerClass(klass: type[Logger]) -> None: ...
595616
def captureWarnings(capture: bool) -> None: ...

0 commit comments

Comments
 (0)