Spaces:
Running
Running
/* | |
pybind11/eval.h: Support for evaluating Python expressions and statements | |
from strings and files | |
Copyright (c) 2016 Klemens Morgenstern <[email protected]> and | |
Wenzel Jakob <[email protected]> | |
All rights reserved. Use of this source code is governed by a | |
BSD-style license that can be found in the LICENSE file. | |
*/ | |
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) | |
PYBIND11_NAMESPACE_BEGIN(detail) | |
inline void ensure_builtins_in_globals(object &global) { | |
// Running exec and eval adds `builtins` module under `__builtins__` key to | |
// globals if not yet present. Python 3.8 made PyRun_String behave | |
// similarly. Let's also do that for older versions, for consistency. This | |
// was missing from PyPy3.8 7.3.7. | |
if (!global.contains("__builtins__")) | |
global["__builtins__"] = module_::import(PYBIND11_BUILTINS_MODULE); | |
(void) global; | |
} | |
PYBIND11_NAMESPACE_END(detail) | |
enum eval_mode { | |
/// Evaluate a string containing an isolated expression | |
eval_expr, | |
/// Evaluate a string containing a single statement. Returns \c none | |
eval_single_statement, | |
/// Evaluate a string containing a sequence of statement. Returns \c none | |
eval_statements | |
}; | |
template <eval_mode mode = eval_expr> | |
object eval(const str &expr, object global = globals(), object local = object()) { | |
if (!local) { | |
local = global; | |
} | |
detail::ensure_builtins_in_globals(global); | |
/* PyRun_String does not accept a PyObject / encoding specifier, | |
this seems to be the only alternative */ | |
std::string buffer = "# -*- coding: utf-8 -*-\n" + (std::string) expr; | |
int start = 0; | |
switch (mode) { | |
case eval_expr: | |
start = Py_eval_input; | |
break; | |
case eval_single_statement: | |
start = Py_single_input; | |
break; | |
case eval_statements: | |
start = Py_file_input; | |
break; | |
default: | |
pybind11_fail("invalid evaluation mode"); | |
} | |
PyObject *result = PyRun_String(buffer.c_str(), start, global.ptr(), local.ptr()); | |
if (!result) { | |
throw error_already_set(); | |
} | |
return reinterpret_steal<object>(result); | |
} | |
template <eval_mode mode = eval_expr, size_t N> | |
object eval(const char (&s)[N], object global = globals(), 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, std::move(global), std::move(local)); | |
} | |
inline void exec(const str &expr, object global = globals(), object local = object()) { | |
eval<eval_statements>(expr, std::move(global), std::move(local)); | |
} | |
template <size_t N> | |
void exec(const char (&s)[N], object global = globals(), object local = object()) { | |
eval<eval_statements>(s, std::move(global), std::move(local)); | |
} | |
template <eval_mode mode = eval_statements> | |
object eval_file(str, object, object) { | |
pybind11_fail("eval_file not supported in PyPy3. Use eval"); | |
} | |
template <eval_mode mode = eval_statements> | |
object eval_file(str, object) { | |
pybind11_fail("eval_file not supported in PyPy3. Use eval"); | |
} | |
template <eval_mode mode = eval_statements> | |
object eval_file(str) { | |
pybind11_fail("eval_file not supported in PyPy3. Use eval"); | |
} | |
template <eval_mode mode = eval_statements> | |
object eval_file(str fname, object global = globals(), object local = object()) { | |
if (!local) { | |
local = global; | |
} | |
detail::ensure_builtins_in_globals(global); | |
int start = 0; | |
switch (mode) { | |
case eval_expr: | |
start = Py_eval_input; | |
break; | |
case eval_single_statement: | |
start = Py_single_input; | |
break; | |
case eval_statements: | |
start = Py_file_input; | |
break; | |
default: | |
pybind11_fail("invalid evaluation mode"); | |
} | |
int closeFile = 1; | |
std::string fname_str = (std::string) fname; | |
FILE *f = _Py_fopen_obj(fname.ptr(), "r"); | |
if (!f) { | |
PyErr_Clear(); | |
pybind11_fail("File \"" + fname_str + "\" could not be opened!"); | |
} | |
if (!global.contains("__file__")) { | |
global["__file__"] = std::move(fname); | |
} | |
PyObject *result | |
= PyRun_FileEx(f, fname_str.c_str(), start, global.ptr(), local.ptr(), closeFile); | |
if (!result) { | |
throw error_already_set(); | |
} | |
return reinterpret_steal<object>(result); | |
} | |
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) | |