This repository was archived by the owner on Jun 25, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 95
Expand file tree
/
Copy pathpython_interpreter.cc
More file actions
155 lines (144 loc) · 5.13 KB
/
python_interpreter.cc
File metadata and controls
155 lines (144 loc) · 5.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include "python_interpreter.h"
#include "notebook.h"
#include "config.h"
#include <iostream>
#include <pygobject.h>
#include "menu.h"
#include "directories.h"
#include "terminal.h"
static wchar_t* DecodeLocale(const char* arg, size_t *size)
{
#ifndef PY_VERSION_HEX
#error Python not included
#elif PY_VERSION_HEX < 0x03050000
return _Py_char2wchar(arg, size);
#else
return Py_DecodeLocale(arg, size);
#endif
}
inline pybind11::module pyobject_from_gobj(gpointer ptr){
auto obj=G_OBJECT(ptr);
if(obj)
return pybind11::reinterpret_steal<pybind11::module>(pygobject_new(obj));
return pybind11::reinterpret_steal<pybind11::module>(Py_None);
}
Python::Interpreter::Interpreter(){
auto init_juci_api=[](){
auto module = pybind11::reinterpret_steal<pybind11::module>(pygobject_init(-1,-1,-1));
pybind11::module api("jucpp","Python bindings for juCi++");
api
.def("get_juci_home",[](){return Config::get().home_juci_path.string();})
.def("get_plugin_folder",[](){return Config::get().python.plugin_directory;});
api
.def_submodule("editor")
.def("get_current_gtk_source_view",[](){
auto view=Notebook::get().get_current_view();
if(view)
return pyobject_from_gobj(view->gobj());
return pybind11::reinterpret_steal<pybind11::module>(Py_None);
})
.def("get_file_path",[](){
auto view=Notebook::get().get_current_view();
if(view)
return view->file_path.string();
return std::string();
});
api
.def("get_gio_plugin_menu",[](){
if(!Menu::get().plugin_menu){
Menu::get().plugin_menu=Gio::Menu::create();
Menu::get().plugin_menu->append("<empty>");
Menu::get().window_menu->append_submenu("_Plugins",Menu::get().plugin_menu);
}
return pyobject_from_gobj(Menu::get().plugin_menu->gobj());
})
.def("get_gio_window_menu",[](){return pyobject_from_gobj(Menu::get().window_menu->gobj());})
.def("get_gio_juci_menu",[](){return pyobject_from_gobj(Menu::get().juci_menu->gobj());})
.def("get_gtk_notebook",[](){return pyobject_from_gobj(Notebook::get().gobj());})
.def_submodule("terminal")
.def("get_gtk_text_view",[](){return pyobject_from_gobj(Terminal::get().gobj());})
.def("println", [](const std::string &message){ Terminal::get().print(message +"\n"); });
api.def_submodule("directories")
.def("get_gtk_treeview",[](){return pyobject_from_gobj(Directories::get().gobj());})
.def("open",[](const std::string &directory){Directories::get().open(directory);})
.def("update",[](){Directories::get().update();});
return api.ptr();
};
PyImport_AppendInittab("jucipp", init_juci_api);
Config::get().load();
configure_path();
Py_Initialize();
#ifdef _WIN32
long long unsigned size = 0L;
#else
long unsigned size = 0L;
#endif
argv=DecodeLocale("",&size);
PySys_SetArgv(0,&argv);
boost::filesystem::directory_iterator end_it;
for(boost::filesystem::directory_iterator it(Config::get().python.plugin_directory);it!=end_it;it++){
auto module_name=it->path().stem().string();
if(module_name.empty())
continue;
auto is_directory=boost::filesystem::is_directory(it->path());
auto has_py_extension=it->path().extension()==".py";
auto is_pycache=module_name=="__pycache__";
if((is_directory && !is_pycache)||has_py_extension){
try {
pybind11::module::import(module_name.c_str());
} catch (pybind11::error_already_set &error) {
Terminal::get().print("Error loading plugin `"+module_name+"`:\n"+error.what()+"\n");
}
}
}
auto sys=find_module("sys");
if(sys){
auto exc_func=[](pybind11::object type,pybind11::object value,pybind11::object traceback){
std::cerr << "ERROR FUNCTION";
};
sys.attr("excepthook")=pybind11::cpp_function(exc_func);
} else {
std::cerr << "Failed to set exception hook\n";
}
}
pybind11::module Python::Interpreter::find_module(const std::string &module_name){
return pybind11::reinterpret_borrow<pybind11::module>(PyImport_AddModule(module_name.c_str()));
}
pybind11::module Python::Interpreter::reload(pybind11::module &module){
auto reload=pybind11::reinterpret_steal<pybind11::module>(PyImport_ReloadModule(module.ptr()));
if(!reload)
throw pybind11::error_already_set();
return reload;
}
void Python::Interpreter::configure_path(){
const std::vector<boost::filesystem::path> python_path = {
"/usr/lib/python3.6",
"/usr/lib/python3.6/lib-dynload",
"/usr/lib/python3.6/site-packages",
Config::get().python.site_packages,
Config::get().python.plugin_directory
};
std::wstring sys_path;
for(auto &path:python_path){
if(path.empty())
continue;
if(!sys_path.empty()){
#ifdef _WIN32
sys_path += ';';
#else
sys_path += ':';
#endif
}
sys_path += path.generic_wstring();
}
Py_SetPath(sys_path.c_str());
}
Python::Interpreter::~Interpreter(){
if(Py_IsInitialized())
Py_Finalize();
if(error())
std::cerr << pybind11::error_already_set().what() << std::endl;
}
pybind11::object Python::Interpreter::error(){
return pybind11::reinterpret_borrow<pybind11::object>(PyErr_Occurred());
}