Coverage for pycommons / io / console.py: 100%
8 statements
« prev ^ index » next coverage.py v7.13.2, created at 2026-02-02 06:36 +0000
« prev ^ index » next coverage.py v7.13.2, created at 2026-02-02 06:36 +0000
1"""The `logger` routine for writing a log string to stdout."""
2import datetime
3from typing import Callable, Final
5from pycommons.processes.caller import is_doc_test
7#: the "now" function
8__DTN: Final[Callable[[], datetime.datetime]] = datetime.datetime.now
11def logger(message: str, note: str = "",
12 do_print: bool = not is_doc_test()) -> None:
13 """
14 Write a message to the console log.
16 The line starts with the current date and time, includes the note, and
17 then the message string after an ": ".
18 This function can use a `lock` context to prevent multiple processes or
19 threads to write to the console at the same time.
21 :param message: the message
22 :param note: a note to put between the time and the message
23 :param do_print: really print the output, by default `False` if this
24 method is called from a "doctest", `True` otherwise
26 >>> from io import StringIO
27 >>> from contextlib import redirect_stdout
28 >>> sio = StringIO()
29 >>> dt1 = datetime.datetime.now()
30 >>> with redirect_stdout(sio):
31 ... logger("hello world!", do_print=True)
32 >>> line = sio.getvalue().strip()
33 >>> print(line[line.index(" ", line.index(" ") + 1) + 1:])
34 hello world!
35 >>> dt2 = datetime.datetime.now()
36 >>> dtx = datetime.datetime.strptime(line[:26], "%Y-%m-%d %H:%M:%S.%f")
37 >>> dt1 <= dtx <= dt2
38 True
40 >>> sio = StringIO()
41 >>> with redirect_stdout(sio):
42 ... logger("hello world!", "note", do_print=True)
43 >>> line = sio.getvalue().strip()
44 >>> print(line[line.index("n"):])
45 note: hello world!
47 >>> logger("hello world") # not printed in doctests
48 >>> logger("hello world", do_print=False) # not printed anyway
49 """
50 if do_print:
51 text: Final[str] = f"{__DTN()}{note}: {message}"
52 print(text, flush=True) # noqa