blob: b7e7e95c906b76c8a4cc7c78db91f9cc0cda8bd8 [file] [log] [blame]
Wenzel Jakob0d3fc352016-07-08 10:52:10 +02001/*
2 pybind11/exec.h: Support for evaluating Python expressions and statements
3 from strings and files
4
5 Copyright (c) 2016 Klemens Morgenstern <klemens.morgenstern@ed-chemnitz.de> and
6 Wenzel Jakob <wenzel.jakob@epfl.ch>
7
8 All rights reserved. Use of this source code is governed by a
9 BSD-style license that can be found in the LICENSE file.
10*/
11
12#pragma once
13
14#pragma once
15
Wenzel Jakobdc13cf02016-07-08 11:07:02 +020016#include "pybind11.h"
Wenzel Jakob0d3fc352016-07-08 10:52:10 +020017
18NAMESPACE_BEGIN(pybind11)
19
20enum eval_mode {
21 /// Evaluate a string containing an isolated expression
22 eval_expr,
23
24 /// Evaluate a string containing a single statement. Returns \c none
25 eval_single_statement,
26
27 /// Evaluate a string containing a sequence of statement. Returns \c none
28 eval_statements
29};
30
31template <eval_mode mode = eval_expr>
Wenzel Jakob464c4352016-07-08 15:06:25 +020032object eval(str expr, object global = object(), object local = object()) {
Wenzel Jakob0d3fc352016-07-08 10:52:10 +020033 if (!global) {
34 global = object(PyEval_GetGlobals(), true);
35 if (!global)
36 global = dict();
37 }
38 if (!local)
39 local = global;
40
Wenzel Jakob464c4352016-07-08 15:06:25 +020041 /* PyRun_String does not accept a PyObject / encoding specifier,
42 this seems to be the only alternative */
43 std::string buffer = "# -*- coding: utf-8 -*-\n" + (std::string) expr;
44
Wenzel Jakob0d3fc352016-07-08 10:52:10 +020045 int start;
46 switch (mode) {
47 case eval_expr: start = Py_eval_input; break;
48 case eval_single_statement: start = Py_single_input; break;
49 case eval_statements: start = Py_file_input; break;
50 default: pybind11_fail("invalid evaluation mode");
51 }
52
Wenzel Jakob464c4352016-07-08 15:06:25 +020053 object result(PyRun_String(buffer.c_str(), start, global.ptr(), local.ptr()), false);
Wenzel Jakob0d3fc352016-07-08 10:52:10 +020054
55 if (!result)
56 throw error_already_set();
57 return result;
58}
59
60template <eval_mode mode = eval_statements>
Wenzel Jakob464c4352016-07-08 15:06:25 +020061object eval_file(str fname, object global = object(), object local = object()) {
Wenzel Jakob0d3fc352016-07-08 10:52:10 +020062 if (!global) {
63 global = object(PyEval_GetGlobals(), true);
64 if (!global)
65 global = dict();
66 }
67 if (!local)
68 local = global;
69
70 int start;
71 switch (mode) {
72 case eval_expr: start = Py_eval_input; break;
73 case eval_single_statement: start = Py_single_input; break;
74 case eval_statements: start = Py_file_input; break;
75 default: pybind11_fail("invalid evaluation mode");
76 }
77
Wenzel Jakob464c4352016-07-08 15:06:25 +020078 int closeFile = 1;
79 std::string fname_str = (std::string) fname;
80#if PY_VERSION_HEX >= 0x03040000
81 FILE *f = _Py_fopen_obj(fname.ptr(), "r");
82#elif PY_VERSION_HEX >= 0x03000000
83 FILE *f = _Py_fopen(fname.ptr(), "r");
84#else
85 /* No unicode support in open() :( */
Wenzel Jakob678d59d2016-07-08 15:14:48 +020086 object fobj(PyFile_FromString(
87 const_cast<char *>(fname_str.c_str()),
88 const_cast<char*>("r")), false);
Wenzel Jakob464c4352016-07-08 15:06:25 +020089 FILE *f = nullptr;
90 if (fobj)
91 f = PyFile_AsFile(fobj.ptr());
92 closeFile = 0;
93#endif
94 if (!f) {
95 PyErr_Clear();
96 pybind11_fail("File \"" + fname_str + "\" could not be opened!");
97 }
Wenzel Jakob0d3fc352016-07-08 10:52:10 +020098
Wenzel Jakob464c4352016-07-08 15:06:25 +020099 object result(PyRun_FileEx(f, fname_str.c_str(), start, global.ptr(),
100 local.ptr(), closeFile),
Wenzel Jakob0d3fc352016-07-08 10:52:10 +0200101 false);
102
103 if (!result)
104 throw error_already_set();
105
106 return result;
107}
108
109NAMESPACE_END(pybind11)