[Sciviews-commits] r353 - in komodo/SciViews-K: components content/js
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Wed Feb 16 15:50:38 CET 2011
Author: prezez
Date: 2011-02-16 15:50:38 +0100 (Wed, 16 Feb 2011)
New Revision: 353
Modified:
komodo/SciViews-K/components/svIUtils.idl
komodo/SciViews-K/components/svUtils.py
komodo/SciViews-K/content/js/r_new.js
Log:
More additions to svUtils XPCOM interface and new methods in the 'sv.rnew' object (socket server)
Modified: komodo/SciViews-K/components/svIUtils.idl
===================================================================
--- komodo/SciViews-K/components/svIUtils.idl 2011-02-14 21:53:06 UTC (rev 352)
+++ komodo/SciViews-K/components/svIUtils.idl 2011-02-16 14:50:38 UTC (rev 353)
@@ -34,11 +34,22 @@
#include "nsISupports.idl"
#include "nsISimpleEnumerator.idl"
+// This is implemented in sv.rnew's JavaScript code.
+[scriptable, uuid(ca1bcf00-394d-11e0-bd69-0002a5d5c51b)]
+interface svIStuffListener: nsISupports {
+ wstring onStuff(in wstring data);
+};
+
[scriptable, uuid(5f82d460-37b6-11e0-b897-0002a5d5c51b)]
interface svIUtils : nsISupports {
+ wstring execFun(in svIStuffListener stuffLlistener);
+ void execFunInBgr(in svIStuffListener requestHandler);
nsISimpleEnumerator getproc(in string propertyName);
- string execInR(in wstring command, in string host, in long port);
- void execInRBgr(in wstring command, in string host, in long port);
+ wstring execInR(in wstring command, in string host, in long port, in string mode);
+ void execInRBgr(in wstring command, in string host, in long port, in string mode);
+ boolean startSocketServer(in string host, in long port, in svIStuffListener requestHandler);
+ void stopSocketServer();
attribute wstring lastCommand;
attribute wstring lastResult;
+ attribute wstring id;
};
Modified: komodo/SciViews-K/components/svUtils.py
===================================================================
--- komodo/SciViews-K/components/svUtils.py 2011-02-14 21:53:06 UTC (rev 352)
+++ komodo/SciViews-K/components/svUtils.py 2011-02-16 14:50:38 UTC (rev 353)
@@ -35,19 +35,16 @@
from xpcom import components, nsError, COMException
from xpcom._xpcom import getProxyForObject, PROXY_SYNC, PROXY_ALWAYS, PROXY_ASYNC
import os, sys, re
-#import tempfile
import string
-#import process
-#import koprocessutils
from xpcom.server.enumerator import SimpleEnumerator
import socket
-#from threading import Thread
import threading
-
-
import logging
log = logging.getLogger('svUtils')
+#log.setLevel(logging.INFO)
+log.setLevel(logging.DEBUG)
+
class svUtils:
_com_interfaces_ = [components.interfaces.svIUtils]
_reg_desc_ = "SciViews-K utilities"
@@ -64,8 +61,31 @@
self.lastCommand = u''
self.lastResult = u''
+ self.id = 'svpy'
+ self.runServer = False
+ self.serverIsUp = False
pass
+
+ def execFun(self, stuffLlistener):
+ listenerProxy = getProxyForObject(1,
+ components.interfaces.svIStuffListener,
+ stuffLlistener, PROXY_ALWAYS | PROXY_SYNC)
+ ret = listenerProxy.onStuff("test 123")
+ return ret
+
+ def execFunInBgr(self, requestHandler):
+ t = threading.Thread(target=self._doExecFn, kwargs={
+ 'requestHandler': requestHandler
+ })
+ t.start()
+
+ def _doExecFn(self, requestHandler):
+ listenerProxy = getProxyForObject(1,
+ components.interfaces.svIStuffListener,
+ requestHandler, PROXY_ALWAYS | PROXY_SYNC)
+ listenerProxy.onStuff("test 12345...")
+
def _asSString(self, s):
ret = components.classes["@mozilla.org/supports-string;1"] \
.createInstance(components.interfaces.nsISupportsString)
@@ -74,7 +94,7 @@
def getproc(self, propertyName):
# TODO: error handling here
-# TODO: checking for correct propertyName
+# TODO: checking for correct propertyName, return several properties at a time
ret = []
if sys.platform.startswith('win'):
from win32com.client import GetObject
@@ -83,10 +103,6 @@
' from Win32_Process where Name="Rgui.exe" or Name="R.exe" or Name="Rterm.exe"')
if len(processes) > 0 :
for p in processes:
- #ret.append([p.Properties_('Name').Value, p.Properties_('ProcessId').Value])
- ##ret.append(p.Properties_('ExecutablePath').Value) 'CommandLine'
- elem = components.classes["@mozilla.org/supports-string;1"] \
- .createInstance(components.interfaces.nsISupportsString)
ret.append(p.Properties_(propertyName).Value)
else:
propertyName = {
@@ -104,48 +120,137 @@
return SimpleEnumerator(ret)
- def execInR(self, command, host, port):
- """
- This should send command to R through a socket connection and return the
- output
- """
+ def execInR(self, command, host, port, mode):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.connect((host, port))
- s.settimeout(5)
+ s.settimeout(.5) # increase if not localhost
+ try:
+ s.connect((host, port))
+ except BaseException, e:
+ return unicode(e.args[0]);
+
# TODO: allow for <<<h>>>
- s.send('<<<id=SciViewsK>>><<<e>>>' + command)
+ s.send('<<<id=' + self.id + '>>><<<' + mode + '>>>' + command)
s.shutdown(socket.SHUT_WR) # does not work without shutdown, why?
result = ''
- while 1:
+ while True:
data = s.recv(1024)
if not data: break
result += data
s.close()
return unicode(result)
- def execInRBgr(self, command, host='localhost', port=8888):
- t = threading.Thread(target=self.rconnect, args=(command, host, port))
- #t.setDaemon(True)
+ def execInRBgr(self, command, host, port, mode):
+ t = threading.Thread(target=self.rconnect, args=(command, host, port, mode))
+ #t.daemon = True
t.start()
- def rconnect(self, command, host, port):
+ def rconnect(self, command, host, port, mode):
self.lastCommand = unicode(command)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.settimeout(None)
- s.send('<<<id=SciViewsK>>><<<e>>>' + command)
+ s.send('<<<id=' + self.id + '>>><<<' + mode + '>>>' + command)
s.shutdown(socket.SHUT_WR) # does not work without shutdown, why?
result = ''
- # notify after each chunk, and at the end
+ # notify after each chunk and at the end
while 1:
data = s.recv(1024)
if not data: break
self._proxiedObsSvc.notifyObservers(None, 'r-command-chunk', data)
result += data
- self._proxiedObsSvc.notifyObservers(None, 'r-command-finished', result)
s.close()
self.lastResult = unicode(result)
+ self._proxiedObsSvc.notifyObservers(None, 'r-command-executed', result)
#try:
- self._proxiedObsSvc.notifyObservers(None, 'r-command-executed', result)
+ #self._proxiedObsSvc.notifyObservers(None, 'r-command-executed', result)
#except Exception:
#log.exception("r-command-executed notification failed")
+
+ def startSocketServer(self, host, port, requestHandler):
+ # TODO: do not run two! use semaphore
+ if(self.serverIsUp): return False
+ self.runServer = True
+ t = threading.Thread(target=self._SocketServer, kwargs={
+ 'host': host,
+ 'port': port,
+ 'requestHandler': requestHandler
+ })
+ t.start()
+ log.debug('Started socket server at port %d' % port)
+ return True
+
+ def stopSocketServer(self):
+ self.runServer = False
+ log.debug('Told socket server to stop')
+
+
+ def _SocketServer(self, host, port, requestHandler):
+ # requestHandler is a Javascript object with component 'onStuff'
+ # which is a function accepting one argument (string), and returning
+ # a string
+ requestHandlerProxy = getProxyForObject(1,
+ components.interfaces.svIStuffListener,
+ requestHandler, PROXY_ALWAYS | PROXY_SYNC)
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.settimeout(5)
+ try:
+ s.bind((host, port))
+ except Exception, e:
+ log.exception(e)
+ return
+ self.serverIsUp = True
+ s.listen(1)
+ log.debug('Socket server listening at %d' % port)
+ count = 0
+ connected = False
+ while self.runServer:
+ while self.runServer:
+ connected = False
+ try:
+ conn, addr = s.accept()
+ connected = True
+ conn.setblocking(1)
+ count += 1
+ break
+ except Exception, e:
+ #print(e)
+ continue
+ if not connected: continue
+ data_all = ''
+ while connected:
+ log.debug('Connected by %s : %d' % addr)
+ data = conn.recv(1024)
+ data_all += data
+ if (not data) or (data[-1] == '\n'): break
+ #print "Sending:", data_all + "."
+ ## Process data here
+ #result = data_all # echo request
+ #unicode(data_all) ?????
+ try:
+ result = requestHandlerProxy.onStuff(data_all)
+ except BaseException, e:
+ result = e.args[0]
+ log.debug('JS request exception: %s' % result)
+ if (result == None): conn.send('\n')
+ else: conn.send(result + '\n')
+ conn.shutdown(socket.SHUT_RDWR)
+ conn.close()
+ log.debug('conn closed')
+ #s.shutdown(socket.SHUT_RDWR) # Is it necessarry?
+ s.close()
+ self.serverIsUp = False
+ log.debug("Exiting after %d connections" % count)
+ pass
+
+
+# conn.setblocking(1)
+# File "<string>", line 1, in setblocking
+# File "/home/kamil/Komodo-Edit-6/lib/python/lib/python2.6/socket.py", line 165, in _dummy
+# raise error(EBADF, 'Bad file descriptor')
+#error: [Errno 9] Bad file descriptor
+
+
+ #def Run(self, command, env, console):
+ # pass
+ #
+ #def _WaitNotifyAndCleanUp(self, child, command, scriptFileName=None):
Modified: komodo/SciViews-K/content/js/r_new.js
===================================================================
--- komodo/SciViews-K/content/js/r_new.js 2011-02-14 21:53:06 UTC (rev 352)
+++ komodo/SciViews-K/content/js/r_new.js 2011-02-16 14:50:38 UTC (rev 353)
@@ -6,19 +6,37 @@
//.result (Read only) last result returned
//.getRProc(property) get information on currently running R processes
// (property is one of 'Handle','ProcessId' or 'CommandLine'
-//.setObserver(callback) set callback function for R command
-//.removeObserver
//.rEval(command, callback) evaluate in R, optional callback (if not provided,
// the most recent one is used)
//.rEvalQuick(command) - do 'quick' evaluation in R, and
-//return the result
+// return the result
+//.startSocketServer(requestHandler) - optional 'requestHandler' is a function that
+// handles the received data and returns a string
+//.stopSocketServer()
+//.testRAvailability(checkProc) - test whether R is available, check connection and
+// optionally look up running processes
+//Debugging functions:
+//.testRCommand(command)
+//.testRCommandNotify(chunk)
+//.enumObservers()
+//Functions below should not be called directy by the user.
+// they will become private later
+//*.setObserver(callback, topic) set callback function for R command
+//*.removeObserver
+try { // in case we inject the script more then one time
+ sv.rnew.removeObserver();
+} catch(e) {}
+
sv.rnew = {};
(function() {
var _this = this;
+ this.port = 8888;
+ this.serverPort = 7052;
+ this.host = 'localhost';
// get string from nsISupportsString
function _str(sString) sString.QueryInterface(Components
@@ -29,7 +47,7 @@
var _obsSvc = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
-var observer;
+var observers = {};
var obsCallback = function() { sv.cmdout.append("test")};
this.__defineGetter__ ('command', function () _svuSvc.lastCommand);
@@ -46,67 +64,149 @@
}
// Observer of 'r-command-executed' notification
-function rObserver() this.register();
+function rObserver(topic, callback) this.register(topic, callback);
rObserver.prototype = {
observe: function(subject, topic, data) {
//ko.dialogs.alert(topic + ":\r\n" + data);
- obsCallback(_svuSvc.lastCommand, data);
+ this.callback(_svuSvc.lastCommand, data);
},
- register: function() {
- _obsSvc.addObserver(this, "r-command-executed", false);
+ register: function(topic, callback) {
+ if(callback) this.callback = callback;
+ this.topic = topic;
+ _obsSvc.addObserver(this, topic, false);
},
unregister: function() {
- _obsSvc.removeObserver(this, "r-command-executed");
- }
+ _obsSvc.removeObserver(this, this.topic);
+ },
+
+ topic: null,
+ callback: function(cmd, data) ko.dialogs.alert(cmd, data)
}
-this.removeObserver = function() {
- observer.unregister();
- callback = function() {};
+this.removeObserver = function(topic) {
+ if (!topic) for (var i in observers) {
+ observers[i].unregister();
+ delete observers[i];
+ }
+ else {
+ observers[topic].unregister();
+ delete observers[topic];
+ }
}
// Set callback for executing R command
-this.setObserver = function(callback) {
+this.setObserver = function(callback, topic) {
+ if(!topic) topic = "r-command-executed";
+
try {
- _this.removeObserver();
+ _this.removeObserver(topic);
} catch(e) {}
- observer = new rObserver();
- if (callback) obsCallback = callback;
+ observers[topic] = new rObserver(topic, callback);
}
+this.enumObservers = function() {
+ var ret = [];
+ for (var i in observers) ret.push(observers[i]);
+ return ret;
+}
// Evaluate in R
-this.rEval = function(command, callback) {
- if(callback) _this.setObserver(callback);
- _svuSvc.execInRBgr(command, 'localhost', 8888);
+this.rEval = function(command, callback, hidden) {
+ if(callback) _this.setObserver(callback, "r-command-executed");
+ _svuSvc.execInRBgr(command, _this.host, _this.port, hidden? "h" : "e");
}
// TODO: this should use <<<h>>>
// Evaluate in R quickly - and return result
this.rEvalQuick = function(command)
- _svuSvc.execInR(command, 'localhost', 8888);
+ _svuSvc.execInR(command, _this.host, _this.port, "h");
// For debugging purposes only
this.testRCommand = function(command) {
if(!command) command = "sample(LETTERS, 10)";
- _svuSvc.execInRBgr(command, 'localhost', 8888);
+ _svuSvc.execInRBgr(command, _this.host, _this.port, "e");
}
-this.testRCommandNotify = function() {
- _obsSvc.notifyObservers(null, "r-command-executed", "!!!");
+this.testRCommandNotify = function(chunk) {
+ topic = "r-command" + (chunk? "chunk" : "executed");
+ _obsSvc.notifyObservers(null, topic, "You are notified. {" + topic + "}");
}
+var rCallback = function(cmd, res) {
+ //sv.cmdout.clear();
+ sv.cmdout.append("::>"+ cmd + ": END")
+}
+
+var rCallbackChunk = function(cmd, res) {
+ sv.cmdout.append("\n<++CHUNK++>\n"+ res, false)
+}
+
+this.testRAvailability = function(checkProc) {
+ var result = _this.rEvalQuick("cat(1)").trim();
+ var connectionUp = result == "1";
+ var rProcess = checkProc? _this.getRProc() : undefined;
+ var rProcessCount = (rProcess == undefined)? -1 : rProcess.length;
+ ret = '';
+ if(!connectionUp) {
+ ret += "Cannot connect to R";
+ if (rProcessCount > 0) {
+ ret += ", but there " + ((rProcessCount > 1)? "are " + rProcessCount
+ + " R processes": "is one R process") + " running.";
+ result += "\n\nR processes currently running:\n" + rProcess.join("\n");
+ } else if (rProcessCount == 0) {
+ ret += ", R is not running.";
+ }
+ } else {
+ result = null;
+ ret += "Connection with R successful.";
+ }
+ //ko.dialogs.alert(ret, result, "R connection test");
+ sv.cmdout.append("R connection test:\n" + ret + "\n" + result);
+ return connectionUp;
+}
+
+_this.setObserver(rCallbackChunk, "r-command-chunk");
+_this.setObserver(rCallback, "r-command-executed");
+
+var defaultRequestHandler = function(str) {
+ str = str.trim();
+ //sv.cmdout.append(str);
+ try {
+ if (str.indexOf("<<<js>>>") == 0)
+ return eval(str.substring(8));
+ else if(str.indexOf("<<<rjsonp>>>") == 0)
+ return sv.rjson.eval(str.substring(12));
+ } catch(e) {
+ return e.message;
+ }
+ sv.cmdout.append(str);
+ return "Received: [" + str + "]"; // echo
+}
+
+
+this.startSocketServer = function(requestHandler) {
+ _this.host = sv.prefs.getString("sciviews.server.host");
+ _this.serverPort = parseInt(sv.prefs.getString("sciviews.server.socket"));
+
+ if(!requestHandler) requestHandler = defaultRequestHandler;
+ return _svuSvc.startSocketServer(_this.host, _this.serverPort, {onStuff: requestHandler});
+}
+
+this.stopSocketServer = function() _svuSvc.stopSocketServer();
+
+addEventListener("load", function() {
+ sv.command.updateRStatus(_this.testRAvailability(false));
+ _this.startSocketServer();
+}, false);
+
+
}).apply(sv.rnew);
// seems to be no problem with encoding (!!?)
-//sv.rnew.testRCommand("cat('pchn¹æ w tê ³ód je¿a i óm skrzyñ fig')")
+//sv.rnew.testRCommand("cat('pchn¹æ w tê ³ód je¿a i óm skrzyñ fig')") // Note this is CP1250 encoding
-var rCallback = function(cmd, res) {
- sv.cmdout.clear();
- sv.cmdout.append("::>"+ cmd + "\n" + res)
-}
//sv.rnew.rEval("cat(1:10)", ko.dialogs.alert);
//result = sv.rnew.rEvalQuick("cat(1:10)");
More information about the Sciviews-commits
mailing list