111986Sandreas.sandberg@arm.com/* 211986Sandreas.sandberg@arm.com pybind11/exec.h: Support for evaluating Python expressions and statements 311986Sandreas.sandberg@arm.com from strings and files 411986Sandreas.sandberg@arm.com 511986Sandreas.sandberg@arm.com Copyright (c) 2016 Klemens Morgenstern <klemens.morgenstern@ed-chemnitz.de> and 611986Sandreas.sandberg@arm.com Wenzel Jakob <wenzel.jakob@epfl.ch> 711986Sandreas.sandberg@arm.com 811986Sandreas.sandberg@arm.com All rights reserved. Use of this source code is governed by a 911986Sandreas.sandberg@arm.com BSD-style license that can be found in the LICENSE file. 1011986Sandreas.sandberg@arm.com*/ 1111986Sandreas.sandberg@arm.com 1211986Sandreas.sandberg@arm.com#pragma once 1311986Sandreas.sandberg@arm.com 1411986Sandreas.sandberg@arm.com#include "pybind11.h" 1511986Sandreas.sandberg@arm.com 1612391Sjason@lowepower.comNAMESPACE_BEGIN(PYBIND11_NAMESPACE) 1711986Sandreas.sandberg@arm.com 1811986Sandreas.sandberg@arm.comenum eval_mode { 1911986Sandreas.sandberg@arm.com /// Evaluate a string containing an isolated expression 2011986Sandreas.sandberg@arm.com eval_expr, 2111986Sandreas.sandberg@arm.com 2211986Sandreas.sandberg@arm.com /// Evaluate a string containing a single statement. Returns \c none 2311986Sandreas.sandberg@arm.com eval_single_statement, 2411986Sandreas.sandberg@arm.com 2511986Sandreas.sandberg@arm.com /// Evaluate a string containing a sequence of statement. Returns \c none 2611986Sandreas.sandberg@arm.com eval_statements 2711986Sandreas.sandberg@arm.com}; 2811986Sandreas.sandberg@arm.com 2911986Sandreas.sandberg@arm.comtemplate <eval_mode mode = eval_expr> 3012391Sjason@lowepower.comobject eval(str expr, object global = globals(), object local = object()) { 3111986Sandreas.sandberg@arm.com if (!local) 3211986Sandreas.sandberg@arm.com local = global; 3311986Sandreas.sandberg@arm.com 3411986Sandreas.sandberg@arm.com /* PyRun_String does not accept a PyObject / encoding specifier, 3511986Sandreas.sandberg@arm.com this seems to be the only alternative */ 3611986Sandreas.sandberg@arm.com std::string buffer = "# -*- coding: utf-8 -*-\n" + (std::string) expr; 3711986Sandreas.sandberg@arm.com 3811986Sandreas.sandberg@arm.com int start; 3911986Sandreas.sandberg@arm.com switch (mode) { 4011986Sandreas.sandberg@arm.com case eval_expr: start = Py_eval_input; break; 4111986Sandreas.sandberg@arm.com case eval_single_statement: start = Py_single_input; break; 4211986Sandreas.sandberg@arm.com case eval_statements: start = Py_file_input; break; 4311986Sandreas.sandberg@arm.com default: pybind11_fail("invalid evaluation mode"); 4411986Sandreas.sandberg@arm.com } 4511986Sandreas.sandberg@arm.com 4611986Sandreas.sandberg@arm.com PyObject *result = PyRun_String(buffer.c_str(), start, global.ptr(), local.ptr()); 4711986Sandreas.sandberg@arm.com if (!result) 4811986Sandreas.sandberg@arm.com throw error_already_set(); 4911986Sandreas.sandberg@arm.com return reinterpret_steal<object>(result); 5011986Sandreas.sandberg@arm.com} 5111986Sandreas.sandberg@arm.com 5212391Sjason@lowepower.comtemplate <eval_mode mode = eval_expr, size_t N> 5312391Sjason@lowepower.comobject eval(const char (&s)[N], object global = globals(), object local = object()) { 5412391Sjason@lowepower.com /* Support raw string literals by removing common leading whitespace */ 5512391Sjason@lowepower.com auto expr = (s[0] == '\n') ? str(module::import("textwrap").attr("dedent")(s)) 5612391Sjason@lowepower.com : str(s); 5712391Sjason@lowepower.com return eval<mode>(expr, global, local); 5812391Sjason@lowepower.com} 5912391Sjason@lowepower.com 6012391Sjason@lowepower.cominline void exec(str expr, object global = globals(), object local = object()) { 6112391Sjason@lowepower.com eval<eval_statements>(expr, global, local); 6212391Sjason@lowepower.com} 6312391Sjason@lowepower.com 6412391Sjason@lowepower.comtemplate <size_t N> 6512391Sjason@lowepower.comvoid exec(const char (&s)[N], object global = globals(), object local = object()) { 6612391Sjason@lowepower.com eval<eval_statements>(s, global, local); 6712391Sjason@lowepower.com} 6812391Sjason@lowepower.com 6911986Sandreas.sandberg@arm.comtemplate <eval_mode mode = eval_statements> 7012391Sjason@lowepower.comobject eval_file(str fname, object global = globals(), object local = object()) { 7111986Sandreas.sandberg@arm.com if (!local) 7211986Sandreas.sandberg@arm.com local = global; 7311986Sandreas.sandberg@arm.com 7411986Sandreas.sandberg@arm.com int start; 7511986Sandreas.sandberg@arm.com switch (mode) { 7611986Sandreas.sandberg@arm.com case eval_expr: start = Py_eval_input; break; 7711986Sandreas.sandberg@arm.com case eval_single_statement: start = Py_single_input; break; 7811986Sandreas.sandberg@arm.com case eval_statements: start = Py_file_input; break; 7911986Sandreas.sandberg@arm.com default: pybind11_fail("invalid evaluation mode"); 8011986Sandreas.sandberg@arm.com } 8111986Sandreas.sandberg@arm.com 8211986Sandreas.sandberg@arm.com int closeFile = 1; 8311986Sandreas.sandberg@arm.com std::string fname_str = (std::string) fname; 8411986Sandreas.sandberg@arm.com#if PY_VERSION_HEX >= 0x03040000 8511986Sandreas.sandberg@arm.com FILE *f = _Py_fopen_obj(fname.ptr(), "r"); 8611986Sandreas.sandberg@arm.com#elif PY_VERSION_HEX >= 0x03000000 8711986Sandreas.sandberg@arm.com FILE *f = _Py_fopen(fname.ptr(), "r"); 8811986Sandreas.sandberg@arm.com#else 8911986Sandreas.sandberg@arm.com /* No unicode support in open() :( */ 9011986Sandreas.sandberg@arm.com auto fobj = reinterpret_steal<object>(PyFile_FromString( 9111986Sandreas.sandberg@arm.com const_cast<char *>(fname_str.c_str()), 9211986Sandreas.sandberg@arm.com const_cast<char*>("r"))); 9311986Sandreas.sandberg@arm.com FILE *f = nullptr; 9411986Sandreas.sandberg@arm.com if (fobj) 9511986Sandreas.sandberg@arm.com f = PyFile_AsFile(fobj.ptr()); 9611986Sandreas.sandberg@arm.com closeFile = 0; 9711986Sandreas.sandberg@arm.com#endif 9811986Sandreas.sandberg@arm.com if (!f) { 9911986Sandreas.sandberg@arm.com PyErr_Clear(); 10011986Sandreas.sandberg@arm.com pybind11_fail("File \"" + fname_str + "\" could not be opened!"); 10111986Sandreas.sandberg@arm.com } 10211986Sandreas.sandberg@arm.com 10312037Sandreas.sandberg@arm.com#if PY_VERSION_HEX < 0x03000000 && defined(PYPY_VERSION) 10412037Sandreas.sandberg@arm.com PyObject *result = PyRun_File(f, fname_str.c_str(), start, global.ptr(), 10512037Sandreas.sandberg@arm.com local.ptr()); 10612037Sandreas.sandberg@arm.com (void) closeFile; 10712037Sandreas.sandberg@arm.com#else 10811986Sandreas.sandberg@arm.com PyObject *result = PyRun_FileEx(f, fname_str.c_str(), start, global.ptr(), 10911986Sandreas.sandberg@arm.com local.ptr(), closeFile); 11012037Sandreas.sandberg@arm.com#endif 11112037Sandreas.sandberg@arm.com 11211986Sandreas.sandberg@arm.com if (!result) 11311986Sandreas.sandberg@arm.com throw error_already_set(); 11411986Sandreas.sandberg@arm.com return reinterpret_steal<object>(result); 11511986Sandreas.sandberg@arm.com} 11611986Sandreas.sandberg@arm.com 11712391Sjason@lowepower.comNAMESPACE_END(PYBIND11_NAMESPACE) 118