IPython notebook ~ Using javascript to run python code? - javascript

I am trying to execute python code through javascript directly:
I fire up IPython Notebook on Chrome
Using chrome developer tools I open up the javascript console.
In the javascript consolde, I type: IPython.notebook.kernel.execute("2+2")
But I get a strange output: "6CEA73CC644648DDA978FDD6A913E519"
Is there any way to take advantage of all the IPython javascript functions available, to run python code from the javascript console as depicted in the image? I'm sure there's a way but I've been beating at it for way too long and thought I would post here.
(I need this to build an app on top of IPython)
Thanks in advance!

You can call Python code execution from JavaScript with Jupyter.notebook.kernel.execute() function.
Depend on this gist from Craig Dennis you can insert this code in Jupyter cell and run it
%%javascript
window.executePython = function(python) {
return new Promise((resolve, reject) => {
var callbacks = {
iopub: {
output: (data) => resolve(data.content.text.trim())
}
};
Jupyter.notebook.kernel.execute(`${python}`, callbacks);
});
}
function Log_out(r)
{ console.log(r); };
var code =
'for i in range(1,6):'+
' print( "#" + str(i))';
window.executePython( code )
.then(result => Log_out(result)); // Log out
Result would be output to browser javascript console.

Are you aware of this blogpost? http://jakevdp.github.io/blog/2013/06/01/ipython-notebook-javascript-python-communication/
I think the exact way he uses doesn't work anymore, but maybe it can get you a step forward

After spending two days on it, here is the solution that worked for me.
To run Python code I am simpy using 'Jupyter.notebook.kernel.execute'. To get the answer from it I found usefull information at this link: https://jupyter-notebook.readthedocs.io/en/stable/comms.html
from ipykernel.comm import Comm
js_input = [] #case willing to track
def func_edit(cobj,text):
my_comm = Comm(target_name=cobj) #this is the callback
my_comm.send('' if text == '' else 'Return: ' + text)
global js_input
js_input.append(f'origin={cobj} text={text}')
from IPython.display import display, HTML
html = """
<script>
var comm_name = "this_control";
function fcalc(x)
{
// here I am passing to the Python function the value to edit and the address for getting the return value
IPython.notebook.kernel.execute("func_edit('" + comm_name + "','" + x.value + "')")
}
Jupyter.notebook.kernel.comm_manager.register_target(comm_name, function(comm, msg)
{
// comm is the frontend comm instance, msg is the comm_open message, which can carry data
// Register handlers for later messages:
comm.on_msg(function(msg) {
document.getElementById("out").value = msg.content.data;
});
//comm.on_close(function(msg) {...});
//comm.send({'foo': 40}); what is it??
});
</script>
<label for="in">Input:</label>
<input type="text" id="in" name="in" oninput="fcalc(this)">
<label for="out">Out:</label>
<input type="text" id="out">
"""
display(HTML(html))

In an effort to isolate a minimum viable implementation, I was able to get responses back from the IPython kernel in just a couple of steps using essentially the same approach as ChrCury78.
Since I want to use the data returned from Python within Javascript, in these examples I just stored the message contents in a member on console. (Unlike what ChrCury78 did, where he pushed the result to the output of the notebook cell.) In my real extension, I'll probably just attach it to a name on Jupyter, or maybe an object of my own creation.
>> Jupyter.notebook.kernel.comm_manager.register_target("mycomm", (comm, msg) => {comm.on_msg( m => {console.retval = m.content.data})})
<- undefined
>> Jupyter.notebook.kernel.execute("from ipykernel.comm import Comm; Comm(target_name='mycomm').send('FOO')")
<- "{hex UID}"
>> console.retval
<- "FOO"
Multi-line Python code worked just fine, too; and, since I'd already imported Comm, I didn't need to import it again:
>> Jupyter.notebook.kernel.execute("l = []\nfor x in range(5):\n l.append(x)\nComm(target_name='mycomm').send(l)")
<- "{hex UID}"
>> console.retval
<- Array(5) [ 0, 1, 2, 3, 4 ]
If you want to keep the kernel namespace unpolluted afterward, you could add a del Comm to the end of the Python command.
I'll definitely be writing wrapper functions of some kind for both of these operations.
This is with Python 3.9.11 and the following packages installed:
ipykernel 6.9.2
ipython 8.1.1
ipython-genutils 0.2.0
ipywidgets 7.7.0
jupyter 1.0.0
jupyter-client 7.1.2
jupyter-console 6.4.3
jupyter-contrib-core 0.3.3
jupyter-contrib-nbextensions 0.5.1
jupyter-core 4.9.2
jupyter-highlight-selected-word 0.2.0
jupyter-latex-envs 1.4.6
jupyter-nbextensions-configurator 0.4.1
jupyterlab-pygments 0.1.2
jupyterlab-widgets 1.1.0

Related

How to return value from a javascript call in Jupyterlab?

I am struggling to read clipboard from jupyterlab.
My jupyter server is running on a remote instance using docker, so pyperclip and other similar tricks are not working. The idea is to use javascript but I have very limited experience using it. I am able to get the clipboard value and paste it to the log console but not to get back the value to python.
The usual trick using ipython.notebook.kernel.execute is not working.
See below the working example. Note that this has to be run in Chrome as afaik Firefox is blocking this feature.
Any suggestion is more than welcome :-)
Patrick
my_js = """
async function paste(input) {
const text = await navigator.clipboard.readText();
return text
}
paste().then((value) => console.log(value));
"""
import ipywidgets as widgets
from IPython.display import HTML, Javascript
button = widgets.Button(
description='Button',
disabled=False,
button_style='',
tooltip='Button',
icon='check'
)
output = widgets.Output()
#output.capture(clear_output=False)
def on_button_clicked(b):
display(Javascript(my_js))
button.on_click(on_button_clicked)
display(button, output)
# if you don't want to use ipywidgets, this would also work :
get_ipython().run_cell_magic("javascript", "",my_js)

add Office.onReady() function to javascript

I am new to Javascript and am trying to make an outlook web-addin take the Office.onReady() function properly.
https://learn.microsoft.com/en-us/office/dev/add-ins/develop/initialize-add-in
I tried using
Office.onReady()
.then
to make my function work with the office js API but it then I got an error that my function couldn't be found.
Code:
$("#brief-summary").click(briefsummary);
$("#email-setup").click(emailsetup);
Office.onReady()
.then(function briefsummary() {
var msgFrom = Office.context.mailbox.item.from;
var msgfirstname = String(msgFrom.displayName).split(" ");
Office.context.mailbox.item.displayReplyAllFormAsync(
"Hello " +
msgfirstname[0] +
", <br> \
<br> Here is a brief summary on everything worked on: \
<br> \
<br>Thank you for your time, \
<br>"
);
});
Result:
Uncaught ReferenceError: briefsummary is not defined
So I am pretty sure I am doing it wrong.
I also tried using Office.onReady(); at the begining of the script. It suppressed the Uncaught Error: Office.js has not fully loaded. Your app must call "Office.onReady()" error but office javascript doesn't do anything. (Its suppose to bring up a new reply window with text inside)
Link to where the app is hosted: https://alloyautomateaddinbeta3.azurewebsites.net/index.html (Although the office.js only loads when you are in the outlook app. But you can go to sources from inspector in chrome and look at the js script in full)
Any ideas would be awesome.
I have seems to figure out what to do but I was pretty janky. If anyone knowas a better way to clean this up let me know.
I essentially my code inbetween this and it worked:
Office.onReady((info) => {
if (info.host === Office.HostType.Outlook) {
#Insert code here
}
});
It was pretty janky as it gives me a warning saying Function variables should not be placed in blocks. Use a function expression or move the statement to the top of the outer function
I will be working on the code periodically so I will update my answer to a better one as time goes on unless someone else has an answer as well.
Thanks

Mail Rules with javascript instead of applescript

In a Mac mail rule, I am trying to run a javascript instead of an applescript. This has been asked in Mail Rules using JavaScript for Automation instead of AppleScript but the answer is not working for me!
I have tried to simplify the code as much as I can. So, the following applescript works fine:
on perform mail action with messages theMessages
say "running!"
end perform mail action with messages
but the equivalent javascript is not working.
function performMailActionWithMessages(messages) {
app = Application.currentApplication()
app.includeStandardAdditions = true
app.say ("running")
}
Edit
Here are my rule parameters
I do it without getting app. Try something like…
// ObjC.import('Cocoa')
ObjC.import('stdlib')
var program="/usr/bin/say"
function performMailActionWithMessages(messages) {
say("running")
}
function say(what){
var command = program + " '"+what+"'"
console.log(command)
$.system(command)
}
I’m not sure you need cocoa. You probably need stdlib.

Disable JavaScript Alerts GeckoFX C#

I'm trying to disable JavaScript alert in GeckoFX-33 + xulrunner 33 ( winforms c# ) but I can't find a solution. I check the example codes, source code but I just can't find something that blocks the alert out. I searched in about:config as well without success.
Anybody knows where I could find a reference at last ?
In prior versions, you could do
webBrowser.JavascriptError += (sender, error) => {
// do something
}
However according to issue 7 on geckofx 33, there's some work that needs to be done to support the new debugging interface:
the geckofx service jsdIDebuggerService was removed from firefox 33. the JavascriptError event implementation used this service. So the JavascriptError event handler needs to be reimplemented using firefox new debugging interface.
geckoWebBrowser1.JavascriptError += (sender, error) =>
{
GeckoWebBrowser browser = geckoWebBrowser1;
string text = "window.alert = function(){};";
using (AutoJSContext context = new AutoJSContext(browser.Window.JSContext))
{
string result;
//toolStripLabel1.Text = "was is loaded?";
context.EvaluateScript(text, (nsISupports)browser.Window.DomWindow, out result);
}
};
Here is the final code for Gecko 29.

PHP WebSockets with Ratchet - example doesn't work

Here's some background first.
My aim is to use Ratchet WebSockets to create two-way client-server communication.
I have installed ratchet and accompanying software, as described here.
I have successfully created a Hello World application as described here.
Now I am trying to create Push functionality using this tutorial. I have copied the code, modifying it slightly (modifications noted in code comments below), installed the ZMQ library (latest version, added it to php.ini, show up in php -m - in short, it's installed correctly). But the WebSockets don't work.
I will give my testing process with real live links to my domain below, so you can check it yourself.
My push server is exactly the same as the one in their tutorial, with the IP changed to my server's IP. I run this through SSH and it seems to connect correctly.
My Pusher class is in the MyApp namespace, same code and same relative location as in their tutorial.
My post.php is slightly modified because there's no need to bother with MySQL queries:
$entryData = array( //hard-coded content of $entryData for simplicity
'cat' => "macka"
, 'title' => "naslov"
, 'article' => "tekst"
, 'when' => time()
);
// This is our new stuff
$context = new ZMQContext();
$socket = $context->getSocket(ZMQ::SOCKET_PUSH, 'my pusher');
$socket->connect("tcp://light-speed-games.com:5555"); //my domain, still using port 5555 as in their example
$socket->send(json_encode($entryData));
This file is located here.
My client.php is the same as theirs, except I had to add a little fix for IE to work with when.js. My problem is browser-independent and the same as it was before the fix was added.
<script>
window.define = function(factory) { //my addition
try{ delete window.define; } catch(e){ window.define = void 0; } // IE
window.when = factory();
};
window.define.amd = {};
</script>
<script src="/apps/scripts/when.js"></script>
<script src="http://autobahn.s3.amazonaws.com/js/autobahn.min.js"></script>
<script>
var conn = new ab.Session(
'ws://light-speed-games.com:8080' // The host (our Ratchet WebSocket server) to connect to
, function() { // Once the connection has been established
conn.subscribe('kittensCategory', function(topic, data) {
// This is where you would add the new article to the DOM (beyond the scope of this tutorial)
console.log('New article published to category "' + topic + '" : ' + data.title);
});
}
, function() { // When the connection is closed
console.warn('WebSocket connection closed');
}
, { // Additional parameters, we're ignoring the WAMP sub-protocol for older browsers
'skipSubprotocolCheck': true
}
);
</script>
This file is located here.
In theory, what should happen is this (for example): I open client.php in Chrome with console switched on; then I open post.php in Firefox; Chrome's console should show the message 'New article published...' etc (from the conn.subscribe function in client.php). However, when I do this, nothing happens. The connection remains open (doesn't show the 'connection closed' error until I switch off push-server.php through SSH). The console remains empty.
I think that's all the relevant info from the last couple of days, a large portion of which I've spent on trying to figure this out. However, I've been unable to even make sure if the problem is with the code or with some server configuration setting I may be unaware of. So, I come to you hoping someone will point me in the right direction.
Important edit
I'm pretty sure the problem is with the Autobahn.js method conn.subscribe not working properly. The connection is being established. When I change the code to:
function() { // Once the connection has been established
console.log('Connection established');
conn.subscribe('kittensCategory', function(topic, data) {
// This is where you would add the new article to the DOM (beyond the scope of this tutorial)
console.log('New article published to category "' + topic + '" : ' + data.title);
});
}
Then Connection established is shown in the console correctly. So I believe we need to troubleshoot the subscribe method. If someone can explain to me how it works, and what exactly "topic" and "data" are supposed to be, it would be of great help. The Autobahn documentation uses a URL as an argument for this method (see here).
Your client is looking for an article in kittensCategory, but you are sending category macka. Try this:
$entryData = array(
'cat' => "kittensCategory",
'title' => "naslov",
'article' => "tekst",
'when' => time()
);
Is it correct to see your host light-speed-games.com on port 8080 is not functioning? If not, I would suggest to fix this as it is likely its causing your issues.

Categories

Resources