@@ -93,94 +93,67 @@ static ReaderConfiguration& ReaderConfiguration_setCryptoKeyReader(ReaderConfigu
9393 return conf;
9494}
9595
96- class LoggerWrapper : public Logger {
97- PyObject* const _pyLogger;
98- const int _pythonLogLevel;
96+ class LoggerWrapper : public Logger , public CaptivePythonObjectMixin {
9997 const std::unique_ptr<Logger> _fallbackLogger;
10098
101- static constexpr int _getLogLevelValue (Level level) { return 10 + (level * 10 ); }
102-
10399 public:
104- LoggerWrapper (PyObject* pyLogger, int pythonLogLevel, Logger* fallbackLogger)
105- : _pyLogger(pyLogger), _pythonLogLevel(pythonLogLevel), _fallbackLogger(fallbackLogger) {
106- Py_XINCREF (_pyLogger);
107- }
100+ LoggerWrapper (PyObject* pyLogger, Logger* fallbackLogger)
101+ : CaptivePythonObjectMixin(pyLogger), _fallbackLogger(fallbackLogger) {}
108102
109103 LoggerWrapper (const LoggerWrapper&) = delete ;
110104 LoggerWrapper (LoggerWrapper&&) noexcept = delete ;
111105 LoggerWrapper& operator =(const LoggerWrapper&) = delete ;
112106 LoggerWrapper& operator =(LoggerWrapper&&) = delete ;
113107
114- virtual ~LoggerWrapper () { Py_XDECREF (_pyLogger); }
115-
116- bool isEnabled (Level level) { return _getLogLevelValue (level) >= _pythonLogLevel; }
108+ bool isEnabled (Level level) {
109+ return true ; // Python loggers are always enabled; they decide internally whether or not to log.
110+ }
117111
118112 void log (Level level, int line, const std::string& message) {
119113 if (!Py_IsInitialized ()) {
120114 // Python logger is unavailable - fallback to console logger
121115 _fallbackLogger->log (level, line, message);
122116 } else {
123117 PyGILState_STATE state = PyGILState_Ensure ();
124-
118+ PyObject *type, *value, *traceback;
119+ PyErr_Fetch (&type, &value, &traceback);
125120 try {
126121 switch (level) {
127122 case Logger::LEVEL_DEBUG:
128- py::call_method <void >(_pyLogger , " debug " , message.c_str ());
123+ py::call <void >(_captive , " DEBUG " , message.c_str ());
129124 break ;
130125 case Logger::LEVEL_INFO:
131- py::call_method <void >(_pyLogger , " info " , message.c_str ());
126+ py::call <void >(_captive , " INFO " , message.c_str ());
132127 break ;
133128 case Logger::LEVEL_WARN:
134- py::call_method <void >(_pyLogger , " warning " , message.c_str ());
129+ py::call <void >(_captive , " WARNING " , message.c_str ());
135130 break ;
136131 case Logger::LEVEL_ERROR:
137- py::call_method <void >(_pyLogger , " error " , message.c_str ());
132+ py::call <void >(_captive , " ERROR " , message.c_str ());
138133 break ;
139134 }
140-
141135 } catch (const py::error_already_set& e) {
136+ PyErr_Print ();
142137 _fallbackLogger->log (level, line, message);
143138 }
144-
139+ PyErr_Restore (type, value, traceback);
145140 PyGILState_Release (state);
146141 }
147142 }
148143};
149144
150- class LoggerWrapperFactory : public LoggerFactory {
145+ class LoggerWrapperFactory : public LoggerFactory , public CaptivePythonObjectMixin {
151146 std::unique_ptr<LoggerFactory> _fallbackLoggerFactory{new ConsoleLoggerFactory};
152- PyObject* _pyLogger;
153- Optional<int > _pythonLogLevel{Optional<int >::empty ()};
154-
155- void initializePythonLogLevel () {
156- PyGILState_STATE state = PyGILState_Ensure ();
157-
158- try {
159- int level = py::call_method<int >(_pyLogger, " getEffectiveLevel" );
160- _pythonLogLevel = Optional<int >::of (level);
161- } catch (const py::error_already_set& e) {
162- // Failed to get log level from _pyLogger, set it to empty to fallback to _fallbackLogger
163- _pythonLogLevel = Optional<int >::empty ();
164- }
165-
166- PyGILState_Release (state);
167- }
168147
169148 public:
170- LoggerWrapperFactory (py::object pyLogger) {
171- _pyLogger = pyLogger.ptr ();
172- Py_XINCREF (_pyLogger);
173- initializePythonLogLevel ();
174- }
175-
176- virtual ~LoggerWrapperFactory () { Py_XDECREF (_pyLogger); }
149+ LoggerWrapperFactory (py::object pyLogger) : CaptivePythonObjectMixin(pyLogger.ptr()) {}
177150
178151 Logger* getLogger (const std::string& fileName) {
179152 const auto fallbackLogger = _fallbackLoggerFactory->getLogger (fileName);
180- if (_pythonLogLevel.is_present ()) {
181- return new LoggerWrapper (_pyLogger, _pythonLogLevel.value (), fallbackLogger);
182- } else {
153+ if (_captive == py::object ().ptr ()) {
183154 return fallbackLogger;
155+ } else {
156+ return new LoggerWrapper (_captive, fallbackLogger);
184157 }
185158 }
186159};
0 commit comments