Something went wrong on our end
-
Studer Gabriel authoredStuder Gabriel authored
python_interpreter.cc 5.37 KiB
//------------------------------------------------------------------------------
// This file is part of the OpenStructure project <www.openstructure.org>
//
// Copyright (C) 2008-2015 by the OpenStructure authors
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 3.0 of the License, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this library; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//------------------------------------------------------------------------------
/*
python interpreter
Authors: Andreas Schenk, Ansgar Philippsen, Marco Biasini
*/
#include "python_interpreter.hh"
#include <iostream>
#include <csignal>
#include <string>
#include <fstream>
#include <boost/filesystem/convenience.hpp>
#include <ost/log.hh>
#include <QFile>
#include <QDebug>
#include <QFile>
#include <QStringList>
namespace ost { namespace gui {
PythonInterpreter::PythonInterpreter():
QObject(),
main_module_(),
main_namespace_(),
running_(false),
compile_command_(),
worker_()
{
connect(this,SIGNAL(WakeWorker()),&worker_,SLOT(Wake()),Qt::QueuedConnection);
connect(&worker_,SIGNAL(Output(unsigned int,const QString&)),this,SIGNAL(Output(unsigned int,const QString&)));
connect(&worker_,SIGNAL(ErrorOutput(unsigned int,const QString&)),this,SIGNAL(ErrorOutput(unsigned int,const QString&)));
connect(&worker_,SIGNAL(Finished(unsigned int, bool)),this,SIGNAL(Finished(unsigned int, bool)));
main_module_ = bp::import("__main__");
main_namespace_ = bp::extract<bp::dict>(main_module_.attr("__dict__"));
main_namespace_["os"]=bp::import("os");
main_namespace_["__builtin__"]=bp::import("__builtin__");
main_namespace_["keyword"]=bp::import("keyword");
bp::object code=bp::import("code");
compile_command_=code.attr("compile_command");
}
PythonInterpreter::~PythonInterpreter()
{
}
PythonInterpreter& PythonInterpreter::Instance()
{
static PythonInterpreter instance;
return instance;
}
void PythonInterpreter::Stop()
{
running_=false;
}
void PythonInterpreter::Start()
{
running_=true;
emit WakeWorker();
}
void PythonInterpreter::StopScript()
{
PyErr_SetInterrupt();
}
unsigned int PythonInterpreter::RunScript(const QString& fname)
{
QFile script(fname);
if (!script.open(QIODevice::ReadOnly | QIODevice::Text)){
LOG_ERROR("could not open " << fname.toStdString());
return RunCommand("");
}
QString command=script.readAll();
command.append('\n');
command.append('\n');
return RunCommand(command);
}
unsigned int PythonInterpreter::RunCommand(const QString& command)
{
unsigned int id=worker_.AddCommand(command);
if(running_){
emit WakeWorker();
}
return id;
}
CodeBlockStatus PythonInterpreter::GetCodeBlockStatus(const QString& command)
{
// move to pure c++ to avoid clash with running worker
// move to worker class
CodeBlockStatus status=CODE_BLOCK_COMPLETE;
/*#ifndef _MSC_VER
SigIntHandler sh(sig_act_);
#endif*/
QStringList lines=command.split("\n");
String cmd;
for (int i=0; i<lines.size(); ++i) {
if (status==CODE_BLOCK_ERROR) {
break;
}
bool complete=false;
if (!(! lines[i].isEmpty() && (lines[i][0]=='\t' || lines[i][0]==' '))) {
cmd.clear();
}
while (!complete && i<lines.size()) {
cmd+=lines[i].toStdString();
if (i<lines.size()-1) {
cmd+="\n";
}
try {
bp::object result=compile_command_(bp::str(cmd));
try {
String doc=bp::extract<String>(result.attr("__doc__"));
complete=true;
status=CODE_BLOCK_COMPLETE;
} catch(bp::error_already_set) {
status=CODE_BLOCK_INCOMPLETE;
++i;
PyErr_Clear();
}
} catch(bp::error_already_set) {
status=CODE_BLOCK_ERROR;
complete=true;
PyErr_Clear();
}
}
}
return status;
}
void PythonInterpreter::AppendModulePath(const QString& entry)
{
RunCommand(QString("sys.path.insert(0, os.path.expanduser(os.path.expandvars('")+ entry + QString("')))\n"));
}
void PythonInterpreter::AppendCommandlineArgument(const QString& arg)
{
QString init_code("");
static bool sys_argv_present=false;
if(!sys_argv_present){
sys_argv_present=true;
init_code += "\nsys.argv=[]";
}
init_code += "\nsys.argv.append('" ;
init_code += arg;
init_code += "')\n";
RunCommand(init_code);
}
bp::object PythonInterpreter::GetMainModule() const
{
return main_module_;
}
bp::dict PythonInterpreter::GetMainNamespace() const
{
bp::dict result=const_cast<bp::dict&>(main_namespace_).copy();
bp::dict builtins_dict=bp::extract<bp::dict>(main_namespace_["__builtin__"].attr("__dict__"));
result.update(builtins_dict);
bp::list kwlist=bp::extract<bp::list>(main_namespace_["keyword"].attr("kwlist"));
unsigned int kwlist_length=bp::len(kwlist);
for(unsigned int i=0;i<kwlist_length;++i){
result[kwlist[i]]=bp::str();
}
return result;
}
}} // ns