eval.h revision 12391
112837Sgabeblack@google.com/*
212837Sgabeblack@google.com    pybind11/exec.h: Support for evaluating Python expressions and statements
312837Sgabeblack@google.com    from strings and files
412837Sgabeblack@google.com
512837Sgabeblack@google.com    Copyright (c) 2016 Klemens Morgenstern <klemens.morgenstern@ed-chemnitz.de> and
612837Sgabeblack@google.com                       Wenzel Jakob <wenzel.jakob@epfl.ch>
712837Sgabeblack@google.com
812837Sgabeblack@google.com    All rights reserved. Use of this source code is governed by a
912837Sgabeblack@google.com    BSD-style license that can be found in the LICENSE file.
1012837Sgabeblack@google.com*/
1112837Sgabeblack@google.com
1212837Sgabeblack@google.com#pragma once
1312837Sgabeblack@google.com
1412837Sgabeblack@google.com#include "pybind11.h"
1512837Sgabeblack@google.com
1612837Sgabeblack@google.comNAMESPACE_BEGIN(PYBIND11_NAMESPACE)
1712837Sgabeblack@google.com
1812837Sgabeblack@google.comenum eval_mode {
1912837Sgabeblack@google.com    /// Evaluate a string containing an isolated expression
2012837Sgabeblack@google.com    eval_expr,
2112837Sgabeblack@google.com
2212837Sgabeblack@google.com    /// Evaluate a string containing a single statement. Returns \c none
2312837Sgabeblack@google.com    eval_single_statement,
2412837Sgabeblack@google.com
2512837Sgabeblack@google.com    /// Evaluate a string containing a sequence of statement. Returns \c none
2612837Sgabeblack@google.com    eval_statements
2712837Sgabeblack@google.com};
2812837Sgabeblack@google.com
2912837Sgabeblack@google.comtemplate <eval_mode mode = eval_expr>
3012837Sgabeblack@google.comobject eval(str expr, object global = globals(), object local = object()) {
3113059Sgabeblack@google.com    if (!local)
3213203Sgabeblack@google.com        local = global;
3312837Sgabeblack@google.com
3413203Sgabeblack@google.com    /* PyRun_String does not accept a PyObject / encoding specifier,
3512837Sgabeblack@google.com       this seems to be the only alternative */
3612837Sgabeblack@google.com    std::string buffer = "# -*- coding: utf-8 -*-\n" + (std::string) expr;
3712837Sgabeblack@google.com
3812837Sgabeblack@google.com    int start;
3913203Sgabeblack@google.com    switch (mode) {
4013203Sgabeblack@google.com        case eval_expr:             start = Py_eval_input;   break;
4113203Sgabeblack@google.com        case eval_single_statement: start = Py_single_input; break;
4213203Sgabeblack@google.com        case eval_statements:       start = Py_file_input;   break;
4313203Sgabeblack@google.com        default: pybind11_fail("invalid evaluation mode");
4413203Sgabeblack@google.com    }
4513203Sgabeblack@google.com
4613203Sgabeblack@google.com    PyObject *result = PyRun_String(buffer.c_str(), start, global.ptr(), local.ptr());
4713203Sgabeblack@google.com    if (!result)
4813203Sgabeblack@google.com        throw error_already_set();
4913203Sgabeblack@google.com    return reinterpret_steal<object>(result);
5013203Sgabeblack@google.com}
5113203Sgabeblack@google.com
5213203Sgabeblack@google.comtemplate <eval_mode mode = eval_expr, size_t N>
5313203Sgabeblack@google.comobject eval(const char (&s)[N], object global = globals(), object local = object()) {
5413203Sgabeblack@google.com    /* Support raw string literals by removing common leading whitespace */
5513203Sgabeblack@google.com    auto expr = (s[0] == '\n') ? str(module::import("textwrap").attr("dedent")(s))
5613203Sgabeblack@google.com                               : str(s);
5713059Sgabeblack@google.com    return eval<mode>(expr, global, local);
5813059Sgabeblack@google.com}
5913203Sgabeblack@google.com
6013203Sgabeblack@google.cominline void exec(str expr, object global = globals(), object local = object()) {
6113238Sgabeblack@google.com    eval<eval_statements>(expr, global, local);
6213203Sgabeblack@google.com}
6313203Sgabeblack@google.com
6413203Sgabeblack@google.comtemplate <size_t N>
6513238Sgabeblack@google.comvoid exec(const char (&s)[N], object global = globals(), object local = object()) {
6613203Sgabeblack@google.com    eval<eval_statements>(s, global, local);
6713203Sgabeblack@google.com}
6813268Sgabeblack@google.com
6913203Sgabeblack@google.comtemplate <eval_mode mode = eval_statements>
7013203Sgabeblack@google.comobject eval_file(str fname, object global = globals(), object local = object()) {
7113238Sgabeblack@google.com    if (!local)
7213203Sgabeblack@google.com        local = global;
7313203Sgabeblack@google.com
7413203Sgabeblack@google.com    int start;
7513059Sgabeblack@google.com    switch (mode) {
7613048Sgabeblack@google.com        case eval_expr:             start = Py_eval_input;   break;
7712837Sgabeblack@google.com        case eval_single_statement: start = Py_single_input; break;
7812837Sgabeblack@google.com        case eval_statements:       start = Py_file_input;   break;
79        default: pybind11_fail("invalid evaluation mode");
80    }
81
82    int closeFile = 1;
83    std::string fname_str = (std::string) fname;
84#if PY_VERSION_HEX >= 0x03040000
85    FILE *f = _Py_fopen_obj(fname.ptr(), "r");
86#elif PY_VERSION_HEX >= 0x03000000
87    FILE *f = _Py_fopen(fname.ptr(), "r");
88#else
89    /* No unicode support in open() :( */
90    auto fobj = reinterpret_steal<object>(PyFile_FromString(
91        const_cast<char *>(fname_str.c_str()),
92        const_cast<char*>("r")));
93    FILE *f = nullptr;
94    if (fobj)
95        f = PyFile_AsFile(fobj.ptr());
96    closeFile = 0;
97#endif
98    if (!f) {
99        PyErr_Clear();
100        pybind11_fail("File \"" + fname_str + "\" could not be opened!");
101    }
102
103#if PY_VERSION_HEX < 0x03000000 && defined(PYPY_VERSION)
104    PyObject *result = PyRun_File(f, fname_str.c_str(), start, global.ptr(),
105                                  local.ptr());
106    (void) closeFile;
107#else
108    PyObject *result = PyRun_FileEx(f, fname_str.c_str(), start, global.ptr(),
109                                    local.ptr(), closeFile);
110#endif
111
112    if (!result)
113        throw error_already_set();
114    return reinterpret_steal<object>(result);
115}
116
117NAMESPACE_END(PYBIND11_NAMESPACE)
118