Commit 194d8b99 by Dean Moldovan Committed by Wenzel Jakob

Support raw string literals as input for py::eval (#766)

* Support raw string literals as input for py::eval
* Dedent only when needed
parent 6db60cd9
...@@ -55,3 +55,18 @@ is always ``none``). ...@@ -55,3 +55,18 @@ is always ``none``).
// Evaluate the statements in an separate Python file on disk // Evaluate the statements in an separate Python file on disk
py::eval_file("script.py", scope); py::eval_file("script.py", scope);
C++11 raw string literals are also supported and quite handy for this purpose.
The only requirement is that the first statement must be on a new line following
the raw string delimiter ``R"(``, ensuring all lines have common leading indent:
.. code-block:: cpp
py::eval<py::eval_statements>(R"(
x = get_answer()
if x == 42:
print('Hello World!')
else:
print('Bye!')
)", scope
);
...@@ -11,8 +11,6 @@ ...@@ -11,8 +11,6 @@
#pragma once #pragma once
#pragma once
#include "pybind11.h" #include "pybind11.h"
NAMESPACE_BEGIN(pybind11) NAMESPACE_BEGIN(pybind11)
...@@ -56,6 +54,14 @@ object eval(str expr, object global = object(), object local = object()) { ...@@ -56,6 +54,14 @@ object eval(str expr, object global = object(), object local = object()) {
return reinterpret_steal<object>(result); return reinterpret_steal<object>(result);
} }
template <eval_mode mode = eval_expr, size_t N>
object eval(const char (&s)[N], object global = object(), object local = object()) {
/* Support raw string literals by removing common leading whitespace */
auto expr = (s[0] == '\n') ? str(module::import("textwrap").attr("dedent")(s))
: str(s);
return eval<mode>(expr, global, local);
}
template <eval_mode mode = eval_statements> template <eval_mode mode = eval_statements>
object eval_file(str fname, object global = object(), object local = object()) { object eval_file(str fname, object global = object(), object local = object()) {
if (!global) { if (!global) {
......
...@@ -20,11 +20,21 @@ test_initializer eval([](py::module &m) { ...@@ -20,11 +20,21 @@ test_initializer eval([](py::module &m) {
return 42; return 42;
}); });
auto result = py::eval<py::eval_statements>( // Regular string literal
"print('Hello World!');\n" py::eval<py::eval_statements>(
"x = call_test();", "message = 'Hello World!'\n"
"x = call_test()",
global, local global, local
); );
// Multi-line raw string literal
auto result = py::eval<py::eval_statements>(R"(
if x == 42:
print(message)
else:
raise RuntimeError
)", global, local
);
auto x = local["x"].cast<int>(); auto x = local["x"].cast<int>();
return result == py::none() && x == 42; return result == py::none() && x == 42;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment