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