Skip to content

Commit

Permalink
Add detection of invalid time format when too many "S" (#855)
Browse files Browse the repository at this point in the history
  • Loading branch information
Delgan committed Apr 28, 2023
1 parent b71a937 commit 28749e7
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Expand Up @@ -2,6 +2,7 @@
=============

- Add a new ``context`` optional argument to ``logger.add()`` specifying ``multiprocessing`` context (like ``"spawn"`` or ``"fork"``) to be used internally instead of the default one (`#851 <https://github.com/Delgan/loguru/issues/851>`_).
- Raise ``ValueError`` if an attempt to use nanosecond precision for time formatting is detected (`#855 <https://github.com/Delgan/loguru/issues/855>`_).


`0.7.0`_ (2023-04-10)
Expand Down
11 changes: 9 additions & 2 deletions loguru/_datetime.py
Expand Up @@ -4,9 +4,9 @@
from datetime import timedelta, timezone
from time import localtime, strftime

tokens = r"H{1,2}|h{1,2}|m{1,2}|s{1,2}|S{1,6}|YYYY|YY|M{1,4}|D{1,4}|Z{1,2}|zz|A|X|x|E|Q|dddd|ddd|d"
tokens = r"H{1,2}|h{1,2}|m{1,2}|s{1,2}|S+|YYYY|YY|M{1,4}|D{1,4}|Z{1,2}|zz|A|X|x|E|Q|dddd|ddd|d"

pattern = re.compile(r"(?:{0})|\[(?:{0}|!UTC)\]".format(tokens))
pattern = re.compile(r"(?:{0})|\[(?:{0}|!UTC|)\]".format(tokens))


class datetime(datetime_): # noqa: N801
Expand All @@ -23,6 +23,13 @@ def __format__(self, spec):
if "%" in spec:
return datetime_.__format__(dt, spec)

if "SSSSSSS" in spec:
raise ValueError(
"Invalid time format: the provided format string contains more than six successive "
"'S' characters. This may be due to an attempt to use nanosecond precision, which "
" not supported."
)

year, month, day, hour, minute, second, weekday, yearday, _ = dt.timetuple()
microsecond = dt.microsecond
timestamp = dt.timestamp()
Expand Down
13 changes: 12 additions & 1 deletion tests/test_datetime.py
Expand Up @@ -82,7 +82,9 @@
("[YYYY] MM [DD]", "2018-02-03 11:09:00.000002", ("UTC", 0), "YYYY 02 DD"),
("[YYYY MM DD]", "2018-01-03 11:03:04.000002", ("UTC", 0), "[2018 01 03]"),
("[[YY]]", "2018-01-03 11:03:04.000002", ("UTC", 0), "[YY]"),
("[]", "2018-01-03 11:03:04.000002", ("UTC", 0), "[]"),
("[]", "2018-01-03 11:03:04.000002", ("UTC", 0), ""),
("[[]]", "2018-01-03 11:03:04.000002", ("UTC", 0), "[]"),
("SSSSSS[]SSS[]SSSSSS", "2018-01-03 11:03:04.100002", ("UTC", 0), "100002100100002"),
("[HHmmss", "2018-01-03 11:03:04.000002", ("UTC", 0), "[110304"),
("HHmmss]", "2018-01-03 11:03:04.000002", ("UTC", 0), "110304]"),
("HH:mm:ss!UTC", "2018-01-01 11:30:00.0", ("A", 7200), "09:30:00"),
Expand Down Expand Up @@ -153,3 +155,12 @@ def test_freezegun_mocking(writer):
logger.info("Frozen")

assert writer.read() == "[2000 01 01 18:00:05] Frozen\n"


@pytest.mark.parametrize(
"format", ["ss.SSSSSSS", "SS.SSSSSSSS.SS", "HH:mm:ss.SSSSSSSSS", "SSSSSSSSSS"]
)
def test_invalid_time_format(writer, format):
logger.add(writer, format=f"{{time:{format}}} {{message}}", catch=False)
with pytest.raises(ValueError, match="Invalid time format"):
logger.info("Test")

0 comments on commit 28749e7

Please sign in to comment.