Communicate with JavaScript modules

In JavaScript you can use modules.

I want to use this JavaScripts modules in pyscript. What is the way to include that?

`<html>
    <head>
        <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
        <script defer src="https://pyscript.net/latest/pyscript.js"></script>
   
        <script type="module" src="canvas.js"></script>
        <script type="module" src="square.js"></script>
    </head>
    <body>
        <py-title>javascript modules</py-title>
    <py-script>
#

from js.canvas import create, createReportList
from js.square import name, draw, reportArea, reportPerimeter 
from js.square import randomSquare

from js import document

myCanvas = create('myCanvas', document.body, 480, 320)
reportList = createReportList(myCanvas.id)

square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue')

reportArea(square1.length, reportList)
reportPerimeter(square1.length, reportList)

square2 = randomSquare(myCanvas.ctx)
        </py-script>
    </body>
</html>

That brings an error.

Best regards Hebi

1 Like

dear hebi.

thank you for posting.
You may want to refer to Jhon Hanley’s article, which is also written here.

Since pyscript uses pyodide,

from pyodide import to_js

I think you need

Regards, you.
ktsh.tanaka.2020

Hello,

I like this article from John Hanley, but it is not about JavaScript modules.

Thanks.

Best regards Hebi

2 Likes

You can get pretty close to this behavior by doing something like:

<script type="module" src="canvas.js"></script>
<script>
    async function main(){
      canvas = await import('./canvas.js')
      create = canvas.create
  }
  main();
</script>

<py-script>
  from js import create

  ctx = create('myCanvas', document.body, 480, 320).ctx
  ctx.fillStyle = "blue"
  ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height)
</py-script>

For some reason, importing canvas directly in Python (either in pyodide.runPython() or in py-script) breaks the import functionality with a TypeError:

import canvas
Python exception:
Traceback (most recent call last):
  File "/lib/python3.10/site-packages/_pyodide/_base.py", line 429, in eval_code
    .run(globals, locals)
  File "/lib/python3.10/site-packages/_pyodide/_base.py", line 300, in run
    coroutine = eval(self.code, globals, locals)
  File "<exec>", line 2, in <module>
  File "<frozen importlib._bootstrap>", line 1075, in _handle_fromlist
JsException: TypeError: Cannot read properties of undefined (reading 'name')

And registerJsModule also fails with the “cannot read properties of undefined” error.

As a hack you can always do something like :

for (const property in canvas){
  window[property] = canvas[property]
}

Which will make all the properties defined in canvas.js into global objects that you can import into Pyodide. It’s definitely feels crude though.

2 Likes

Well, after all that fooling around, it turns out the issue with “Cannot read properties of undefined” is fixed in Pyodide 0.21.0a3 as per Issue #2901.

So when Pyodide 0.21 is released, you could just do:

<script>
  (async () => { canvas = await import('./canvas.js') })()
</script>
<py-script>
  # confirm we're really running 0.21
  import pyodide_js
  print(f"{pyodide_js.version= }") 

  from js import canvas
  ctx = canvas.create('myCanvas', document.body, 480, 320).ctx
  ctx.fillStyle = "blue"
  ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height)
</py-script>

Result:
image

Unfortunately, contrary to what the reporter of that issue said, it seems loading runtimes from a URL via py-config is currently disabled (as of 2022.06.1), so I had to make the example above work by building pyscript from source with the default runtime source set to https://pyodide-cdn2.iodide.io/dev/full/pyodide.js)

But leaving this here for the future, since importing js modules like python modules feels just swell.

2 Likes

Thanks @JeffGlass looks great.

I will try it with different modules.

Best regards Hebi

1 Like

Dropping back in to say - the PyScript core devs just merged PR #719, updating Pyodide to Version 21.1. So if you link to the unstable PyScript release, you can try that functionality today, or it will be available in the next PyScript release.

1 Like