Created
March 9, 2024 06:58
-
-
Save sneakers-the-rat/fc1387f9e90c7e5f6eaa4dc8f21b8407 to your computer and use it in GitHub Desktop.
LinkML Pydanticgen in the browser with Pyodide
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<script src="https://cdn.jsdelivr.net/pyodide/v0.25.0/full/pyodide.js"></script> | |
<link rel="stylesheet" href="https://unpkg.com/@highlightjs/cdn-assets@11.9.0/styles/default.min.css"> | |
<script src="https://unpkg.com/@highlightjs/cdn-assets@11.9.0/highlight.min.js"></script> | |
<!-- and it's easy to individually load additional languages --> | |
<script src="https://unpkg.com/@highlightjs/cdn-assets@11.9.0/languages/python.min.js"></script> | |
<script src="https://unpkg.com/@highlightjs/cdn-assets@11.9.0/languages/yaml.min.js"></script> | |
</head> | |
<body> | |
<div id="boxes" style="display: flex; flex-direction: row; width: 100%; align-items: stretch; position:absolute; height: 100%;"> | |
<div id="schemabox" style="width: 100%; flex-grow:1; padding: 1em; display: flex; flex-direction:column;"> | |
<p>Schema:</p> | |
<textarea id="code" class="language-yaml" style="width: 100%; flex-grow: 1;"> | |
id: https://w3id.org/linkml/examples/pyodide | |
name: pyodide | |
description: |- | |
Oh look its linkml in the browser | |
license: https://creativecommons.org/publicdomain/zero/1.0/ | |
default_curi_maps: | |
- semweb_context | |
imports: | |
- linkml:types | |
default_prefix: pyodide | |
default_range: string | |
classes: | |
Lol: | |
description: laughing out loud | |
slots: | |
- id | |
- name | |
- websites | |
Lmao: | |
description: |- | |
An additional indication of laughter | |
relating to the ass becoming displaced. | |
slots: | |
- place | |
- ass | |
- last_seen | |
slots: | |
id: | |
identifier: true | |
name: | |
websites: | |
multivalued: true | |
place: | |
ass: | |
range: boolean | |
last_seen: | |
any_of: | |
- range: date | |
- range: datetime | |
multivalued: true | |
</textarea> | |
</div> | |
<div id="outputbox" style="width: 100%; flex-grow:1; padding: 1em; display: flex; flex-direction: column;"> | |
<p>Output:</p> | |
<pre style="width: 100%; flex-grow:1;" disabled><code class="language-python" id="output"></code></textarea> | |
</div> | |
<div id="consolebox" style="width: 100%; flex-grow:1; padding: 1em; display: flex; flex-direction: column;"> | |
<p>Console:</p> | |
<textarea id="console-input" style="width: 100%; flex-grow: 1;"></textarea> | |
<textarea id="console-output" id="console-input" style="width: 100%; flex-grow: 5;" disabled></textarea> | |
</div> | |
</div> | |
<script> | |
const output = document.getElementById("output"); | |
const code = document.getElementById("code"); | |
const consoleinput = document.getElementById("console-input"); | |
const consoleoutput = document.getElementById("console-output"); | |
function addToOutput(s) { | |
// output.value += ">>>" + code.value + "\n" + s + "\n"; | |
output.innerHTML += "\n" + s; | |
} | |
output.value = "Initializing...\n"; | |
// init Pyodide | |
async function main() { | |
let pyodide = await loadPyodide(); | |
await pyodide.loadPackage("micropip"); | |
const micropip = pyodide.pyimport("micropip"); | |
let packages = [ | |
"linkml", | |
"linkml_runtime", | |
"rdflib", | |
"isodate", | |
"six", | |
"prefixcommons", | |
"requests", | |
"prefixmaps", | |
"curies", | |
"pydantic", | |
"https://hackers.piracy.solutions/PyTrie-0.4.0-py3-none-any.whl", | |
"sortedcontainers", | |
"pyyaml", | |
"deprecated", | |
"wrapt", | |
"jsonasobj2", | |
"hbreader", | |
"ssl", | |
"jinja2", | |
"json_flattener", | |
"python-dateutil", | |
"jsonasobj", | |
"click", | |
"ShExJSG", | |
"pyjsg", | |
"sqlalchemy" | |
] | |
addToOutput('Installing packages...') | |
for await (const package of packages) { | |
await micropip.install(package, keep_going = true, deps = false); | |
addToOutput('Installed: ' + package); | |
} | |
let initial_load = pyodide.runPython(` | |
from linkml.generators.pydanticgen import PydanticGenerator | |
from linkml_runtime.loaders.yaml_loader import YAMLLoader | |
from linkml_runtime.linkml_model import SchemaDefinition | |
`) | |
addToOutput(initial_load) | |
async function evaluateSchema() { | |
output.value = "generating..." | |
try{ | |
let generated = pyodide.runPython(` | |
sch = YAMLLoader().load_any(target_class=SchemaDefinition, source="""${code.value}""") | |
gen = PydanticGenerator(sch) | |
gen.serialize() | |
`) | |
pyodide.runPython(generated); | |
output.removeAttribute('data-highlighted'); | |
output.innerHTML = generated | |
} catch (err) { | |
output.value = err; | |
} | |
hljs.highlightAll(); | |
} | |
async function evaluateConsole(){ | |
try { | |
consoleinput.disabled = true; | |
let output = pyodide.runPython(consoleinput.value); | |
addToConsole(output); | |
consoleinput.value = ""; | |
} catch (err) { | |
addToConsole(err); | |
} | |
consoleinput.disabled = false; | |
} | |
function addToConsole(s) { | |
consoleoutput.value += ">>>" + consoleinput.value + "\n" + s + "\n"; | |
} | |
await evaluateSchema(); | |
code.addEventListener('input', evaluateSchema); | |
consoleinput.addEventListener('keypress', (event) => { | |
if (event.key === "Enter" && !event.shiftKey){ | |
event.preventDefault(); | |
evaluateConsole() | |
} | |
}) | |
return pyodide; | |
} | |
let pyodideReadyPromise = main(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
as seen on https://github.com/orgs/linkml/discussions/1963