mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 22:52:01 +00:00
Add py::print() function
Replicates Python API including keyword arguments.
This commit is contained in:
parent
c743e1b1b4
commit
67990d9e19
@ -1233,6 +1233,33 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
NAMESPACE_BEGIN(detail)
|
||||
PYBIND11_NOINLINE inline void print(tuple args, dict kwargs) {
|
||||
auto strings = tuple(args.size());
|
||||
for (size_t i = 0; i < args.size(); ++i) {
|
||||
strings[i] = args[i].cast<object>().str();
|
||||
}
|
||||
auto sep = kwargs["sep"] ? kwargs["sep"] : cast(" ");
|
||||
auto line = sep.attr("join").cast<object>()(strings);
|
||||
|
||||
auto file = kwargs["file"] ? kwargs["file"].cast<object>()
|
||||
: module::import("sys").attr("stdout");
|
||||
auto write = file.attr("write").cast<object>();
|
||||
write(line);
|
||||
write(kwargs["end"] ? kwargs["end"] : cast("\n"));
|
||||
|
||||
if (kwargs["flush"] && kwargs["flush"].cast<bool>()) {
|
||||
file.attr("flush").cast<object>()();
|
||||
}
|
||||
}
|
||||
NAMESPACE_END(detail)
|
||||
|
||||
template <return_value_policy policy = return_value_policy::automatic_reference, typename... Args>
|
||||
void print(Args &&...args) {
|
||||
auto c = detail::collect_arguments<policy>(std::forward<Args>(args)...);
|
||||
detail::print(c.args(), c.kwargs());
|
||||
}
|
||||
|
||||
#if defined(WITH_THREAD)
|
||||
|
||||
/* The functions below essentially reproduce the PyGILState_* API using a RAII
|
||||
|
@ -68,18 +68,22 @@ class Capture(object):
|
||||
def __init__(self, capfd):
|
||||
self.capfd = capfd
|
||||
self.out = ""
|
||||
self.err = ""
|
||||
|
||||
def _flush_stdout(self):
|
||||
def _flush(self):
|
||||
"""Workaround for issues on Windows: to be removed after tests get py::print"""
|
||||
sys.stdout.flush()
|
||||
os.fsync(sys.stdout.fileno()) # make sure C++ output is also read
|
||||
return self.capfd.readouterr()[0]
|
||||
os.fsync(sys.stdout.fileno())
|
||||
sys.stderr.flush()
|
||||
os.fsync(sys.stderr.fileno())
|
||||
return self.capfd.readouterr()
|
||||
|
||||
def __enter__(self):
|
||||
self._flush_stdout()
|
||||
self._flush()
|
||||
return self
|
||||
|
||||
def __exit__(self, *_):
|
||||
self.out = self._flush_stdout()
|
||||
self.out, self.err = self._flush()
|
||||
|
||||
def __eq__(self, other):
|
||||
a = Output(self.out)
|
||||
@ -100,6 +104,10 @@ class Capture(object):
|
||||
def unordered(self):
|
||||
return Unordered(self.out)
|
||||
|
||||
@property
|
||||
def stderr(self):
|
||||
return Output(self.err)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def capture(capfd):
|
||||
|
@ -197,4 +197,18 @@ test_initializer python_types([](py::module &m) {
|
||||
.def_readwrite_static("value", &ExamplePythonTypes::value, "Static value member")
|
||||
.def_readonly_static("value2", &ExamplePythonTypes::value2, "Static value member (readonly)")
|
||||
;
|
||||
|
||||
m.def("test_print_function", []() {
|
||||
py::print("Hello, World!");
|
||||
py::print(1, 2.0, "three", true, std::string("-- multiple args"));
|
||||
auto args = py::make_tuple("and", "a", "custom", "separator");
|
||||
py::print("*args", *args, "sep"_a="-");
|
||||
py::print("no new line here", "end"_a=" -- ");
|
||||
py::print("next print");
|
||||
|
||||
auto py_stderr = py::module::import("sys").attr("stderr").cast<py::object>();
|
||||
py::print("this goes to stderr", "file"_a=py_stderr);
|
||||
|
||||
py::print("flush", "flush"_a=true);
|
||||
});
|
||||
});
|
||||
|
@ -218,3 +218,18 @@ def test_module():
|
||||
assert ExamplePythonTypes.__module__ == "pybind11_tests"
|
||||
assert ExamplePythonTypes.get_set.__name__ == "get_set"
|
||||
assert ExamplePythonTypes.get_set.__module__ == "pybind11_tests"
|
||||
|
||||
|
||||
def test_print(capture):
|
||||
from pybind11_tests import test_print_function
|
||||
|
||||
with capture:
|
||||
test_print_function()
|
||||
assert capture == """
|
||||
Hello, World!
|
||||
1 2.0 three True -- multiple args
|
||||
*args-and-a-custom-separator
|
||||
no new line here -- next print
|
||||
flush
|
||||
"""
|
||||
assert capture.stderr == "this goes to stderr"
|
||||
|
Loading…
Reference in New Issue
Block a user