Skip to content

Commit a94c1d9

Browse files
committed
from #129
1 parent 0f6c3d4 commit a94c1d9

File tree

1 file changed

+81
-1
lines changed

1 file changed

+81
-1
lines changed

geos-utils/src/geos/utils/Logger.py

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,96 @@
22
# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies.
33
# SPDX-FileContributor: Martin Lemay
44
import logging
5-
from typing import Any, Union
5+
from typing import Any, Union, Generator
66
from typing_extensions import Self
77

8+
import os
9+
import re
10+
import tempfile
11+
from contextlib import contextmanager
12+
813
__doc__ = """
914
Logger module manages logging tools.
1015
1116
Code was modified from <https://stackoverflow.com/questions/384076/how-can-i-color-python-logging-output>
17+
18+
It also include adaptor strategy to make vtkLogger behave as a logging's logger.
19+
Indeed, C++ adapted class is based on private Callback assignement which is not compatible
20+
with logging python's logic.
21+
22+
usage:
23+
#near logger definition
24+
from vtkmodules.vtkCommonCore import vtkLogger
25+
26+
vtkLogger.SetStderrVerbosity(vtkLogger.VERBOSITY_TRACE)
27+
logger.addFilter(RegexExceptionFilter())
28+
29+
...
30+
31+
#near VTK calls
32+
with VTKCaptureLog() as captured_log:
33+
vtkcalls..
34+
captured_log.seek(0) # be kind let's just rewind
35+
captured = captured_log.read().decode()
36+
37+
logger.error(captured.strip())
38+
1239
"""
1340

1441

42+
class RegexExceptionFilter( logging.Filter ):
43+
"""Class to regexp VTK messages rethrown into logger by VTKCaptureLog."""
44+
45+
pattern: str = r"ERR" #pattern captured that will raise a vtkError
46+
47+
def __init__( self ) -> None:
48+
"""Init filter with class based pattern as this is patch to logging logic."""
49+
super().__init__()
50+
self.regex = re.compile( self.pattern )
51+
52+
def filter( self, record: logging.LogRecord ) -> bool:
53+
"""Filter VTK Error from stdErr.
54+
55+
Args:
56+
record(loggging.LogRecord) : record that logger will provide as evaluated
57+
58+
Raises:
59+
VTKError(geos.utils.Error) if a pattern symbol is caught in the stderr.
60+
"""
61+
message = record.getMessage()
62+
if self.regex.search( message ):
63+
raise TypeError( f"Log message matched forbidden pattern: {message}" )
64+
return True # Allow other messages to pass
65+
66+
67+
@contextmanager
68+
def VTKCaptureLog() -> Generator[ Any, Any, Any ]:
69+
"""Hard way of adapting C-like vtkLogger to logging class by throwing in stderr and reading back from it.
70+
71+
Returns:
72+
Generator: buffering os stderr.
73+
74+
"""
75+
#equiv to pyvista's
76+
# from pyvista.utilities import VtkErrorCatcher
77+
# with VtkErrorCatcher() as err:
78+
# append_filter.Update()
79+
# print(err)
80+
# original_stderr_fd = sys.stderr.fileno()
81+
original_stderr_fd = 2
82+
saved_stderr_fd = os.dup( original_stderr_fd )
83+
84+
# Create a temporary file to capture stderr
85+
with tempfile.TemporaryFile( mode='w+b' ) as tmp:
86+
os.dup2( tmp.fileno(), original_stderr_fd )
87+
try:
88+
yield tmp
89+
finally:
90+
# Restore original stderr
91+
os.dup2( saved_stderr_fd, original_stderr_fd )
92+
os.close( saved_stderr_fd )
93+
94+
1595
class CountWarningHandler( logging.Handler ):
1696
"""Create an handler to count the warnings logged."""
1797

0 commit comments

Comments
 (0)