This commit is contained in:
PodmogilnyjIvan
2021-12-03 03:34:31 -08:00
commit ff4acf84be
542 changed files with 136810 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* 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.
*/
#pragma once
#include <Python.h>
#include <pangolin/var/varextra.h>
#include <pangolin/python/pyuniqueobj.h>
#include <pangolin/console/ConsoleInterpreter.h>
#include <queue>
#include <set>
#include <thread>
namespace pangolin
{
class PyInterpreter : public ConsoleInterpreter
{
public:
PyInterpreter();
~PyInterpreter() override;
void PushCommand(const std::string &cmd) override;
bool PullLine(ConsoleLine& line) override;
std::vector<std::string> Complete(
const std::string& cmd, int max_options
) override;
static void AttachPrefix(void* data, const std::string& name, VarValueGeneric& var, bool brand_new );
private:
PyObject* pycompleter;
PyObject* pycomplete;
std::string ToString(PyObject* py);
void CheckPrintClearError();
PyUniqueObj EvalExec(const std::string& cmd);
std::queue<ConsoleLine> line_queue;
std::set<std::string> base_prefixes;
};
}

View File

@@ -0,0 +1,178 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* 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.
*/
#pragma once
#include <Python.h>
#include <iomanip>
#include <queue>
#include <structmember.h>
#include <pangolin/var/var.h>
#include <pangolin/console/ConsoleInterpreter.h>
namespace pangolin
{
struct PyPangoIO {
PyObject_HEAD
static PyTypeObject Py_type;
static PyMethodDef Py_methods[];
PyPangoIO(PyTypeObject *type, std::queue<ConsoleLine>& line_queue, ConsoleLineType line_type)
: line_queue(line_queue), line_type(line_type)
{
#if PY_MAJOR_VERSION >= 3
ob_base.ob_refcnt = 1;
ob_base.ob_type = type;
#else
ob_refcnt = 1;
ob_type = type;
#endif
}
static void Py_dealloc(PyPangoIO* self)
{
delete self;
}
static PyObject * Py_new(PyTypeObject */*type*/, PyObject */*args*/, PyObject */*kwds*/)
{
// Failure. Can only new in c++
return 0;
}
static int Py_init(PyPangoIO* /*self*/, PyObject* /*args*/, PyObject* /*kwds*/)
{
return 0;
}
static PyObject* Py_getattr(PyPangoIO *self, char* name)
{
#if PY_MAJOR_VERSION >= 3
PyObject* pystr = PyUnicode_FromString(name);
#else
PyObject* pystr = PyString_FromString(name);
#endif
return PyObject_GenericGetAttr((PyObject*)self, pystr );
}
static int Py_setattr(PyPangoIO *self, char* name, PyObject* val)
{
#if PY_MAJOR_VERSION >= 3
PyObject* pystr = PyUnicode_FromString(name);
#else
PyObject* pystr = PyString_FromString(name);
#endif
return PyObject_GenericSetAttr((PyObject*)self, pystr, val);
}
static PyObject* Py_write(PyPangoIO* self, PyObject *args)
{
const char *text = 0;
if (PyArg_ParseTuple(args, "s", &text)) {
self->buffer += std::string(text);
size_t nl = self->buffer.find_first_of('\n');
while(nl != std::string::npos) {
const std::string line = self->buffer.substr(0,nl);
self->line_queue.push(ConsoleLine(line,self->line_type));
self->buffer = self->buffer.substr(nl+1);
nl = self->buffer.find_first_of('\n');
}
}
Py_RETURN_NONE;
}
std::string buffer;
std::queue<ConsoleLine>& line_queue;
ConsoleLineType line_type;
};
PyMethodDef PyPangoIO::Py_methods[] = {
{"write", (PyCFunction)PyPangoIO::Py_write, METH_VARARGS, "Write to console" },
{NULL, NULL, 0, NULL}
};
#pragma GCC diagnostic push // Ignore python missing initializer warning.
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
PyTypeObject PyPangoIO::Py_type = {
PyVarObject_HEAD_INIT(NULL,0)
"pangolin.PangoIO", /* tp_name*/
sizeof(PyPangoIO), /* tp_basicsize*/
0, /* tp_itemsize*/
(destructor)PyPangoIO::Py_dealloc, /* tp_dealloc*/
0, /* tp_print*/
(getattrfunc)PyPangoIO::Py_getattr, /* tp_getattr*/
(setattrfunc)PyPangoIO::Py_setattr, /* tp_setattr*/
0, /* tp_compare*/
0, /* tp_repr*/
0, /* tp_as_number*/
0, /* tp_as_sequence*/
0, /* tp_as_mapping*/
0, /* tp_hash */
0, /* tp_call*/
0, /* tp_str*/
0, /* tp_getattro*/
0, /* tp_setattro*/
0, /* tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags*/
"PyPangoIO object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
PyPangoIO::Py_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)PyPangoIO::Py_init, /* tp_init */
0, /* tp_alloc */
(newfunc)PyPangoIO::Py_new, /* tp_new */
0, /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
0, /* tp_del */
0 /* tp_version_tag */
};
#pragma GCC diagnostic pop // Return to normal
}

View File

@@ -0,0 +1,40 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* 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.
*/
#pragma once
#include <Python.h>
#include <pangolin/platform.h>
namespace pangolin
{
PANGOLIN_EXPORT
PyMODINIT_FUNC InitPyPangolinModule();
}

View File

@@ -0,0 +1,111 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* 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.
*/
#pragma once
#include <Python.h>
#include <pangolin/platform.h>
namespace pangolin
{
/// Class represents a reference counted PythonObject.
/// PythonObject is appropriately Py_INCREF'd and Py_DECREF'd
class PyUniqueObj
{
public:
inline
PyUniqueObj()
: obj(0)
{
}
/// Assumption: PythonObject has already been appropriately INCREF'd.
inline
PyUniqueObj(PyObject* obj)
: obj(obj)
{
}
inline
PyUniqueObj(const PyUniqueObj& other)
:obj(other.obj)
{
if(obj) Py_INCREF(obj);
}
inline
~PyUniqueObj()
{
if(obj) Py_DECREF(obj);
}
inline
PyUniqueObj(PyUniqueObj&& other)
: obj(other.obj)
{
other.obj = 0;
}
inline
void operator=(PyUniqueObj&& other)
{
Release();
obj = other.obj;
other.obj = 0;
}
inline
void operator=(PyObject* obj)
{
Release();
this->obj = obj;
}
inline
void Release() {
if(obj) {
Py_DECREF(obj);
obj = 0;
}
}
inline
PyObject* operator*() {
return obj;
}
inline
operator PyObject*() {
return obj;
}
private:
PyObject* obj;
};
}

View File

@@ -0,0 +1,271 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* 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.
*/
#pragma once
#include <Python.h>
#include <structmember.h>
#include <iomanip>
#include <pangolin/var/var.h>
#include <pangolin/python/pyuniqueobj.h>
namespace pangolin
{
PyObject* GetPangoVarAsPython(const std::string& name)
{
VarState::VarStoreContainer::iterator i = VarState::I().vars.find(name);
if(i != VarState::I().vars.end()) {
VarValueGeneric* var = i->second;
try{
if( !strcmp(var->TypeId(), typeid(bool).name() ) ) {
const bool val = Var<bool>(*var).Get();
return PyBool_FromLong( val );
}else if( !strcmp(var->TypeId(), typeid(short).name() ) ||
!strcmp(var->TypeId(), typeid(int).name() ) ||
!strcmp(var->TypeId(), typeid(long).name() ) ) {
const long val = Var<long>(*var).Get();
return PyLong_FromLong( val );
}else if( !strcmp(var->TypeId(), typeid(double).name() ) ||
!strcmp(var->TypeId(), typeid(float).name() ) ) {
const double val = Var<double>(*var).Get();
return PyFloat_FromDouble(val);
}else{
const std::string val = var->str->Get();
#if PY_MAJOR_VERSION >= 3
return PyUnicode_FromString(val.c_str());
#else
return PyString_FromString(val.c_str());
#endif
}
}catch(const std::exception&) {
}
}
Py_RETURN_NONE;
}
void SetPangoVarFromPython(const std::string& name, PyObject* val)
{
try{
if (PyFloat_Check(val)) {
pangolin::Var<double> pango_var(name);
pango_var = PyFloat_AsDouble(val);
pango_var.Meta().gui_changed = true;
}else if (PyLong_Check(val)) {
pangolin::Var<long> pango_var(name);
pango_var = PyLong_AsLong(val);
pango_var.Meta().gui_changed = true;
}else if (PyBool_Check(val)) {
pangolin::Var<bool> pango_var(name);
pango_var = (val == Py_True) ? true : false;
pango_var.Meta().gui_changed = true;
}
#if PY_MAJOR_VERSION >= 3
else if (PyUnicode_Check(val)) {
pangolin::Var<std::string> pango_var(name);
pango_var = PyUnicode_AsUTF8(val);
pango_var.Meta().gui_changed = true;
}
#else
else if (PyString_Check(val)) {
pangolin::Var<std::string> pango_var(name);
pango_var = PyString_AsString(val);
pango_var.Meta().gui_changed = true;
} else if (PyInt_Check(val)) {
pangolin::Var<int> pango_var(name);
pango_var = PyInt_AsLong(val);
pango_var.Meta().gui_changed = true;
}
#endif
else {
PyUniqueObj pystr = PyObject_Repr(val);
#if PY_MAJOR_VERSION >= 3
const std::string str = PyUnicode_AsUTF8(pystr);
#else
const std::string str = PyString_AsString(pystr);
#endif
pangolin::Var<std::string> pango_var(name);
pango_var = str;
pango_var.Meta().gui_changed = true;
}
FlagVarChanged();
}catch(const std::exception& e) {
pango_print_error("%s\n", e.what());
}
}
struct PyVar {
static PyTypeObject Py_type;
PyObject_HEAD
PyVar(PyTypeObject *type)
{
#if PY_MAJOR_VERSION >= 3
ob_base.ob_refcnt = 1;
ob_base.ob_type = type;
#else
ob_refcnt = 1;
ob_type = type;
#endif
}
static void Py_dealloc(PyVar* self)
{
delete self;
}
static PyObject * Py_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
{
PyVar* self = new PyVar(type);
return (PyObject *)self;
}
static int Py_init(PyVar *self, PyObject *args, PyObject * /*kwds*/)
{
char* cNamespace = 0;
if (!PyArg_ParseTuple(args, "s", &cNamespace))
return -1;
self->ns = std::string(cNamespace);
return 0;
}
static PyObject* Py_getattr(PyVar *self, char* name)
{
const std::string prefix = self->ns + ".";
const std::string full_name = self->ns.empty() ? name : prefix + std::string(name);
if( !strcmp(name, "__call__") ||
!strcmp(name, "__dict__") ||
!strcmp(name, "__methods__") ||
!strcmp(name, "__class__") )
{
// Default behaviour
#if PY_MAJOR_VERSION >= 3
return PyObject_GenericGetAttr((PyObject*)self, PyUnicode_FromString(name));
#else
return PyObject_GenericGetAttr((PyObject*)self, PyString_FromString(name));
#endif
} else if( !strcmp(name, "__members__") ) {
const int nss = prefix.size();
PyObject* l = PyList_New(0);
for(const std::string& s : VarState::I().var_adds) {
if(!s.compare(0, nss, prefix)) {
size_t dot = s.find_first_of('.', nss);
std::string val = (dot != std::string::npos) ? s.substr(nss, dot - nss) : s.substr(nss);
#if PY_MAJOR_VERSION >= 3
PyList_Append(l, PyUnicode_FromString(val.c_str()));
#else
PyList_Append(l, PyString_FromString(val.c_str()));
#endif
}
}
return l;
}else if( pangolin::VarState::I().Exists(full_name) ) {
return GetPangoVarAsPython(full_name);
}else{
PyVar* obj = (PyVar*)PyVar::Py_new(&PyVar::Py_type,NULL,NULL);
if(obj) {
obj->ns = full_name;
return PyObject_Init((PyObject *)obj,&PyVar::Py_type);
}
return (PyObject *)obj;
}
Py_RETURN_NONE;
}
static int Py_setattr(PyVar *self, char* name, PyObject* val)
{
const std::string full_name = self->ns.empty() ? name : self->ns + "." + std::string(name);
SetPangoVarFromPython(full_name, val);
return 0;
}
std::string ns;
};
// The uninitialized variable can be ignored.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
PyTypeObject PyVar::Py_type = {
PyVarObject_HEAD_INIT(NULL,0)
"pypangolin.Var", /* tp_name*/
sizeof(PyVar), /* tp_basicsize*/
0, /* tp_itemsize*/
(destructor)PyVar::Py_dealloc, /* tp_dealloc*/
0, /* tp_print*/
(getattrfunc)PyVar::Py_getattr, /* tp_getattr*/
(setattrfunc)PyVar::Py_setattr, /* tp_setattr*/
0, /* tp_compare*/
0, /* tp_repr*/
0, /* tp_as_number*/
0, /* tp_as_sequence*/
0, /* tp_as_mapping*/
0, /* tp_hash */
0, /* tp_call*/
0, /* tp_str*/
0, /* tp_getattro*/
0, /* tp_setattro*/
0, /* tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags*/
"PyVar object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)PyVar::Py_init, /* tp_init */
0, /* tp_alloc */
(newfunc)PyVar::Py_new, /* tp_new */
0, /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
0, /* tp_del */
0 /* tp_version_tag */
};
#pragma GCC diagnostic pop
}