Skip to content

Commit 31ea291

Browse files
committed
PythonInterpreter: finish off bits needed for the plugin to work with the XmlRpcEmbedder
1 parent 0948613 commit 31ea291

5 files changed

Lines changed: 132 additions & 209 deletions

File tree

PythonInterpreter/PythonInterpCtrl.cpp

Lines changed: 63 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -4,82 +4,21 @@
44
#include "PythonInterpCtrl.h"
55
#include <globals.h>
66

7-
DECLARE_LOCAL_EVENT_TYPE(wxEVT_PY_NOTIFY_UI_CODEOK, -1)
7+
//DECLARE_LOCAL_EVENT_TYPE(wxEVT_PY_NOTIFY_UI_CODEOK, -1)
88
DEFINE_EVENT_TYPE( wxEVT_PY_NOTIFY_UI_CODEOK )
99

10-
DECLARE_LOCAL_EVENT_TYPE(wxEVT_PY_NOTIFY_UI_INPUT, -1)
10+
//DECLARE_LOCAL_EVENT_TYPE(wxEVT_PY_NOTIFY_UI_INPUT, -1)
1111
DEFINE_EVENT_TYPE( wxEVT_PY_NOTIFY_UI_INPUT )
1212

13-
////////////////////////////////////// PythonInterpJob /////////////////////////////////////////////
14-
15-
bool PyInterpJob::operator()()
16-
{
17-
// talk to m_client
18-
// wxMessageBox(_("entered operator..."));
19-
int status=0;
20-
if(!pctl->RunCode(m_code,status))
21-
return false; //TODO: maybe retry before failing out completely
22-
if(status>=0)
23-
{
24-
wxCommandEvent pe(wxEVT_PY_NOTIFY_UI_CODEOK,0);
25-
::wxPostEvent(parent,pe);
26-
}
27-
wxCommandEvent pe(wxEVT_PY_NOTIFY_UI_NOTIFY,0);
28-
::wxPostEvent(parent,pe);
29-
bool break_called=false;
30-
while(status>0)
31-
{
32-
m_break_mutex.Lock();
33-
if(m_break_job && !break_called)
34-
{
35-
m_break_mutex.Unlock();
36-
if(pctl->BreakCode())
37-
break_called=true;
38-
} else
39-
m_break_mutex.Unlock();
40-
bool line_input_request;
41-
if(!pctl->Continue(status,line_input_request))
42-
return false; //TODO: maybe retry before failing out completely
43-
// PyNotifyUIEvent pe(id,pyinst,parent,PYSTATE_NOTIFY);
44-
::wxPostEvent(parent,pe);
45-
if(line_input_request)
46-
{
47-
pctl->m_input_mutex.Lock();
48-
wxCommandEvent ie(wxEVT_PY_NOTIFY_UI_INPUT,0);
49-
::wxPostEvent(parent,ie);
50-
pctl->m_input_cond->Wait();
51-
pctl->m_input_mutex.Unlock();
52-
}
53-
// sleep for some period of time
54-
else
55-
if(status>0)
56-
Sleep(50); //TODO: Make the sleep period user-defined
57-
}
58-
if(status==0)
59-
{
60-
wxCommandEvent pef(wxEVT_PY_NOTIFY_UI_FINISHED,0);
61-
::wxPostEvent(parent,pef);
62-
} else
63-
{
64-
wxCommandEvent pef(wxEVT_PY_NOTIFY_UI_ABORTED,0);
65-
::wxPostEvent(parent,pef);
66-
}
67-
return true;
68-
}
69-
70-
void PyInterpJob::Break()
71-
{
72-
m_break_mutex.Lock();
73-
m_break_job=true;
74-
m_break_mutex.Unlock();
75-
}
13+
//DECLARE_LOCAL_EVENT_TYPE(wxEVT_PY_PROC_END, -1)
14+
DEFINE_EVENT_TYPE( wxEVT_PY_PROC_END )
7615

7716
////////////////////////////////////// PythonIOCtrl //////////////////////////////////////////////
7817

7918
BEGIN_EVENT_TABLE(PythonIOCtrl, wxTextCtrl)
8019
EVT_CHAR(PythonIOCtrl::OnUserInput)
8120
// EVT_TEXT(wxID_ANY, PythonIOCtrl::OnTextChange)
82-
EVT_COMMAND(0, wxEVT_PY_NOTIFY_UI_INPUT, PythonIOCtrl::OnLineInputRequest)
21+
// EVT_COMMAND(0, wxEVT_PY_NOTIFY_UI_INPUT, PythonIOCtrl::OnLineInputRequest)
8322
END_EVENT_TABLE()
8423

8524
void PythonIOCtrl::OnUserInput(wxKeyEvent& ke)
@@ -117,8 +56,6 @@ void PythonIOCtrl::OnUserInput(wxKeyEvent& ke)
11756
line.Replace(_T("\n"),_T("")); //will cause major problems if there is more than one line feed returned here, so we remove them (TODO: fix on server side?? server should treat buffered lines as new input without errors)
11857
line.Append(_T("\n"));
11958
m_pyctrl->stdin_append(line);
120-
m_pyctrl->m_input_cond->Signal();
121-
m_pyctrl->m_input_mutex.Unlock();
12259
return;
12360
}
12461
}
@@ -135,11 +72,10 @@ void PythonIOCtrl::OnTextChange(wxCommandEvent &e)
13572
e.Skip(true);
13673
}
13774

138-
void PythonIOCtrl::OnLineInputRequest(wxCommandEvent &e)
75+
void PythonIOCtrl::LineInputRequest()
13976
{
14077
if(!m_line_entry_mode)
14178
{
142-
m_pyctrl->m_input_mutex.Lock();
14379
m_line_entry_mode=true;
14480
m_line_entry_point=this->GetLastPosition();
14581
this->SetSelection(m_line_entry_point,m_line_entry_point);
@@ -199,12 +135,9 @@ BEGIN_EVENT_TABLE(PythonInterpCtrl, wxPanel)
199135
// EVT_PY_NOTIFY_UI(PythonInterpCtrl::OnPyNotify)
200136
// EVT_END_PROCESS(ID_PROC, PythonInterpCtrl::OnEndProcess)
201137
// EVT_LEFT_DCLICK(PythonInterpCtrl::OnDClick)
202-
EVT_COMMAND(0, wxEVT_PY_NOTIFY_UI_NOTIFY, PythonInterpCtrl::OnPyNotify)
203-
EVT_COMMAND(0, wxEVT_PY_NOTIFY_UI_CODEOK, PythonInterpCtrl::OnPyCode)
204-
EVT_COMMAND(0, wxEVT_PY_NOTIFY_UI_INPUT, PythonInterpCtrl::OnLineInputRequest)
205-
EVT_COMMAND(0, wxEVT_PY_NOTIFY_UI_STARTED, PythonInterpCtrl::OnPyNotify)
206-
EVT_COMMAND(0, wxEVT_PY_NOTIFY_UI_FINISHED, PythonInterpCtrl::OnPyJobDone)
207-
EVT_COMMAND(0, wxEVT_PY_NOTIFY_UI_ABORTED, PythonInterpCtrl::OnPyJobAbort)
138+
EVT_XMLRPC_RESPONSE(wxID_ANY, PythonInterpCtrl::OnPyNotify)
139+
// EVT_COMMAND(0, wxEVT_PY_NOTIFY_UI_CODEOK, PythonInterpCtrl::OnPyCode)
140+
// EVT_COMMAND(0, wxEVT_PY_NOTIFY_UI_INPUT, PythonInterpCtrl::OnLineInputRequest)
208141
EVT_COMMAND(0, wxEVT_PY_PROC_END, PythonInterpCtrl::OnEndProcess)
209142

210143
EVT_SIZE (PythonInterpCtrl::OnSize)
@@ -215,7 +148,6 @@ PythonInterpCtrl::PythonInterpCtrl(wxWindow* parent, int id, const wxString &nam
215148
m_killlevel=0;
216149
m_port=0;
217150
m_pyinterp=NULL;
218-
m_input_cond=new wxCondition(m_input_mutex);
219151
m_sw=new wxSplitterWindow(this, wxID_ANY);
220152
m_ioctrl=new PythonIOCtrl(m_sw, this);//new wxTextCtrl(m_sw, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_RICH|wxTE_MULTILINE|wxTE_READONLY|wxTE_PROCESS_ENTER|wxTE_PROCESS_TAB|wxEXPAND);
221153
m_codectrl=new PythonCodeCtrl(m_sw, this);
@@ -266,7 +198,13 @@ long PythonInterpCtrl::LaunchProcess(const wxString &processcmd, const wxArraySt
266198
}
267199
if(!global&&!local) //No interpreter script found, return failure.
268200
return -2; //TODO: Return meaningful messages (or at least use the codeblocks logger)
269-
m_pyinterp=new PyInstance(cmd,_T("localhost"),m_port,this);
201+
202+
m_pyinterp = XmlRpcMgr::Get().LaunchProcess(cmd,m_port);
203+
if(m_pyinterp->IsDead())
204+
{
205+
Manager::Get()->GetLogManager()->Log(_("Error Starting Interpreter"));
206+
return -1;
207+
}
270208
//TODO: Perform any initial communication with the running python process...
271209
return 1;
272210
}
@@ -292,17 +230,48 @@ bool PythonInterpCtrl::DispatchCode(const wxString &code)
292230
{
293231
if(m_pyinterp->IsJobRunning())
294232
return false;
295-
m_pyinterp->AddJob(new PyInterpJob(wxString(code.c_str()),m_pyinterp,this,m_ioctrl));
233+
int status;
296234
m_code=code;
235+
if (RunCode(wxString(code.c_str())))
236+
{
237+
wxTextAttr oldta=m_ioctrl->GetDefaultStyle();
238+
wxTextAttr ta=oldta;
239+
wxFont f=ta.GetFont();
240+
f.SetWeight(wxFONTWEIGHT_BOLD);
241+
ta.SetFont(f);
242+
m_ioctrl->SetDefaultStyle(ta);
243+
m_ioctrl->AppendText(m_code);
244+
m_ioctrl->SetDefaultStyle(oldta);
245+
m_ioctrl->AppendText(_T("\n"));
246+
// wxCommandEvent pe(wxEVT_PY_NOTIFY_UI_CODEOK,0);
247+
// ::wxPostEvent(this,pe);
248+
}
297249
return true;
298250
}
299251

300-
void PythonInterpCtrl::OnPyNotify(wxCommandEvent& event)
252+
void PythonInterpCtrl::OnPyNotify(XmlRpcResponseEvent& event)
301253
{
302-
if(m_ioctrl->m_line_entry_mode)
303-
return;
304-
m_ioctrl->AppendText(stdout_retrieve());
305-
m_ioctrl->AppendText(stderr_retrieve());
254+
// if(m_ioctrl->m_line_entry_mode)
255+
// return;
256+
if (event.GetState()==XMLRPC_STATE_RESPONSE)
257+
{
258+
XmlRpc::XmlRpcValue val = event.GetResponse();
259+
int return_code = val[0];
260+
std::string stdout(val[1]);
261+
std::string stderr(val[2]);
262+
int input_request = val[3];
263+
264+
m_ioctrl->AppendText(wxString(stdout.c_str(),wxConvUTF8));
265+
//TODO: Color errors
266+
m_ioctrl->AppendText(wxString(stderr.c_str(),wxConvUTF8));
267+
268+
if (input_request)
269+
m_ioctrl->ProcessEvent(event);
270+
271+
if (return_code == 1)
272+
this->Continue();
273+
}
274+
//TODO: If not in error and more input available, need to call RunCode("cont")
306275
}
307276

308277
void PythonInterpCtrl::OnLineInputRequest(wxCommandEvent& event)
@@ -426,106 +395,34 @@ void PythonInterpCtrl::OnUserInput(wxKeyEvent& ke)
426395
// m_ioctrl->SetInsertionPointEnd();
427396
}
428397

429-
void PythonInterpCtrl::stdin_append(const wxString &data)
430-
{ //asynchronously dispatch data to python interpreter's stdin
431-
wxMutexLocker ml(io_mutex);
432-
stdin_data+=data;
433-
}
434-
435-
void PythonInterpCtrl::stdout_append(const wxString &data)
436-
{ //asynchronously dispatch data to python interpreter's stdin
437-
wxMutexLocker ml(io_mutex);
438-
stdout_data+=data;
439-
}
440-
441-
void PythonInterpCtrl::stderr_append(const wxString &data)
442-
{ //asynchronously dispatch data to python interpreter's stdin
443-
wxMutexLocker ml(io_mutex);
444-
stderr_data+=data;
445-
}
446-
447-
wxString PythonInterpCtrl::stdin_retrieve()
448-
{
449-
wxMutexLocker ml(io_mutex);
450-
wxString s(stdin_data);
451-
stdin_data=_T("");
452-
return s;
453-
}
454-
455-
wxString PythonInterpCtrl::stdout_retrieve()
456-
{
457-
wxMutexLocker ml(io_mutex);
458-
wxString s(stdout_data);
459-
stdout_data=_T("");
460-
return s;
461-
}
462-
463-
wxString PythonInterpCtrl::stderr_retrieve()
464-
{
465-
wxMutexLocker ml(io_mutex);
466-
wxString s(stderr_data);
467-
stderr_data=_T("");
468-
return s;
469-
}
470398

471-
bool PythonInterpCtrl::RunCode(const wxString &codestr, int &status)
399+
bool PythonInterpCtrl::RunCode(const wxString &codestr)
472400
{
401+
//TODO: Should use a common ID for this and cont
473402
XmlRpc::XmlRpcValue args, result;
474403
args[0]=codestr.utf8_str();
475404
args[1]=stdin_retrieve().utf8_str();
476-
if(m_pyinterp->Exec(_("run_code"), args, result))
477-
{
478-
status=result[0];
479-
std::string r1=result[1];
480-
stdout_append(wxString::FromUTF8(r1.c_str()));
481-
std::string r2=result[2];
482-
stderr_append(wxString::FromUTF8(r2.c_str()));
483-
return true;
484-
}
485-
status=-4;
486-
return false;
405+
return m_pyinterp->ExecAsync(_T("run_code"), args, this);
487406
}
488407

489-
bool PythonInterpCtrl::Continue(int &status, bool &line_input_request)
408+
bool PythonInterpCtrl::Continue()
490409
{
491410
XmlRpc::XmlRpcValue args, result;
492411
args[0]=stdin_retrieve().utf8_str();
493-
if(m_pyinterp->Exec(_("cont"), args, result))
494-
{
495-
status=result[0];
496-
std::string r1=result[1];
497-
stdout_append(wxString::FromUTF8(r1.c_str()));
498-
std::string r2=result[2];
499-
stderr_append(wxString::FromUTF8(r2.c_str()));
500-
line_input_request=result[3];
501-
return true;
502-
}
503-
status=-4;
504-
return false;
412+
return m_pyinterp->ExecAsync(_("cont"), args, this);
505413
}
506414

507415
bool PythonInterpCtrl::BreakCode()
508416
{
509-
m_pyinterp->Break();
510-
return true;
511-
XmlRpc::XmlRpcValue args, result;
512-
if(m_pyinterp->Exec(_("break_code"), args, result))
513-
{
514-
//TODO: evaluate result -- if it not true, there was no code running
515-
wxMessageBox(_("break sent"));
516-
return true;
517-
}
518-
wxMessageBox(_("break not sent"));
519-
return false;
417+
//TODO: Need to use a separate ID for this
418+
XmlRpc::XmlRpcValue args;
419+
return m_pyinterp->ExecAsync(_("break_code"), args, this);
520420
}
521421

522422
bool PythonInterpCtrl::SendKill()
523423
{
424+
//TODO: Need to use a separate ID for this
524425
XmlRpc::XmlRpcValue args, result;
525-
if(m_pyinterp->Exec(_("end"), args, result))
526-
{
527-
return true;
528-
}
529-
return false;
426+
return m_pyinterp->ExecAsync(_("end"), args, this);
530427
}
531428

0 commit comments

Comments
 (0)