diff options
Diffstat (limited to 'ext/pybind11/include/pybind11/eval.h')
-rw-r--r-- | ext/pybind11/include/pybind11/eval.h | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/ext/pybind11/include/pybind11/eval.h b/ext/pybind11/include/pybind11/eval.h new file mode 100644 index 000000000..204427d77 --- /dev/null +++ b/ext/pybind11/include/pybind11/eval.h @@ -0,0 +1,105 @@ +/* + pybind11/exec.h: Support for evaluating Python expressions and statements + from strings and files + + Copyright (c) 2016 Klemens Morgenstern <klemens.morgenstern@ed-chemnitz.de> and + Wenzel Jakob <wenzel.jakob@epfl.ch> + + All rights reserved. Use of this source code is governed by a + BSD-style license that can be found in the LICENSE file. +*/ + +#pragma once + +#pragma once + +#include "pybind11.h" + +NAMESPACE_BEGIN(pybind11) + +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(str expr, object global = object(), object local = object()) { + if (!global) { + global = reinterpret_borrow<object>(PyEval_GetGlobals()); + if (!global) + global = dict(); + } + if (!local) + local = 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; + 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_statements> +object eval_file(str fname, object global = object(), object local = object()) { + if (!global) { + global = reinterpret_borrow<object>(PyEval_GetGlobals()); + if (!global) + global = dict(); + } + if (!local) + local = global; + + int start; + 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; +#if PY_VERSION_HEX >= 0x03040000 + FILE *f = _Py_fopen_obj(fname.ptr(), "r"); +#elif PY_VERSION_HEX >= 0x03000000 + FILE *f = _Py_fopen(fname.ptr(), "r"); +#else + /* No unicode support in open() :( */ + auto fobj = reinterpret_steal<object>(PyFile_FromString( + const_cast<char *>(fname_str.c_str()), + const_cast<char*>("r"))); + FILE *f = nullptr; + if (fobj) + f = PyFile_AsFile(fobj.ptr()); + closeFile = 0; +#endif + if (!f) { + PyErr_Clear(); + pybind11_fail("File \"" + fname_str + "\" could not be opened!"); + } + + 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); +} + +NAMESPACE_END(pybind11) |