Skip to content

Commit 60110c3

Browse files
committed
Redirect SOFA logs to Python's sys.stdout using a custom PythonMessageHandler.
1 parent d2ba475 commit 60110c3

File tree

4 files changed

+139
-3
lines changed

4 files changed

+139
-3
lines changed

bindings/SofaRuntime/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ project(Bindings.SofaRuntime)
22

33
set(SOURCE_FILES
44
${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/SofaRuntime/Module_SofaRuntime.cpp
5+
${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/SofaRuntime/PythonMessageHandler.cpp
56
${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/SofaRuntime/Timer/Submodule_Timer.cpp
67
)
78

89
set(HEADER_FILES
10+
${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/SofaRuntime/PythonMessageHandler.h
911
${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/SofaRuntime/Timer/Submodule_Timer.h
1012
${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/SofaRuntime/Timer/Submodule_Timer_doc.h
1113
)

bindings/SofaRuntime/src/SofaPython3/SofaRuntime/Module_SofaRuntime.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ using sofapython3::SceneLoaderPY3;
6262
#include <sofa/core/logging/PerComponentLoggingMessageHandler.h>
6363
using sofa::helper::logging::MessageDispatcher;
6464
using sofa::helper::logging::MainPerComponentLoggingMessageHandler;
65-
using sofa::helper::logging::MainConsoleMessageHandler;
65+
#include <SofaPython3/SofaRuntime/PythonMessageHandler.h>
6666

6767
#include <sofa/core/init.h>
6868
#include <sofa/helper/init.h>
@@ -155,9 +155,9 @@ PYBIND11_MODULE(SofaRuntime, m) {
155155

156156
m.def("init", []() {
157157
MessageDispatcher::clearHandlers();
158-
MessageDispatcher::addHandler(&MainConsoleMessageHandler::getInstance());
158+
MessageDispatcher::addHandler(&MainPythonMessageHandler::getInstance());
159159
MessageDispatcher::addHandler(&MainPerComponentLoggingMessageHandler::getInstance());
160-
});
160+
}, "redirect SOFA messages to Python's sys.stdout");
161161

162162
m.add_object("DataRepository", py::cast(&sofa::helper::system::DataRepository));
163163
m.add_object("PluginRepository", py::cast(&sofa::helper::system::PluginRepository));
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/******************************************************************************
2+
* SOFA, Simulation Open-Framework Architecture *
3+
* (c) 2006 INRIA, USTL, UJF, CNRS, MGH *
4+
* *
5+
* This program is free software; you can redistribute it and/or modify it *
6+
* under the terms of the GNU Lesser General Public License as published by *
7+
* the Free Software Foundation; either version 2.1 of the License, or (at *
8+
* your option) any later version. *
9+
* *
10+
* This program is distributed in the hope that it will be useful, but WITHOUT *
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
13+
* for more details. *
14+
* *
15+
* You should have received a copy of the GNU Lesser General Public License *
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
17+
*******************************************************************************
18+
* Authors: The SOFA Team and external contributors (see Authors.txt) *
19+
* *
20+
* Contact information: contact@sofa-framework.org *
21+
******************************************************************************/
22+
#include <SofaPython3/SofaRuntime/PythonMessageHandler.h>
23+
#include <pybind11/pybind11.h>
24+
#include <sofa/helper/logging/Message.h>
25+
26+
namespace sofapython3
27+
{
28+
29+
namespace
30+
{
31+
32+
using namespace std::string_literals;
33+
auto red { "\033[31m"s };
34+
auto green { "\033[32m"s };
35+
auto orange { "\033[38;5;214m"s };
36+
auto magenta { "\033[35m"s };
37+
auto blue { "\033[34m"s };
38+
auto reset { "\033[0m"s };
39+
40+
std::string format(const std::string& type, const std::string& color)
41+
{
42+
return color + "[" + type + "] " + reset;
43+
};
44+
45+
std::string_view getPrefixText(sofa::helper::logging::Message::Type type)
46+
{
47+
static std::string advice = format("SUGGESTION", green);
48+
static std::string deprecated = format("DEPRECATED", orange);
49+
static std::string warning = format("WARNING", orange);
50+
static std::string info = format("INFO", green);
51+
static std::string error = format("ERROR", red);
52+
static std::string fatal = format("FATAL", magenta);
53+
static std::string empty = format("EMPTY", reset);
54+
55+
switch (type)
56+
{
57+
case sofa::helper::logging::Message::Advice : return advice;
58+
case sofa::helper::logging::Message::Deprecated : return deprecated;
59+
case sofa::helper::logging::Message::Warning : return warning;
60+
case sofa::helper::logging::Message::Info : return info;
61+
case sofa::helper::logging::Message::Error : return error;
62+
case sofa::helper::logging::Message::Fatal : return fatal;
63+
case sofa::helper::logging::Message::TEmpty : return empty;
64+
65+
default:
66+
return "";
67+
}
68+
}
69+
70+
}
71+
72+
namespace py { using namespace pybind11; }
73+
74+
void PythonMessageHandler::process(sofa::helper::logging::Message &m)
75+
{
76+
if (!m.sender().empty())
77+
{
78+
py::print(getPrefixText(m.type()), format(m.sender(), blue), m.messageAsString());
79+
}
80+
else
81+
{
82+
py::print(getPrefixText(m.type()), m.messageAsString());
83+
}
84+
}
85+
86+
PythonMessageHandler& MainPythonMessageHandler::getInstance()
87+
{
88+
static PythonMessageHandler s_instance;
89+
return s_instance;
90+
}
91+
92+
} // namespace sofapython3
93+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/******************************************************************************
2+
* SOFA, Simulation Open-Framework Architecture *
3+
* (c) 2006 INRIA, USTL, UJF, CNRS, MGH *
4+
* *
5+
* This program is free software; you can redistribute it and/or modify it *
6+
* under the terms of the GNU Lesser General Public License as published by *
7+
* the Free Software Foundation; either version 2.1 of the License, or (at *
8+
* your option) any later version. *
9+
* *
10+
* This program is distributed in the hope that it will be useful, but WITHOUT *
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
13+
* for more details. *
14+
* *
15+
* You should have received a copy of the GNU Lesser General Public License *
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
17+
*******************************************************************************
18+
* Authors: The SOFA Team and external contributors (see Authors.txt) *
19+
* *
20+
* Contact information: contact@sofa-framework.org *
21+
******************************************************************************/
22+
#pragma once
23+
24+
#include <sofa/helper/logging/MessageHandler.h>
25+
26+
namespace sofapython3
27+
{
28+
29+
class PythonMessageHandler : public sofa::helper::logging::MessageHandler
30+
{
31+
public:
32+
PythonMessageHandler() = default;
33+
void process(sofa::helper::logging::Message& m) override ;
34+
};
35+
36+
class MainPythonMessageHandler
37+
{
38+
public:
39+
static PythonMessageHandler& getInstance() ;
40+
};
41+
} // namespace sofapython3

0 commit comments

Comments
 (0)