Skip to content
This repository has been archived by the owner on Jun 25, 2020. It is now read-only.

Commit

Permalink
feature: Update pybind11 to latest version
Browse files Browse the repository at this point in the history
  • Loading branch information
Jørgen Lien Sellæg authored and zalox committed Feb 28, 2017
1 parent 868f4c6 commit bb6b4aa
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 175 deletions.
4 changes: 2 additions & 2 deletions ci/update_ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ function windows () {
if [ "$PLATFORM" == "x86" ]; then
arch=i686
fi
sh -c "pacman -S --noconfirm git mingw-w64-${arch}-cmake make mingw-w64-${arch}-toolchain mingw-w64-${arch}-clang mingw-w64-${arch}-gtkmm3 mingw-w64-${arch}-gtksourceviewmm3 mingw-w64-${arch}-boost mingw-w64-${arch}-aspell mingw-w64-${arch}-aspell-en mingw-w64-${arch}-libgit2"
sh -c "pacman -S --noconfirm git mingw-w64-${arch}-pygobject-devel mingw-w64-${arch}-cmake make mingw-w64-${arch}-toolchain mingw-w64-${arch}-clang mingw-w64-${arch}-gtkmm3 mingw-w64-${arch}-gtksourceviewmm3 mingw-w64-${arch}-boost mingw-w64-${arch}-aspell mingw-w64-${arch}-aspell-en mingw-w64-${arch}-libgit2"
}

if [ "$TRAVIS_OS_NAME" == "" ]; then
TRAVIS_OS_NAME=windows
fi

$TRAVIS_OS_NAME
$TRAVIS_OS_NAME
2 changes: 1 addition & 1 deletion docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ make install

Install dependencies (replace `x86_64` with `i686` for 32-bit MSYS2 installs):
```sh
pacman -S git mingw-w64-x86_64-cmake make mingw-w64-x86_64-toolchain mingw-w64-x86_64-clang mingw-w64-x86_64-gtkmm3 mingw-w64-x86_64-gtksourceviewmm3 mingw-w64-x86_64-boost mingw-w64-x86_64-aspell mingw-w64-x86_64-aspell-en mingw-w64-x86_64-libgit2 mingw-w64-x86_64-universal-ctags-git
pacman -S git mingw-w64-x86_64-cmake make mingw-w64-x86_64-toolchain mingw-w64-x86_64-clang mingw-w64-x86_64-gtkmm3 mingw-w64-x86_64-gtksourceviewmm3 mingw-w64-x86_64-boost mingw-w64-x86_64-aspell mingw-w64-x86_64-aspell-en mingw-w64-x86_64-gobject-introspection mingw-w64-x86_64-pygobject-devel mingw-w64-x86_64-python3-gobject mingw-w64-x86_64-libgit2 mingw-w64-x86_64-universal-ctags-git
```

Note that juCi++ must be built and run in a MinGW Shell (for instance MinGW-w64 Win64 Shell).
Expand Down
2 changes: 1 addition & 1 deletion pybind11
Submodule pybind11 updated 184 files
6 changes: 3 additions & 3 deletions src/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ void Config::find_or_create_config_files() {
auto config_json = config_dir/"config.json";

boost::filesystem::create_directories(config_dir); // io exp captured by calling method
boost::filesystem::create_directories(home/"plugins");
boost::filesystem::create_directories(home_juci_path/"plugins");

if (!boost::filesystem::exists(config_json))
filesystem::write(config_json, default_config_file);
Expand Down Expand Up @@ -118,8 +118,8 @@ void Config::retrieve_config() {
}
}
#endif
python.plugin_directory=cfg.get<std::string>("python.plugin_directory",(home/"plugins").string());
python.site_packages=cfg.get<std::string>("python.site_packages","/usr/lib/python3.5/site-packages");
python.plugin_directory=cfg.get<std::string>("python.plugin_directory",(home_juci_path/"plugins").string());
python.site_packages=cfg.get<std::string>("python.site_packages","");
}

bool Config::add_missing_nodes(const boost::property_tree::ptree &default_cfg, std::string parent_path) {
Expand Down
2 changes: 2 additions & 0 deletions src/menu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,8 @@ void Menu::set_keys() {
}
}

Menu::Menu() : plugin_menu(nullptr) {}

void Menu::build() {
try {
builder = Gtk::Builder::create_from_string(menu_xml);
Expand Down
5 changes: 2 additions & 3 deletions src/menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
#include <gtkmm.h>

class Menu {
Menu() {}
private:
Menu();
public:
static Menu &get() {
static Menu singleton;
Expand All @@ -21,11 +22,9 @@ class Menu {

Glib::RefPtr<Gio::Menu> juci_menu;
Glib::RefPtr<Gio::Menu> window_menu;

std::unique_ptr<Gtk::Menu> right_click_line_menu;
std::unique_ptr<Gtk::Menu> right_click_selected_menu;
Glib::RefPtr<Gio::Menu> plugin_menu;

private:
Glib::RefPtr<Gtk::Builder> builder;
};
Expand Down
180 changes: 65 additions & 115 deletions src/python_interpreter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,25 @@ static wchar_t* DecodeLocale(const char* arg, size_t *size)
inline pybind11::module pyobject_from_gobj(gpointer ptr){
auto obj=G_OBJECT(ptr);
if(obj)
return pybind11::module(pygobject_new(obj), false);
return pybind11::module(Py_None, false);
return pybind11::reinterpret_steal<pybind11::module>(pygobject_new(obj));
return pybind11::reinterpret_steal<pybind11::module>(Py_None);
}

Python::Interpreter::Interpreter(){
#ifdef _WIN32
auto root_path=Config::get().terminal.msys2_mingw_path;
append_path(root_path/"include/python3.5m");
append_path(root_path/"lib/python3.5");
long long unsigned size = 0L;
#else
long unsigned size = 0L;
#endif

auto init_juci_api=[](){
pybind11::module(pygobject_init(-1,-1,-1),false);
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().juci_home_path().string();})
.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::module(Py_None,false);
return pybind11::reinterpret_steal<pybind11::module>(Py_None);
})
.def("get_file_path",[](){
auto view=Notebook::get().get_current_view();
Expand All @@ -55,13 +48,12 @@ Python::Interpreter::Interpreter(){
});
api
.def("get_gio_plugin_menu",[](){
auto &plugin_menu=Menu::get().plugin_menu;
if(!plugin_menu){
plugin_menu=Gio::Menu::create();
plugin_menu->append("<empty>");
Menu::get().window_menu->append_submenu("_Plugins",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(plugin_menu->gobj());
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());})
Expand All @@ -76,129 +68,87 @@ Python::Interpreter::Interpreter(){
return api.ptr();
};
PyImport_AppendInittab("jucipp", init_juci_api);

Config::get().load();
auto plugin_path=Config::get().python.plugin_directory;
add_path(Config::get().python.site_packages);
add_path(plugin_path);
configure_path();
Py_Initialize();
#ifdef _WIN32
long long unsigned size = 0L;
#else
long unsigned size = 0L;
#endif
argv=DecodeLocale("",&size);
PySys_SetArgv(0,&argv);
auto sys=get_loaded_module("sys");
auto exc_func=[](pybind11::object type,pybind11::object value,pybind11::object traceback){
if(!given_exception_matches(type,PyExc_SyntaxError))
Terminal::get().print(Error(type,value,traceback),true);
else
Terminal::get().print(SyntaxError(type,value,traceback),true);
};
sys.attr("excepthook")=pybind11::cpp_function(exc_func);
boost::filesystem::directory_iterator end_it;
for(boost::filesystem::directory_iterator it(plugin_path);it!=end_it;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())
break;
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){
auto module=import(module_name);
if(!module){
auto msg="Error loading plugin `"+module_name+"`:\n";
auto err=std::string(Error());
Terminal::get().print(msg+err+"\n");
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::get_loaded_module(const std::string &module_name){
return pybind11::module(PyImport_AddModule(module_name.c_str()), true);
}

pybind11::module Python::import(const std::string &module_name){
return pybind11::module(PyImport_ImportModule(module_name.c_str()), false);
}

pybind11::module Python::reload(pybind11::module &module){
return pybind11::module(PyImport_ReloadModule(module.ptr()),false);
pybind11::module Python::Interpreter::find_module(const std::string &module_name){
return pybind11::reinterpret_borrow<pybind11::module>(PyImport_AddModule(module_name.c_str()));
}

Python::SyntaxError::SyntaxError(pybind11::object type,pybind11::object value,pybind11::object traceback)
: Error(type,value,traceback){}

Python::Error::Error(pybind11::object type,pybind11::object value,pybind11::object traceback){
exp=type;
val=value;
trace=traceback;
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::add_path(const boost::filesystem::path &path){
if(path.empty())
return;
std::wstring sys_path(Py_GetPath());
if(!sys_path.empty())
#ifdef _WIN32
sys_path += ';';
#else
sys_path += ':';
#endif
sys_path += path.generic_wstring();
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(){
auto err=Error();
if(Py_IsInitialized())
Py_Finalize();
if(err)
std::cerr << std::string(err) << std::endl;
if(error())
std::cerr << pybind11::error_already_set().what() << std::endl;
}

pybind11::object Python::error_occured(){
return pybind11::object(PyErr_Occurred(),true);
pybind11::object Python::Interpreter::error(){
return pybind11::reinterpret_borrow<pybind11::object>(PyErr_Occurred());
}

bool Python::thrown_exception_matches(pybind11::handle exception_type){
return PyErr_ExceptionMatches(exception_type.ptr());
}

bool Python::given_exception_matches(const pybind11::object &exception, pybind11::handle exception_type){
return PyErr_GivenExceptionMatches(exception.ptr(),exception_type.ptr());
}

Python::Error::Error(){
if(error_occured()){
try{
PyErr_Fetch(&exp.ptr(),&val.ptr(),&trace.ptr());
PyErr_NormalizeException(&exp.ptr(),&val.ptr(),&trace.ptr());
}catch(const std::exception &e) {
Terminal::get().print(e.what(),true);
}
}
}

Python::Error::operator std::string(){
return std::string(exp.str())+"\n"+std::string(val.str())+"\n";
}

Python::SyntaxError::SyntaxError():Error(){
if(val){
_Py_IDENTIFIER(msg);
_Py_IDENTIFIER(lineno);
_Py_IDENTIFIER(offset);
_Py_IDENTIFIER(text);
exp=std::string(pybind11::str(_PyObject_GetAttrId(val.ptr(),&PyId_msg),false));
text=std::string(pybind11::str(_PyObject_GetAttrId(val.ptr(),&PyId_text),false));
pybind11::object py_line_number(_PyObject_GetAttrId(val.ptr(),&PyId_lineno),false);
pybind11::object py_line_offset(_PyObject_GetAttrId(val.ptr(),&PyId_offset),false);
line_number=pybind11::cast<int>(py_line_number);
line_offset=pybind11::cast<int>(py_line_offset);
}
}

Python::SyntaxError::operator std::string(){
return exp+" ("+std::to_string(line_number)+":"+std::to_string(line_offset)+"):\n"+text;
}

Python::Error::operator bool(){
return exp || trace || val;
}
37 changes: 6 additions & 31 deletions src/python_interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,48 +7,23 @@
#include <iostream>
using namespace std;

class Python {
public:
namespace Python {
class Interpreter {
public:
pybind11::module static find_module(const std::string &module_name);
pybind11::module static reload(pybind11::module &module);
pybind11::object static error();
private:
Interpreter();
~Interpreter();
wchar_t *argv;
void add_path(const boost::filesystem::path &path);
void configure_path();
public:
static Interpreter& get(){
static Interpreter singleton;
return singleton;
}
};

pybind11::module static get_loaded_module(const std::string &module_name);
pybind11::module static import(const std::string &module_name);
pybind11::module static reload(pybind11::module &module);

class Error {
public:
Error();
Error(pybind11::object type,pybind11::object value,pybind11::object traceback);
operator std::string();
operator bool();
pybind11::object exp, val, trace;
};

class SyntaxError : public Error{
public:
SyntaxError();
SyntaxError(pybind11::object type,pybind11::object value,pybind11::object traceback);
operator std::string();
std::string exp, text;
int line_number, line_offset;
};

bool static thrown_exception_matches(pybind11::handle exception_type);
bool static given_exception_matches(const pybind11::object &exception,pybind11::handle exception_type);

private:
pybind11::object static error_occured();
};

#endif // JUCI_PYTHON_INTERPRETER_H_
Loading

0 comments on commit bb6b4aa

Please sign in to comment.