diff options
author | Miodrag Milanovic <mmicko@gmail.com> | 2018-06-28 17:56:44 +0200 |
---|---|---|
committer | Miodrag Milanovic <mmicko@gmail.com> | 2018-06-28 17:57:26 +0200 |
commit | 1676b285ae726eb858d4d7ed089496133ce3de4b (patch) | |
tree | b7c2a9a59c2a9a0377d266567e545f5a1c23ae58 /3rdparty/python-console/modified/pyinterpreter.cc | |
parent | 2037fff7426e252a8692b971f88689c1dd8c03e8 (diff) | |
download | nextpnr-1676b285ae726eb858d4d7ed089496133ce3de4b.tar.gz nextpnr-1676b285ae726eb858d4d7ed089496133ce3de4b.tar.bz2 nextpnr-1676b285ae726eb858d4d7ed089496133ce3de4b.zip |
adapted python-console for easier use
Diffstat (limited to '3rdparty/python-console/modified/pyinterpreter.cc')
-rw-r--r-- | 3rdparty/python-console/modified/pyinterpreter.cc | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/3rdparty/python-console/modified/pyinterpreter.cc b/3rdparty/python-console/modified/pyinterpreter.cc new file mode 100644 index 00000000..ee8c4aa8 --- /dev/null +++ b/3rdparty/python-console/modified/pyinterpreter.cc @@ -0,0 +1,155 @@ +/** +python-console +Copyright (C) 2014 Alex Tsui + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#include "pyinterpreter.h" +#include <Python.h> +#include <iostream> +#include <map> +#include <memory> +#include "pyredirector.h" + +static PyThreadState *MainThreadState = NULL; + +static PyThreadState *m_threadState = NULL; +static PyObject *glb = NULL; +static PyObject *loc = NULL; + +static std::list<std::string> m_suggestions; + +template <typename... Args> std::string string_format(const std::string &format, Args... args) +{ + size_t size = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0' + std::unique_ptr<char[]> buf(new char[size]); + std::snprintf(buf.get(), size, format.c_str(), args...); + return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside +} + +std::string pyinterpreter_execute(const std::string &command, int *errorCode) +{ + PyEval_AcquireThread(m_threadState); + *errorCode = 0; + + PyObject *py_result; + PyObject *dum; + std::string res; + py_result = Py_CompileString(command.c_str(), "<stdin>", Py_single_input); + if (py_result == 0) { + if (PyErr_Occurred()) { + *errorCode = 1; + PyErr_Print(); + res = redirector_take_output(m_threadState); + } + + PyEval_ReleaseThread(m_threadState); + return res; + } + dum = PyEval_EvalCode(py_result, glb, loc); + Py_XDECREF(dum); + Py_XDECREF(py_result); + if (PyErr_Occurred()) { + *errorCode = 1; + PyErr_Print(); + } + + res = redirector_take_output(m_threadState); + + PyEval_ReleaseThread(m_threadState); + return res; +} + +const std::list<std::string> &pyinterpreter_suggest(const std::string &hint) +{ + PyEval_AcquireThread(m_threadState); + m_suggestions.clear(); + int i = 0; + std::string command = string_format("sys.completer.complete('%s', %d)\n", hint.c_str(), i); + std::string res; + do { + PyObject *py_result; + PyObject *dum; + py_result = Py_CompileString(command.c_str(), "<stdin>", Py_single_input); + dum = PyEval_EvalCode(py_result, glb, loc); + Py_XDECREF(dum); + Py_XDECREF(py_result); + res = redirector_take_output(m_threadState); + + ++i; + command = string_format("sys.completer.complete('%s', %d)\n", hint.c_str(), i); + if (res.size()) { + // throw away the newline + res = res.substr(1, res.size() - 3); + m_suggestions.push_back(res); + } + } while (res.size()); + + PyEval_ReleaseThread(m_threadState); + return m_suggestions; +} + +void pyinterpreter_preinit() +{ + m_suggestions.clear(); + inittab_redirector(); +} + +void pyinterpreter_initialize() +{ + PyEval_InitThreads(); + MainThreadState = PyEval_SaveThread(); + PyEval_AcquireThread(MainThreadState); + m_threadState = Py_NewInterpreter(); + + PyObject *module = PyImport_ImportModule("__main__"); + loc = glb = PyModule_GetDict(module); + + PyRun_SimpleString("import sys\n" + "import redirector\n" + "sys.path.insert(0, \".\")\n" // add current path + "sys.stdout = redirector.redirector()\n" + "sys.stderr = sys.stdout\n" + "import rlcompleter\n" + "sys.completer = rlcompleter.Completer()\n"); + + PyEval_ReleaseThread(m_threadState); +} + +void pyinterpreter_finalize() +{ + m_suggestions.clear(); + + PyEval_AcquireThread(m_threadState); + Py_EndInterpreter(m_threadState); + PyEval_ReleaseLock(); + + PyEval_RestoreThread(MainThreadState); +} + +void pyinterpreter_aquire() +{ + PyEval_AcquireThread(m_threadState); +} + +void pyinterpreter_release() +{ + PyEval_ReleaseThread(m_threadState); +} |