Skip to article frontmatterSkip to article content

here is an attempt to embed a dynamic nbautoeval activity

this is not yet working, because

the following code could help in downloading & importing it, provided that we could deposit the exercise code under e.g. _static/exo_pgcd.py
but that’s not something that is currently possible with myst I’m afraid

# this code seems OK, it computes the current window's location
# and messes with it to come up with the URL for e.g. an exercice .py code
# assuming it is stored in _static
# and assuming also that myst lets us expose the contents of _static

import js, asyncio, io, os

async def fetch_static_to_file(filename):
    # Try several JS expressions that *may* give the page URL
    page_url = None
    for expr in ("globalThis.location.href", "self.location.href", "location.href"):
        try:
            v = js.eval(expr)
            if v:
                page_url = str(v)
                break
        except Exception:
            continue

    if page_url:
        base = page_url.rsplit("/", 1)[0]
        url = f"{base}/_static/{filename}"
    else:
        # fallback to a relative path (often works because fetch resolves relative to the page)
        url = f"_static/{filename}"

    print("Fetching:", url)
    resp = await js.fetch(url)
    if not resp.ok:
        raise RuntimeError(f"fetch failed with status {resp.status} for {url}")
    text = await resp.text()
    # write to Pyodide virtual filesystem
    with open(filename, "w", encoding="utf-8") as f:
        f.write(str(text))

# Usage (in a cell that allows top-level await):
await fetch_static_to_file("exo_pgcd.py")
import exo_pgcd
# now use exo_pgcd
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[1], line 6
      1 # this code seems OK, it computes the current window's location
      2 # and messes with it to come up with the URL for e.g. an exercice .py code
      3 # assuming it is stored in _static
      4 # and assuming also that myst lets us expose the contents of _static
----> 6 import js, asyncio, io, os
      8 async def fetch_static_to_file(filename):
      9     # Try several JS expressions that *may* give the page URL
     10     page_url = None

ModuleNotFoundError: No module named 'js'
# hopefully tmp
# need to gain control on the preloaded packages

%pip install nbautoeval
# exo_pgcd being under corrections/
from exo_pgcd import exo_pgcd

exo_pgcd.example()
# maybe some day one will be allowed to change the cell content
# before running it

def pgcd(a, b):
    return b % a
exo_pgcd.correction(pgcd)

leftovers


# trash me
# this is cell to introspect the js object and find where
# we find the 'location' information so we can build the URL
# where to fetch static stuff

import js

cands = ["window", "globalThis", "self", "location", "document"]
print("hasattr on js:", {c: hasattr(js, c) for c in cands})

for expr in (
    "globalThis.location.href",
    "self.location.href",
    "location.href",
    "document.location && document.location.href",
    "window && window.location.href",
):
    try:
        v = js.eval(expr)
        print(f"{expr} ->", v)
    except Exception as e:
        print(f"{expr} -> error: {type(e).__name__}: {e}")
# trash me

# this code allows to inspect the contents of a Python module
# it won't work with `js` though because it is of some special nature...

from IPython.display import HTML, JSON, Latex, Markdown

def clean(mod_dict):
    result = dict()
    for k, v in mod_dict.items():
        if isinstance(v, (int, float, str, bool, list, tuple)):
            result[k] = v
        elif isinstance(v, dict):
            result[k] = clean(v)
        else:
            result[k] = '--foreign--'
    return result

def inspect_module(mod):
    try:
        return JSON(clean(mod.__dict__))
    except:
        return JSON(clean(mod))