eval.h revision 12037:d28054ac6ec9
1/*
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
16#include "pybind11.h"
17
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>
32object eval(str expr, object global = object(), object local = object()) {
33    if (!global) {
34        global = reinterpret_borrow<object>(PyEval_GetGlobals());
35        if (!global)
36            global = dict();
37    }
38    if (!local)
39        local = global;
40
41    /* 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
45    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
53    PyObject *result = PyRun_String(buffer.c_str(), start, global.ptr(), local.ptr());
54    if (!result)
55        throw error_already_set();
56    return reinterpret_steal<object>(result);
57}
58
59template <eval_mode mode = eval_statements>
60object eval_file(str fname, object global = object(), object local = object()) {
61    if (!global) {
62        global = reinterpret_borrow<object>(PyEval_GetGlobals());
63        if (!global)
64            global = dict();
65    }
66    if (!local)
67        local = global;
68
69    int start;
70    switch (mode) {
71        case eval_expr:             start = Py_eval_input;   break;
72        case eval_single_statement: start = Py_single_input; break;
73        case eval_statements:       start = Py_file_input;   break;
74        default: pybind11_fail("invalid evaluation mode");
75    }
76
77    int closeFile = 1;
78    std::string fname_str = (std::string) fname;
79#if PY_VERSION_HEX >= 0x03040000
80    FILE *f = _Py_fopen_obj(fname.ptr(), "r");
81#elif PY_VERSION_HEX >= 0x03000000
82    FILE *f = _Py_fopen(fname.ptr(), "r");
83#else
84    /* No unicode support in open() :( */
85    auto fobj = reinterpret_steal<object>(PyFile_FromString(
86        const_cast<char *>(fname_str.c_str()),
87        const_cast<char*>("r")));
88    FILE *f = nullptr;
89    if (fobj)
90        f = PyFile_AsFile(fobj.ptr());
91    closeFile = 0;
92#endif
93    if (!f) {
94        PyErr_Clear();
95        pybind11_fail("File \"" + fname_str + "\" could not be opened!");
96    }
97
98#if PY_VERSION_HEX < 0x03000000 && defined(PYPY_VERSION)
99    PyObject *result = PyRun_File(f, fname_str.c_str(), start, global.ptr(),
100                                  local.ptr());
101    (void) closeFile;
102#else
103    PyObject *result = PyRun_FileEx(f, fname_str.c_str(), start, global.ptr(),
104                                    local.ptr(), closeFile);
105#endif
106
107    if (!result)
108        throw error_already_set();
109    return reinterpret_steal<object>(result);
110}
111
112NAMESPACE_END(pybind11)
113