#pragma once #include #include #include "machine.h" // Where a klammer set's Python may speak. Embedded Python's own stdout is // nowhere a user looks: its buffer is never flushed (no Py_Finalize), so on // a pipe or a file a print() vanished, and on a terminal it landed in the // document's stream. Under a command, Eval_python routes it to the engine's // log instead: K_log(level, text) is a builtin every module sees (kutil.msg // uses it), and sys.stdout is replaced by a stream that logs each line at // level 1 -- stderr under -v, silent otherwise, never the document (the // output policy in CLAUDE.md). The switch is ON for the commands // (set_verbose_level) and OFF for the Python binding, where sys.stdout is // the host script's own and must not be touched. void set_python_output_to_log(bool on); class Eval_python { public: static std::regex statement_delimiter; explicit Eval_python(Machine& machine, const Locator& loc); Eval_python(const Eval_python&) = delete; Eval_python& operator=(const Eval_python&) = delete; ~Eval_python(); void add_module_path(const std::string& path); std::vector parse_modules(std::string code); void import_module(const std::string& module_name, bool verify = true); std::string get_result(PyObject* result_object); // The Python exception currently raised (there must be one): clear it, // return the formatted traceback, and keep the exception object in the // slot below. ktext puts the text into the Error it throws; the Python // binding (kpy/) additionally chains the object as the Error's __cause__, // so a script sees the ZeroDivisionError its @eval raised, with its // traceback, and not only a description of it. std::string fetch_python_exception(); // Take ownership of the exception kept by the last fetch (nullptr if // none); the slot is cleared. ktext never calls this: it terminates on // the Error, and the interpreter is torn down with the process. static PyObject* take_last_exception(); std::string eval_expression(const std::string& expression, bool import_modules = true); std::string eval_statements(const std::string& script); std::string eval(std::string code); //std::string eval_katom_list(const katom_iter& begin, const katom_iter& end); std::string eval_katom_list( std::vector& katoms, const std::vector::iterator& begin, const std::vector::iterator& end); Machine m_machine; Locator m_loc; PyObject* m_globals; PyObject* m_locals; static PyObject* s_last_exception; };