iodide-project / iodide

Literate scientific computing and communication for the web
Mozilla Public License 2.0
1.49k stars 142 forks source link

Demo broken #2524

Closed simlan123 closed 4 years ago

simlan123 commented 4 years ago

I have noticed that the demo notebook (https://alpha.iodide.io/notebooks/300/) linked from the documentation seems to be broken. I tested it with Firefox, Chrome & Microsoft Edge (Chrome mobile) to rule out any browser issues. It looks like the color codes used to demo the dom interactions are somehow garbled: image

Also other strings are affected. Here is the content of the buffer I get when starting the demo:


%% md
# Pyodide 🐍

Pyodide brings the Python runtime to the browser via WebAssembly, along with NumPy, Pandas, Matplotlib, parts of SciPy, and NetworkX.

press `shift+enter` to step through this notebook.

%% raw

As you can see, some basic parts of Python work as you might expect. To use Python, just use the `%% py` delimiter in your editor, and hit `shift+enter` to evaluate. Your browser will then go off to grab Python & initialize it.

%% py
# python
import sys
sys.version

%% raw

It also does the parts you might be surprised by! Try evaluating the chunk below (`shift+enter`).

%% py
import antigravity

%% raw

Pyodide performs quick translation of data types into javascript, so there is one clear interface for accessing data and representing it.

%% py
[0, 1, 32.0, 'foo', {'a': 10, 'b': '20'}]

%% raw
## Using Javascript from Python

We've built ways of importing anything from javascript land into python. Here, we'll import `document`, which should be familiar to javascript web developers everywhere, and use its APIs to manipulate a DOM element.

Note that Markdown allows embedding of inline HTML, so we'll add target element in a Markdown block.

%% md
#### Here's a DOM element to manipulate:
<div id="targetElement">Change me!</div>

%% py
from js import document
elt = document.getElementById("targetElement")
elt.innerText = "I am changed!"
elt.style.backgroundColor = &#x27;#ffcccc&#x27;

%% py
# let&#x27;s switch it back
elt.style.backgroundColor = &#x27;#ffffff&#x27;

%% raw

Because we _have_ direct access to the DOM, we can do fun things like make UI widgets.

Run the code chunk below (`shift+enter`) and then click on the "Report Preview" tab on the top right. This report preview should render everything you see in these `%% md` chunks, as well as a button. The code you just ran below generated that button. Take a look at what the code does, and then click the button.

Don&#x27;t forget to switch back to the "Console" view when you&#x27;re finished here - we have more to show you.

%% py
from js import iodide
button = iodide.output.element(&#x27;button&#x27;)
button.textContent = "Click me!"
count = 0
def onclick(evt):
    global count
    if elt.style.backgroundColor == &#x27;rgb(255, 255, 255)&#x27;:
        elt.style.backgroundColor = &#x27;#ffcccc&#x27;
        elt.innerText = "I&#x27;ve been changed " + str(count) + " times!"
    else:
        elt.style.backgroundColor = &#x27;#ffffff&#x27;
        elt.innerText = "I&#x27;ve been changed " + str(count) + " times!"
    count += 1
button.addEventListener(&#x27;click&#x27;, onclick)

%% raw
Or really make use of event callbacks to build a simple painting canvas...

%% css
canvas {
  border: 2px solid #ddd;
}

%% py
from js import document, iodide

canvas = iodide.output.element(&#x27;canvas&#x27;)
canvas.setAttribute(&#x27;width&#x27;, 450)
canvas.setAttribute(&#x27;height&#x27;, 300)
context = canvas.getContext("2d")
context.strokeStyle = "#df4b26"
context.lineJoin = "round"
context.lineWidth = 8
pen = False
lastPoint = (0, 0)

def onmousemove(e):
  global lastPoint
  if pen:
    newPoint = (e.offsetX, e.offsetY)
    context.beginPath()
    context.moveTo(lastPoint[0], lastPoint[1])
    context.lineTo(newPoint[0], newPoint[1])
    context.closePath()
    context.stroke()
    lastPoint = newPoint

def onmousedown(e):
  global pen, lastPoint
  pen = True
  lastPoint = (e.offsetX, e.offsetY)

def onmouseup(e):
  global pen
  pen = False

canvas.addEventListener(&#x27;mousemove&#x27;, onmousemove)
canvas.addEventListener(&#x27;mousedown&#x27;, onmousedown)
canvas.addEventListener(&#x27;mouseup&#x27;, onmouseup)

%% raw
Using Python from Javascript

So far so good, but wouldn&#x27;t it be great to use Python from within Javascript as well? When you load Pyodide, you&#x27;ll get `pyodide` in the JS namespace, which lets you import anything on the Py side.

%% py
# python
class Foo:
    def __init__(self, val):
        self.val = val
foo = Foo(42)
foo
%% js
// javascript
var foo = pyodide.pyimport("foo")
foo.val

%% raw
## The Scientific libraries

The real power of Pyodide comes from its scientific computing libraries. So far we&#x27;ve compiled numpy, pandas, matplotlib, parts of scipy, and networkx. At the top of any py chunk, simply write something like `import numpy as np` and run the chunk, and it&#x27;ll begin the process of grabbing numpy.

%% py
import numpy as np
x = np.linspace(0, 2.0 * np.pi, 100)
y = np.sin(x)
y

%% raw

Matplotlib defaults to printing into the report preview, so you can run the code chunk below and see the plot. It&#x27;s easy to drag around the plot, zoom in, and zoom out, all pretty effortlessly.

%% py
from matplotlib import pyplot as plt
plt.figure()
plt.plot(x, y)
plt.show()

%% raw

It should be clear by now that Pyodide makes it so you don&#x27;t have to choose only one library, nor do you have to choose one language to do your data science. Let&#x27;s download Plotly and create the same graph, but send Plotly over to Python and plot it from within python itself.

Switch back to the console, and run the `%% fetch` chunk below (which fetches Plotly from a cdn), then run the `%% py` chunk below that, and switch back to the report view.

%% fetch
js: https://cdn.plot.ly/plotly-latest.min.js

%% py
from js import Plotly
from js import iodide
Plotly.plot(
    iodide.output.element(&#x27;div&#x27;),
    [{ &#x27;y&#x27;: y, &#x27;x&#x27;: x }],
)

Is there anything wrong on my end or does someone else have this behavior too ?

firejava commented 4 years ago

Error: Traceback (most recent call last): File "/lib/python3.7/site-packages/pyodide.py", line 57, in find_imports mod = ast.parse(code) File "/lib/python3.7/ast.py", line 35, in parse return compile(source, filename, mode, PyCF_ONLY_AST) File "", line 1 [0, 1, 32.0, 'foo', {'a': 10, 'b': '20'}] ^ SyntaxError: invalid syntax

_hiwire_throw_error (https://pyodide.cdn.iodide.io/pyodide.asm.js:8:38602) wasm-function[356]:0xfc617:: wasm-function[384]:0xfe3cb:: Object.Module.__findImports (https://pyodide.cdn.iodide.io/pyodide.asm.js:8:1989524) Object.Module.runPythonAsync (https://pyodide.cdn.iodide.io/pyodide.asm.js:8:43222

teonbrooks commented 4 years ago

hi @firejava, looks like there was some encoding error added to the notebook, which is leading to execution error. @mdboom, do you have a previous version of this notebook?

mdboom commented 4 years ago

I think the bug is in Iodide itself, not in the notebook content, as it's affecting all notebooks. I don't have a backup beyond the backups of the database already, but I think we need to fix the bug in iodide regardless.

firejava commented 4 years ago

if you look at the history, then copy and paste code there, it runs fine it looks like.

Your correct, it does appear to be encoding problem putting text into editor on load

if I paste here, it turns it correctly into what it should be...

simlan123 commented 4 years ago

Wow that was fast! Thanks :)