55from contextlib import contextmanager
66from dataclasses import dataclass , field
77from types import SimpleNamespace
8- from typing import TypeAlias
8+ from typing import Final , TypeAlias
99
1010
1111def _timedelta_as_minute_second_ms (delta : datetime .timedelta ) -> str :
@@ -30,28 +30,17 @@ def _timedelta_as_minute_second_ms(delta: datetime.timedelta) -> str:
3030 return f"{ sign } { result .strip ()} "
3131
3232
33- def _resolve (val : str | Callable [[], str ], context : str ) -> str :
34- """Resolve a message value that can be either a string or a callable.
35-
36- Args:
37- val: The value to resolve (string or callable returning string)
38- context: Description of which message this is for error reporting
39-
40- Returns:
41- The resolved string value
42- """
43- if isinstance (val , str ):
44- return val
33+ def _resolve (val : str | Callable [[], str ], prefix : str , suffix : str ) -> str :
4534 try :
46- return val ()
47- except Exception as exc :
35+ return f" { prefix } { val if isinstance ( val , str ) else val () } { suffix } "
36+ except Exception as exc : # pylint: disable=broad-exception-caught
4837 warnings .warn (
49- f"Failed to generate { context } message: { exc !r} . "
38+ f"Failed to generate { val } message: { exc !r} . "
5039 f"Fix the callable to return a string without raising exceptions." ,
5140 UserWarning ,
5241 stacklevel = 3 ,
5342 )
54- return f"❌❌❌ [{ context } message generation failed TIP: Check how the { context } message is generated!] ❌❌❌"
43+ return f"❌❌❌ [{ val } message generation failed TIP: Check how the { val } message is generated!] ❌❌❌"
5544
5645
5746class DynamicIndentFormatter (logging .Formatter ):
@@ -100,12 +89,12 @@ def setup(cls, logger: logging.Logger) -> None:
10089
10190
10291# Message formatting constants
103- _STARTING_PREFIX = "--> "
104- _STARTING_SUFFIX = " ⏳"
105- _DONE_PREFIX = "<-- "
106- _DONE_SUFFIX = " ✅"
107- _RAISED_PREFIX = "❌❌❌ Error: "
108- _RAISED_SUFFIX = " ❌❌❌"
92+ _STARTING_PREFIX : Final [ str ] = "--> "
93+ _STARTING_SUFFIX : Final [ str ] = " ⏳"
94+ _DONE_PREFIX : Final [ str ] = "<-- "
95+ _DONE_SUFFIX : Final [ str ] = " ✅"
96+ _RAISED_PREFIX : Final [ str ] = "❌❌❌ Error: "
97+ _RAISED_SUFFIX : Final [ str ] = " ❌❌❌"
10998
11099
111100@dataclass
@@ -115,40 +104,9 @@ class ContextMessages:
115104 raised : str | Callable [[], str ] = field (default = "" )
116105
117106 def __post_init__ (self ):
118- # Store original callables before processing
119- original_starting = self .starting
120- original_done = self .done
121- original_raised = self .raised
122-
123- # Apply formatting to starting message
124- if isinstance (self .starting , str ):
125- self .starting = f"{ _STARTING_PREFIX } { self .starting } { _STARTING_SUFFIX } "
126- else :
127- self .starting = (
128- lambda : f"{ _STARTING_PREFIX } { _resolve (original_starting , 'starting' )} { _STARTING_SUFFIX } "
129- )
130-
131- # Apply formatting to done message
132- if isinstance (self .done , str ):
133- self .done = f"{ _DONE_PREFIX } { self .done } { _DONE_SUFFIX } "
134- else :
135- self .done = (
136- lambda : f"{ _DONE_PREFIX } { _resolve (original_done , 'done' )} { _DONE_SUFFIX } "
137- )
138-
139- # Apply formatting to raised message or create default
140107 if not self .raised :
141- if isinstance (original_done , str ):
142- # Extract base message from original done message (before formatting)
143- self .raised = f"{ _RAISED_PREFIX } { original_done } { _RAISED_SUFFIX } "
144- else :
145- # For callable done, create a simple error message
146- self .raised = f"{ _RAISED_PREFIX } operation failed{ _RAISED_SUFFIX } "
147- elif isinstance (self .raised , str ):
148- self .raised = f"{ _RAISED_PREFIX } { self .raised } { _RAISED_SUFFIX } "
149- else :
150108 self .raised = (
151- lambda : f"{ _RAISED_PREFIX } { _resolve ( original_raised , 'raised' ) } { _RAISED_SUFFIX } "
109+ lambda : f"{ self . done if isinstance ( self . done , str ) else self . done () } [with raised error] "
152110 )
153111
154112
@@ -207,11 +165,16 @@ def log_context(
207165 try :
208166 DynamicIndentFormatter .cls_increase_indent ()
209167
210- logger .log (level , _resolve (ctx_msg .starting , "starting" ), * args , ** kwargs )
168+ logger .log (
169+ level ,
170+ _resolve (ctx_msg .starting , _STARTING_PREFIX , _STARTING_SUFFIX ),
171+ * args ,
172+ ** kwargs ,
173+ )
211174 with _increased_logger_indent (logger ):
212175 yield SimpleNamespace (logger = logger , messages = ctx_msg )
213176 elapsed_time = datetime .datetime .now (tz = datetime .UTC ) - started_time
214- done_message = f"{ _resolve (ctx_msg .done , 'done' )} ({ _timedelta_as_minute_second_ms (elapsed_time )} )"
177+ done_message = f"{ _resolve (ctx_msg .done , _DONE_PREFIX , _DONE_SUFFIX )} ({ _timedelta_as_minute_second_ms (elapsed_time )} )"
215178 logger .log (
216179 level ,
217180 done_message ,
@@ -221,7 +184,7 @@ def log_context(
221184
222185 except :
223186 elapsed_time = datetime .datetime .now (tz = datetime .UTC ) - started_time
224- error_message = f"{ _resolve (ctx_msg .raised , 'raised' )} ({ _timedelta_as_minute_second_ms (elapsed_time )} )"
187+ error_message = f"{ _resolve (ctx_msg .raised , _RAISED_PREFIX , _RAISED_SUFFIX )} ({ _timedelta_as_minute_second_ms (elapsed_time )} )"
225188 logger .exception (
226189 error_message ,
227190 * args ,
0 commit comments