2 * This file is part of the SmuView project.
4 * Copyright (C) 2019-2021 Frank Stettner <frank-stettner@gmx.net>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #ifndef PYTHON_PYSTREAMREDIRECT_HPP
21 #define PYTHON_PYSTREAMREDIRECT_HPP
27 #include <pybind11/pybind11.h>
31 #include "src/python/pystreambuf.hpp"
32 #include "src/python/smuscriptrunner.hpp"
34 using std::shared_ptr
;
37 namespace py
= pybind11
;
42 class __attribute__((visibility("hidden"))) PyStreamRedirect
: public QObject
47 explicit PyStreamRedirect(shared_ptr
<SmuScriptRunner
> script_runner
) :
48 script_runner_(script_runner
)
50 auto sys_module
= py::module::import("sys");
51 old_stdout_
= sys_module
.attr("stdout");
52 old_stderr_
= sys_module
.attr("stderr");
54 auto locale_module
= py::module::import("locale");
55 auto default_encoding
= locale_module
.attr("getpreferredencoding")(false);
57 stdout_buf_
= new PyStreamBuf(
58 py::str(py::getattr(old_stdout_
, "encoding", default_encoding
)),
59 py::str(py::getattr(old_stdout_
, "errors", py::str("strict"))));
60 auto py_stdout_buf
= py::cast(
61 stdout_buf_
, py::return_value_policy::reference
);
62 connect(stdout_buf_
, &PyStreamBuf::send_string
,
63 script_runner_
.get(), &SmuScriptRunner::send_py_stdout
);
65 stderr_buf_
= new PyStreamBuf(
66 py::str(py::getattr(old_stderr_
, "encoding", default_encoding
)),
67 py::str(py::getattr(old_stderr_
, "errors", py::str("backslashreplace"))));
68 auto py_stderr_buf
= py::cast(
69 stderr_buf_
, py::return_value_policy::reference
);
70 connect(stderr_buf_
, &PyStreamBuf::send_string
,
71 script_runner_
.get(), &SmuScriptRunner::send_py_stderr
);
73 sys_module
.attr("stdout") = py_stdout_buf
;
74 sys_module
.attr("stderr") = py_stderr_buf
;
80 auto sys_module
= py::module::import("sys");
81 sys_module
.attr("stdout") = old_stdout_
;
82 sys_module
.attr("stderr") = old_stderr_
;
84 catch (const py::error_already_set
&) {}
86 stdout_buf_
->py_close();
87 stderr_buf_
->py_close();
89 disconnect(stdout_buf_
, &PyStreamBuf::send_string
,
90 script_runner_
.get(), &SmuScriptRunner::send_py_stdout
);
91 disconnect(stderr_buf_
, &PyStreamBuf::send_string
,
92 script_runner_
.get(), &SmuScriptRunner::send_py_stderr
);
96 shared_ptr
<SmuScriptRunner
> script_runner_
;
97 py::object old_stdout_
;
98 py::object old_stderr_
;
99 PyStreamBuf
*stdout_buf_
;
100 PyStreamBuf
*stderr_buf_
;
104 } // namespace python
107 #endif // PYTHON_PYSTREAMREDIRECT_HPP