dycw-utilities 0.131.11__py3-none-any.whl → 0.131.13__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dycw_utilities-0.131.11.dist-info → dycw_utilities-0.131.13.dist-info}/METADATA +1 -1
- {dycw_utilities-0.131.11.dist-info → dycw_utilities-0.131.13.dist-info}/RECORD +21 -21
- utilities/__init__.py +1 -1
- utilities/atools.py +7 -9
- utilities/cachetools.py +8 -10
- utilities/datetime.py +2 -9
- utilities/fastapi.py +2 -4
- utilities/fpdf2.py +2 -2
- utilities/hypothesis.py +0 -136
- utilities/logging.py +54 -52
- utilities/orjson.py +46 -45
- utilities/period.py +86 -256
- utilities/pyinstrument.py +2 -3
- utilities/traceback.py +18 -21
- utilities/typing.py +25 -1
- utilities/tzdata.py +1 -53
- utilities/tzlocal.py +2 -26
- utilities/whenever2.py +15 -2
- utilities/zoneinfo.py +2 -2
- {dycw_utilities-0.131.11.dist-info → dycw_utilities-0.131.13.dist-info}/WHEEL +0 -0
- {dycw_utilities-0.131.11.dist-info → dycw_utilities-0.131.13.dist-info}/licenses/LICENSE +0 -0
utilities/logging.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import datetime as dt
|
4
3
|
import re
|
5
4
|
from dataclasses import dataclass, field
|
6
5
|
from functools import cached_property
|
@@ -19,7 +18,6 @@ from logging import (
|
|
19
18
|
from logging.handlers import BaseRotatingHandler, TimedRotatingFileHandler
|
20
19
|
from pathlib import Path
|
21
20
|
from re import Pattern
|
22
|
-
from time import time
|
23
21
|
from typing import (
|
24
22
|
TYPE_CHECKING,
|
25
23
|
Any,
|
@@ -32,17 +30,31 @@ from typing import (
|
|
32
30
|
override,
|
33
31
|
)
|
34
32
|
|
33
|
+
from whenever import PlainDateTime, ZonedDateTime
|
34
|
+
|
35
35
|
from utilities.atomicwrites import move_many
|
36
36
|
from utilities.dataclasses import replace_non_sentinel
|
37
|
-
from utilities.datetime import parse_datetime_compact, serialize_compact
|
38
37
|
from utilities.errors import ImpossibleCaseError
|
39
38
|
from utilities.iterables import OneEmptyError, always_iterable, one
|
40
39
|
from utilities.pathlib import ensure_suffix, get_path
|
40
|
+
from utilities.re import (
|
41
|
+
ExtractGroupError,
|
42
|
+
ExtractGroupsError,
|
43
|
+
extract_group,
|
44
|
+
extract_groups,
|
45
|
+
)
|
41
46
|
from utilities.sentinel import Sentinel, sentinel
|
42
|
-
from utilities.tzlocal import
|
47
|
+
from utilities.tzlocal import LOCAL_TIME_ZONE_NAME
|
48
|
+
from utilities.whenever2 import (
|
49
|
+
WheneverLogRecord,
|
50
|
+
format_compact,
|
51
|
+
get_now,
|
52
|
+
get_now_local,
|
53
|
+
)
|
43
54
|
|
44
55
|
if TYPE_CHECKING:
|
45
56
|
from collections.abc import Callable, Iterable, Mapping
|
57
|
+
from datetime import time
|
46
58
|
from logging import _FilterType
|
47
59
|
|
48
60
|
from utilities.types import (
|
@@ -54,7 +66,9 @@ if TYPE_CHECKING:
|
|
54
66
|
)
|
55
67
|
|
56
68
|
|
57
|
-
_DEFAULT_FORMAT =
|
69
|
+
_DEFAULT_FORMAT = (
|
70
|
+
"{zoned_datetime} | {name}:{funcName}:{lineno} | {levelname:8} | {message}"
|
71
|
+
)
|
58
72
|
_DEFAULT_DATEFMT = "%Y-%m-%d %H:%M:%S"
|
59
73
|
_DEFAULT_BACKUP_COUNT: int = 100
|
60
74
|
_DEFAULT_MAX_BYTES: int = 10 * 1024**2
|
@@ -76,7 +90,6 @@ def add_filters(handler: Handler, /, *filters: _FilterType) -> None:
|
|
76
90
|
def basic_config(
|
77
91
|
*,
|
78
92
|
obj: LoggerOrName | Handler | None = None,
|
79
|
-
whenever: bool = False,
|
80
93
|
format_: str = _DEFAULT_FORMAT,
|
81
94
|
datefmt: str = _DEFAULT_DATEFMT,
|
82
95
|
level: LogLevel = "INFO",
|
@@ -93,7 +106,6 @@ def basic_config(
|
|
93
106
|
logger.addHandler(handler := StreamHandler())
|
94
107
|
basic_config(
|
95
108
|
obj=handler,
|
96
|
-
whenever=whenever,
|
97
109
|
format_=format_,
|
98
110
|
datefmt=datefmt,
|
99
111
|
level=level,
|
@@ -104,7 +116,6 @@ def basic_config(
|
|
104
116
|
case str() as name:
|
105
117
|
basic_config(
|
106
118
|
obj=get_logger(logger=name),
|
107
|
-
whenever=whenever,
|
108
119
|
format_=format_,
|
109
120
|
datefmt=datefmt,
|
110
121
|
level=level,
|
@@ -117,7 +128,6 @@ def basic_config(
|
|
117
128
|
if filters is not None:
|
118
129
|
add_filters(handler, *always_iterable(filters))
|
119
130
|
formatter = get_formatter(
|
120
|
-
whenever=whenever,
|
121
131
|
format_=format_,
|
122
132
|
datefmt=datefmt,
|
123
133
|
plain=plain,
|
@@ -179,18 +189,13 @@ class _FieldStyleDict(TypedDict):
|
|
179
189
|
|
180
190
|
def get_formatter(
|
181
191
|
*,
|
182
|
-
whenever: bool = False,
|
183
192
|
format_: str = _DEFAULT_FORMAT,
|
184
193
|
datefmt: str = _DEFAULT_DATEFMT,
|
185
194
|
plain: bool = False,
|
186
195
|
color_field_styles: Mapping[str, _FieldStyleKeys] | None = None,
|
187
196
|
) -> Formatter:
|
188
197
|
"""Get the formatter; colored if available."""
|
189
|
-
|
190
|
-
from utilities.whenever2 import WheneverLogRecord
|
191
|
-
|
192
|
-
setLogRecordFactory(WheneverLogRecord)
|
193
|
-
format_ = format_.replace("{asctime}", "{zoned_datetime}")
|
198
|
+
setLogRecordFactory(WheneverLogRecord)
|
194
199
|
if plain:
|
195
200
|
return _get_plain_formatter(format_=format_, datefmt=datefmt)
|
196
201
|
try:
|
@@ -199,8 +204,7 @@ def get_formatter(
|
|
199
204
|
return _get_plain_formatter(format_=format_, datefmt=datefmt)
|
200
205
|
default = cast("dict[_FieldStyleKeys, _FieldStyleDict]", DEFAULT_FIELD_STYLES)
|
201
206
|
field_styles = {cast("str", k): v for k, v in default.items()}
|
202
|
-
|
203
|
-
field_styles["zoned_datetime"] = default["asctime"]
|
207
|
+
field_styles["zoned_datetime"] = default["asctime"]
|
204
208
|
if color_field_styles is not None:
|
205
209
|
field_styles.update({k: default[v] for k, v in color_field_styles.items()})
|
206
210
|
return ColoredFormatter(
|
@@ -256,7 +260,6 @@ class GetLoggingLevelNumberError(Exception):
|
|
256
260
|
def setup_logging(
|
257
261
|
*,
|
258
262
|
logger: LoggerOrName | None = None,
|
259
|
-
whenever: bool = False,
|
260
263
|
format_: str = _DEFAULT_FORMAT,
|
261
264
|
datefmt: str = _DEFAULT_DATEFMT,
|
262
265
|
console_level: LogLevel = "INFO",
|
@@ -272,7 +275,6 @@ def setup_logging(
|
|
272
275
|
"""Set up logger."""
|
273
276
|
basic_config(
|
274
277
|
obj=logger,
|
275
|
-
whenever=whenever,
|
276
278
|
format_=f"{console_prefix} {format_}",
|
277
279
|
datefmt=datefmt,
|
278
280
|
level=console_level,
|
@@ -295,7 +297,6 @@ def setup_logging(
|
|
295
297
|
logger_use.addHandler(handler)
|
296
298
|
basic_config(
|
297
299
|
obj=handler,
|
298
|
-
whenever=whenever,
|
299
300
|
format_=format_,
|
300
301
|
datefmt=datefmt,
|
301
302
|
level=level,
|
@@ -330,7 +331,7 @@ class SizeAndTimeRotatingFileHandler(BaseRotatingHandler):
|
|
330
331
|
interval: int = 1,
|
331
332
|
backupCount: int = _DEFAULT_BACKUP_COUNT,
|
332
333
|
utc: bool = False,
|
333
|
-
atTime:
|
334
|
+
atTime: time | None = None,
|
334
335
|
) -> None:
|
335
336
|
path = Path(filename)
|
336
337
|
path.parent.mkdir(parents=True, exist_ok=True)
|
@@ -382,7 +383,7 @@ class SizeAndTimeRotatingFileHandler(BaseRotatingHandler):
|
|
382
383
|
if not self.delay: # pragma: no cover
|
383
384
|
self.stream = self._open()
|
384
385
|
self._time_handler.rolloverAt = ( # skipif-ci-and-windows
|
385
|
-
self._time_handler.computeRollover(
|
386
|
+
self._time_handler.computeRollover(get_now().timestamp())
|
386
387
|
)
|
387
388
|
|
388
389
|
def _should_rollover(self, record: LogRecord, /) -> bool:
|
@@ -400,10 +401,8 @@ class SizeAndTimeRotatingFileHandler(BaseRotatingHandler):
|
|
400
401
|
def _compute_rollover_patterns(stem: str, suffix: str, /) -> _RolloverPatterns:
|
401
402
|
return _RolloverPatterns(
|
402
403
|
pattern1=re.compile(rf"^{stem}\.(\d+){suffix}$"),
|
403
|
-
pattern2=re.compile(rf"^{stem}\.(\d+)__(\
|
404
|
-
pattern3=re.compile(
|
405
|
-
rf"^{stem}\.(\d+)__(\d{{8}}T\d{{6}})__(\d{{8}}T\d{{6}}){suffix}$"
|
406
|
-
),
|
404
|
+
pattern2=re.compile(rf"^{stem}\.(\d+)__([\dT]+?){suffix}$"),
|
405
|
+
pattern3=re.compile(rf"^{stem}\.(\d+)__([\dT]+?)__([\dT]+?){suffix}$"),
|
407
406
|
)
|
408
407
|
|
409
408
|
|
@@ -452,7 +451,7 @@ def _compute_rollover_actions(
|
|
452
451
|
rotations.add(
|
453
452
|
_Rotation(file=file, index=curr + 1, start=start, end=end)
|
454
453
|
)
|
455
|
-
case int() as index,
|
454
|
+
case int() as index, ZonedDateTime(), ZonedDateTime():
|
456
455
|
rotations.add(_Rotation(file=file, index=index + 1))
|
457
456
|
case _: # pragma: no cover
|
458
457
|
raise NotImplementedError
|
@@ -476,8 +475,8 @@ class _RotatingLogFile:
|
|
476
475
|
stem: str
|
477
476
|
suffix: str
|
478
477
|
index: int | None = None
|
479
|
-
start:
|
480
|
-
end:
|
478
|
+
start: ZonedDateTime | None = None
|
479
|
+
end: ZonedDateTime | None = None
|
481
480
|
|
482
481
|
@classmethod
|
483
482
|
def from_path(
|
@@ -494,16 +493,23 @@ class _RotatingLogFile:
|
|
494
493
|
if patterns is None:
|
495
494
|
patterns = _compute_rollover_patterns(stem, suffix)
|
496
495
|
try:
|
497
|
-
|
498
|
-
except
|
496
|
+
index, start, end = extract_groups(patterns.pattern3, path.name)
|
497
|
+
except ExtractGroupsError:
|
499
498
|
pass
|
500
499
|
else:
|
501
500
|
return cls(
|
502
|
-
directory=path.parent,
|
501
|
+
directory=path.parent,
|
502
|
+
stem=stem,
|
503
|
+
suffix=suffix,
|
504
|
+
index=int(index),
|
505
|
+
start=PlainDateTime.parse_common_iso(start).assume_tz(
|
506
|
+
LOCAL_TIME_ZONE_NAME
|
507
|
+
),
|
508
|
+
end=PlainDateTime.parse_common_iso(end).assume_tz(LOCAL_TIME_ZONE_NAME),
|
503
509
|
)
|
504
510
|
try:
|
505
|
-
|
506
|
-
except
|
511
|
+
index, end = extract_groups(patterns.pattern2, path.name)
|
512
|
+
except ExtractGroupsError:
|
507
513
|
pass
|
508
514
|
else:
|
509
515
|
return cls(
|
@@ -511,21 +517,17 @@ class _RotatingLogFile:
|
|
511
517
|
stem=stem,
|
512
518
|
suffix=suffix,
|
513
519
|
index=int(index),
|
514
|
-
end=
|
520
|
+
end=PlainDateTime.parse_common_iso(end).assume_tz(LOCAL_TIME_ZONE_NAME),
|
515
521
|
)
|
516
522
|
try:
|
517
|
-
|
518
|
-
except
|
519
|
-
|
523
|
+
index = extract_group(patterns.pattern1, path.name)
|
524
|
+
except ExtractGroupError:
|
525
|
+
pass
|
520
526
|
else:
|
521
527
|
return cls(
|
522
|
-
directory=path.parent,
|
523
|
-
stem=stem,
|
524
|
-
suffix=suffix,
|
525
|
-
index=int(index),
|
526
|
-
start=parse_datetime_compact(start),
|
527
|
-
end=parse_datetime_compact(end),
|
528
|
+
directory=path.parent, stem=stem, suffix=suffix, index=int(index)
|
528
529
|
)
|
530
|
+
return cls(directory=path.parent, stem=stem, suffix=suffix)
|
529
531
|
|
530
532
|
@cached_property
|
531
533
|
def path(self) -> Path:
|
@@ -535,10 +537,10 @@ class _RotatingLogFile:
|
|
535
537
|
tail = None
|
536
538
|
case int() as index, None, None:
|
537
539
|
tail = str(index)
|
538
|
-
case int() as index, None,
|
539
|
-
tail = f"{index}__{
|
540
|
-
case int() as index,
|
541
|
-
tail = f"{index}__{
|
540
|
+
case int() as index, None, ZonedDateTime() as end:
|
541
|
+
tail = f"{index}__{format_compact(end)}"
|
542
|
+
case int() as index, ZonedDateTime() as start, ZonedDateTime() as end:
|
543
|
+
tail = f"{index}__{format_compact(start)}__{format_compact(end)}"
|
542
544
|
case _: # pragma: no cover
|
543
545
|
raise ImpossibleCaseError(
|
544
546
|
case=[f"{self.index=}", f"{self.start=}", f"{self.end=}"]
|
@@ -550,8 +552,8 @@ class _RotatingLogFile:
|
|
550
552
|
self,
|
551
553
|
*,
|
552
554
|
index: int | None | Sentinel = sentinel,
|
553
|
-
start:
|
554
|
-
end:
|
555
|
+
start: ZonedDateTime | None | Sentinel = sentinel,
|
556
|
+
end: ZonedDateTime | None | Sentinel = sentinel,
|
555
557
|
) -> Self:
|
556
558
|
return replace_non_sentinel(self, index=index, start=start, end=end)
|
557
559
|
|
@@ -568,8 +570,8 @@ class _Deletion:
|
|
568
570
|
class _Rotation:
|
569
571
|
file: _RotatingLogFile
|
570
572
|
index: int = 0
|
571
|
-
start:
|
572
|
-
end:
|
573
|
+
start: ZonedDateTime | None | Sentinel = sentinel
|
574
|
+
end: ZonedDateTime | Sentinel = sentinel
|
573
575
|
|
574
576
|
@cached_property
|
575
577
|
def destination(self) -> Path:
|
utilities/orjson.py
CHANGED
@@ -14,6 +14,7 @@ from pathlib import Path
|
|
14
14
|
from re import Pattern, search
|
15
15
|
from typing import TYPE_CHECKING, Any, Literal, Self, assert_never, overload, override
|
16
16
|
from uuid import UUID
|
17
|
+
from zoneinfo import ZoneInfo
|
17
18
|
|
18
19
|
from orjson import (
|
19
20
|
OPT_PASSTHROUGH_DATACLASS,
|
@@ -22,6 +23,7 @@ from orjson import (
|
|
22
23
|
dumps,
|
23
24
|
loads,
|
24
25
|
)
|
26
|
+
from whenever import ZonedDateTime
|
25
27
|
|
26
28
|
from utilities.concurrent import concurrent_map
|
27
29
|
from utilities.dataclasses import dataclass_to_dict
|
@@ -35,15 +37,8 @@ from utilities.iterables import (
|
|
35
37
|
)
|
36
38
|
from utilities.logging import get_logging_level_number
|
37
39
|
from utilities.math import MAX_INT64, MIN_INT64
|
38
|
-
from utilities.types import
|
39
|
-
|
40
|
-
DateOrDateTime,
|
41
|
-
LogLevel,
|
42
|
-
MaybeIterable,
|
43
|
-
PathLike,
|
44
|
-
StrMapping,
|
45
|
-
)
|
46
|
-
from utilities.tzlocal import get_local_time_zone
|
40
|
+
from utilities.types import Dataclass, LogLevel, MaybeIterable, PathLike, StrMapping
|
41
|
+
from utilities.tzlocal import LOCAL_TIME_ZONE
|
47
42
|
from utilities.uuid import UUID_PATTERN
|
48
43
|
from utilities.version import Version, parse_version
|
49
44
|
from utilities.whenever import (
|
@@ -57,12 +52,14 @@ from utilities.whenever import (
|
|
57
52
|
serialize_time,
|
58
53
|
serialize_timedelta,
|
59
54
|
)
|
60
|
-
from utilities.
|
55
|
+
from utilities.whenever2 import from_timestamp
|
61
56
|
|
62
57
|
if TYPE_CHECKING:
|
63
58
|
from collections.abc import Set as AbstractSet
|
64
59
|
from logging import _FormatStyle
|
65
60
|
|
61
|
+
from whenever import Date
|
62
|
+
|
66
63
|
from utilities.types import Parallelism
|
67
64
|
|
68
65
|
|
@@ -92,6 +89,7 @@ class _Prefixes(Enum):
|
|
92
89
|
unserializable = "un"
|
93
90
|
uuid = "uu"
|
94
91
|
version = "v"
|
92
|
+
zoned_datetime = "zd"
|
95
93
|
|
96
94
|
|
97
95
|
type _DataclassHook = Callable[[type[Dataclass], StrMapping], StrMapping]
|
@@ -194,6 +192,8 @@ def _pre_process(
|
|
194
192
|
return f"[{_Prefixes.exception_class.value}|{error_cls.__qualname__}]"
|
195
193
|
case Version() as version:
|
196
194
|
return f"[{_Prefixes.version.value}]{version!s}"
|
195
|
+
case ZonedDateTime() as datetime:
|
196
|
+
return f"[{_Prefixes.zoned_datetime.value}]{datetime}"
|
197
197
|
# contains
|
198
198
|
case Dataclass() as dataclass:
|
199
199
|
asdict = dataclass_to_dict(
|
@@ -350,6 +350,11 @@ _ZONED_DATETIME_PATTERN = re.compile(
|
|
350
350
|
+ _Prefixes.datetime.value
|
351
351
|
+ r"\](\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,6})?[\+\-]\d{2}:\d{2}(?::\d{2})?\[(?!(?:dt\.)).+?\])$"
|
352
352
|
)
|
353
|
+
_ZONED_DATETIME_PATTERN2 = re.compile(
|
354
|
+
r"^\["
|
355
|
+
+ _Prefixes.zoned_datetime.value
|
356
|
+
+ r"\](\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?[\+\-]\d{2}:\d{2}(?::\d{2})?\[(?!(?:dt\.)).+?\])$"
|
357
|
+
)
|
353
358
|
|
354
359
|
|
355
360
|
def _make_unit_pattern(prefix: _Prefixes, /) -> Pattern[str]:
|
@@ -437,6 +442,8 @@ def _object_hook(
|
|
437
442
|
return parse_version(match.group(1))
|
438
443
|
if match := _ZONED_DATETIME_PATTERN.search(text):
|
439
444
|
return parse_zoned_datetime(match.group(1))
|
445
|
+
if match := _ZONED_DATETIME_PATTERN2.search(text):
|
446
|
+
return ZonedDateTime.parse_common_iso(match.group(1))
|
440
447
|
if (
|
441
448
|
exc_class := _object_hook_exception_class(
|
442
449
|
text, data=data, objects=objects, redirects=redirects
|
@@ -753,9 +760,7 @@ class OrjsonFormatter(Formatter):
|
|
753
760
|
path_name=Path(record.pathname),
|
754
761
|
line_num=record.lineno,
|
755
762
|
message=record.getMessage(),
|
756
|
-
datetime=
|
757
|
-
record.created, tz=get_local_time_zone()
|
758
|
-
),
|
763
|
+
datetime=from_timestamp(record.created, time_zone=LOCAL_TIME_ZONE),
|
759
764
|
func_name=record.funcName,
|
760
765
|
extra=extra if len(extra) >= 1 else None,
|
761
766
|
)
|
@@ -859,11 +864,16 @@ class GetLogRecordsOutput:
|
|
859
864
|
for r in self.records
|
860
865
|
]
|
861
866
|
if len(records) >= 1:
|
862
|
-
time_zone = one_unique(
|
867
|
+
time_zone = one_unique(ZoneInfo(r.datetime.tz) for r in records)
|
863
868
|
else:
|
864
|
-
time_zone =
|
869
|
+
time_zone = LOCAL_TIME_ZONE
|
865
870
|
return DataFrame(
|
866
|
-
data=[
|
871
|
+
data=[
|
872
|
+
dataclass_to_dict(
|
873
|
+
replace(r, datetime=r.datetime.py_datetime()), recursive=False
|
874
|
+
)
|
875
|
+
for r in records
|
876
|
+
],
|
867
877
|
schema={
|
868
878
|
"index": UInt64,
|
869
879
|
"name": String,
|
@@ -891,9 +901,12 @@ class GetLogRecordsOutput:
|
|
891
901
|
level: LogLevel | None = None,
|
892
902
|
min_level: LogLevel | None = None,
|
893
903
|
max_level: LogLevel | None = None,
|
894
|
-
|
895
|
-
|
896
|
-
|
904
|
+
date: Date | None = None,
|
905
|
+
min_date: Date | None = None,
|
906
|
+
max_date: Date | None = None,
|
907
|
+
datetime: ZonedDateTime | None = None,
|
908
|
+
min_datetime: ZonedDateTime | None = None,
|
909
|
+
max_datetime: ZonedDateTime | None = None,
|
897
910
|
func_name: bool | str | None = None,
|
898
911
|
extra: bool | MaybeIterable[str] | None = None,
|
899
912
|
log_file: bool | PathLike | None = None,
|
@@ -932,30 +945,18 @@ class GetLogRecordsOutput:
|
|
932
945
|
records = [
|
933
946
|
r for r in records if r.level <= get_logging_level_number(max_level)
|
934
947
|
]
|
935
|
-
if
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
if
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
case dt.date() as min_date:
|
948
|
-
records = [r for r in records if r.date >= min_date]
|
949
|
-
case _ as never:
|
950
|
-
assert_never(never)
|
951
|
-
if max_date_or_datetime is not None:
|
952
|
-
match max_date_or_datetime:
|
953
|
-
case dt.datetime() as max_datetime:
|
954
|
-
records = [r for r in records if r.datetime <= max_datetime]
|
955
|
-
case dt.date() as max_date:
|
956
|
-
records = [r for r in records if r.date <= max_date]
|
957
|
-
case _ as never:
|
958
|
-
assert_never(never)
|
948
|
+
if date is not None:
|
949
|
+
records = [r for r in records if r.date == date]
|
950
|
+
if min_date is not None:
|
951
|
+
records = [r for r in records if r.date >= min_date]
|
952
|
+
if max_date is not None:
|
953
|
+
records = [r for r in records if r.date <= max_date]
|
954
|
+
if datetime is not None:
|
955
|
+
records = [r for r in records if r.datetime == datetime]
|
956
|
+
if min_datetime is not None:
|
957
|
+
records = [r for r in records if r.datetime >= min_datetime]
|
958
|
+
if max_datetime is not None:
|
959
|
+
records = [r for r in records if r.datetime <= max_datetime]
|
959
960
|
if func_name is not None:
|
960
961
|
match func_name:
|
961
962
|
case bool() as has_func_name:
|
@@ -1058,7 +1059,7 @@ class OrjsonLogRecord:
|
|
1058
1059
|
level: int
|
1059
1060
|
path_name: Path
|
1060
1061
|
line_num: int
|
1061
|
-
datetime:
|
1062
|
+
datetime: ZonedDateTime
|
1062
1063
|
func_name: str | None = None
|
1063
1064
|
stack_info: str | None = None
|
1064
1065
|
extra: StrMapping | None = None
|
@@ -1066,7 +1067,7 @@ class OrjsonLogRecord:
|
|
1066
1067
|
log_file_line_num: int | None = None
|
1067
1068
|
|
1068
1069
|
@cached_property
|
1069
|
-
def date(self) ->
|
1070
|
+
def date(self) -> Date:
|
1070
1071
|
return self.datetime.date()
|
1071
1072
|
|
1072
1073
|
|