|
'use strict'; |
|
|
|
const { fetchFiles, fetchJSModules, fetchPaths, writeFile } = require('./_utils.js'); |
|
const { getFormat, loader, registerJSModule, run, runAsync, runEvent } = require('./_python.js'); |
|
const { stdio, buffered } = require('./_io.js'); |
|
const mip = (require('../python/mip.js')); |
|
const zip = (require('../zip.js')); |
|
|
|
const type = 'micropython'; |
|
|
|
|
|
|
|
const mkdir = (FS, path) => { |
|
try { |
|
FS.mkdir(path); |
|
} |
|
|
|
catch (_) { |
|
|
|
} |
|
}; |
|
|
|
module.exports = { |
|
type, |
|
module: (version = '1.22.0-356') => |
|
`https://cdn.jsdelivr.net/npm/@micropython/micropython-webassembly-pyscript@${version}/micropython.mjs`, |
|
async engine({ loadMicroPython }, config, url) { |
|
const { stderr, stdout, get } = stdio({ |
|
stderr: buffered(console.error), |
|
stdout: buffered(console.log), |
|
}); |
|
url = url.replace(/\.m?js$/, '.wasm'); |
|
const interpreter = await get(loadMicroPython({ linebuffer: false, stderr, stdout, url })); |
|
const py_imports = importPackages.bind(interpreter); |
|
loader.set(interpreter, py_imports); |
|
if (config.files) await fetchFiles(this, interpreter, config.files); |
|
if (config.fetch) await fetchPaths(this, interpreter, config.fetch); |
|
if (config.js_modules) await fetchJSModules(config.js_modules); |
|
|
|
|
|
this.writeFile(interpreter, './mip.py', mip); |
|
if (config.packages) await py_imports(config.packages); |
|
return interpreter; |
|
}, |
|
registerJSModule, |
|
run, |
|
runAsync, |
|
runEvent, |
|
transform: (interpreter, value) => interpreter.PyProxy.toJs(value), |
|
writeFile: (interpreter, path, buffer, url) => { |
|
const { FS, _module: { PATH, PATH_FS } } = interpreter; |
|
const fs = { FS, PATH, PATH_FS }; |
|
const format = getFormat(path, url); |
|
if (format) { |
|
const extractDir = path.slice(0, -1); |
|
if (extractDir !== './') FS.mkdir(extractDir); |
|
switch (format) { |
|
case 'zip': { |
|
const blob = new Blob([buffer], { type: 'application/zip' }); |
|
return zip().then(async ({ BlobReader, Uint8ArrayWriter, ZipReader }) => { |
|
const zipFileReader = new BlobReader(blob); |
|
const zipReader = new ZipReader(zipFileReader); |
|
for (const entry of await zipReader.getEntries()) { |
|
const { directory, filename } = entry; |
|
const name = extractDir + filename; |
|
if (directory) mkdir(FS, name); |
|
else { |
|
mkdir(FS, PATH.dirname(name)); |
|
const buffer = await entry.getData(new Uint8ArrayWriter); |
|
FS.writeFile(name, buffer, { |
|
canOwn: true, |
|
}); |
|
} |
|
} |
|
zipReader.close(); |
|
}); |
|
} |
|
case 'tar.gz': { |
|
const TMP = './_.tar.gz'; |
|
writeFile(fs, TMP, buffer); |
|
interpreter.runPython(` |
|
import os, gzip, tarfile |
|
tar = tarfile.TarFile(fileobj=gzip.GzipFile(fileobj=open("${TMP}", "rb"))) |
|
for f in tar: |
|
name = f"${extractDir}{f.name}" |
|
if f.type == tarfile.DIRTYPE: |
|
if f.name != "./": |
|
os.mkdir(name.strip("/")) |
|
else: |
|
dir = os.path.dirname(name) |
|
if not os.path.exists(dir): |
|
os.mkdir(dir) |
|
source = tar.extractfile(f) |
|
with open(name, "wb") as dest: |
|
dest.write(source.read()) |
|
dest.close() |
|
tar.close() |
|
os.remove("${TMP}") |
|
`); |
|
return; |
|
} |
|
} |
|
} |
|
return writeFile(fs, path, buffer); |
|
}, |
|
}; |
|
|
|
async function importPackages(packages) { |
|
const mpyPackageManager = this.pyimport('mip'); |
|
for (const mpyPackage of packages) |
|
mpyPackageManager.install(mpyPackage); |
|
} |
|
|
|
|