120 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C++
		
	
	
| /*
 | |
|     tests/test_eval.cpp -- Usage of eval() and eval_file()
 | |
| 
 | |
|     Copyright (c) 2016 Klemens D. Morgenstern
 | |
| 
 | |
|     All rights reserved. Use of this source code is governed by a
 | |
|     BSD-style license that can be found in the LICENSE file.
 | |
| */
 | |
| 
 | |
| 
 | |
| #include <pybind11/eval.h>
 | |
| 
 | |
| #include "pybind11_tests.h"
 | |
| #include <utility>
 | |
| 
 | |
| TEST_SUBMODULE(eval_, m) {
 | |
|     // test_evals
 | |
| 
 | |
|     auto global = py::dict(py::module_::import("__main__").attr("__dict__"));
 | |
| 
 | |
|     m.def("test_eval_statements", [global]() {
 | |
|         auto local = py::dict();
 | |
|         local["call_test"] = py::cpp_function([&]() -> int {
 | |
|             return 42;
 | |
|         });
 | |
| 
 | |
|         // Regular string literal
 | |
|         py::exec(
 | |
|             "message = 'Hello World!'\n"
 | |
|             "x = call_test()",
 | |
|             global, local
 | |
|         );
 | |
| 
 | |
|         // Multi-line raw string literal
 | |
|         py::exec(R"(
 | |
|             if x == 42:
 | |
|                 print(message)
 | |
|             else:
 | |
|                 raise RuntimeError
 | |
|             )", global, local
 | |
|         );
 | |
|         auto x = local["x"].cast<int>();
 | |
| 
 | |
|         return x == 42;
 | |
|     });
 | |
| 
 | |
|     m.def("test_eval", [global]() {
 | |
|         auto local = py::dict();
 | |
|         local["x"] = py::int_(42);
 | |
|         auto x = py::eval("x", global, local);
 | |
|         return x.cast<int>() == 42;
 | |
|     });
 | |
| 
 | |
|     m.def("test_eval_single_statement", []() {
 | |
|         auto local = py::dict();
 | |
|         local["call_test"] = py::cpp_function([&]() -> int {
 | |
|             return 42;
 | |
|         });
 | |
| 
 | |
|         auto result = py::eval<py::eval_single_statement>("x = call_test()", py::dict(), local);
 | |
|         auto x = local["x"].cast<int>();
 | |
|         return result.is_none() && x == 42;
 | |
|     });
 | |
| 
 | |
|     m.def("test_eval_file", [global](py::str filename) {
 | |
|         auto local = py::dict();
 | |
|         local["y"] = py::int_(43);
 | |
| 
 | |
|         int val_out = 0;
 | |
|         local["call_test2"] = py::cpp_function([&](int value) { val_out = value; });
 | |
| 
 | |
|         auto result = py::eval_file(std::move(filename), global, local);
 | |
|         return val_out == 43 && result.is_none();
 | |
|     });
 | |
| 
 | |
|     m.def("test_eval_failure", []() {
 | |
|         try {
 | |
|             py::eval("nonsense code ...");
 | |
|         } catch (py::error_already_set &) {
 | |
|             return true;
 | |
|         }
 | |
|         return false;
 | |
|     });
 | |
| 
 | |
|     m.def("test_eval_file_failure", []() {
 | |
|         try {
 | |
|             py::eval_file("non-existing file");
 | |
|         } catch (std::exception &) {
 | |
|             return true;
 | |
|         }
 | |
|         return false;
 | |
|     });
 | |
| 
 | |
|     // test_eval_empty_globals
 | |
|     m.def("eval_empty_globals", [](py::object global) {
 | |
|         if (global.is_none())
 | |
|             global = py::dict();
 | |
|         auto int_class = py::eval("isinstance(42, int)", global);
 | |
|         return global;
 | |
|     });
 | |
| 
 | |
|     // test_eval_closure
 | |
|     m.def("test_eval_closure", []() {
 | |
|         py::dict global;
 | |
|         global["closure_value"] = 42;
 | |
|         py::dict local;
 | |
|         local["closure_value"] = 0;
 | |
|         py::exec(R"(
 | |
|             local_value = closure_value
 | |
| 
 | |
|             def func_global():
 | |
|                 return closure_value
 | |
| 
 | |
|             def func_local():
 | |
|                 return local_value
 | |
|             )", global, local);
 | |
|         return std::make_pair(global, local);
 | |
|     });
 | |
| }
 |