forked from jupyterlite/jupyterlite
-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: Robolite #1
Closed
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
4c3607c
WIP
datakurre b2cfba4
Add packaged jupyterlab_robotmode
datakurre 5509903
Fix error messages
datakurre d58e59c
Update robotkernel wheel
datakurre 1cb377a
Add robolite example
datakurre 01557d5
Add transient argument for publishExecutionResult
datakurre 5ba6abc
Update robotkernel wheel
datakurre d2ea5c8
Update robotkernel wheel
datakurre fc1ca36
Update robolite example
datakurre f7d62c1
Update robolite example
datakurre d3c05f5
Update robolite kernel banner
datakurre 10e8433
Update robolite kernel with changes for pyolite kernel
datakurre d72dc55
Add to support JSON traceback at publishExecutionError
datakurre a5fcad3
Update robolite example
datakurre f81c038
Merge branch 'main' into robolite
datakurre d96c37e
Add nix shell
datakurre 2c7fef3
Update robolite
datakurre c15e2af
Patch jupyterlite to generate pipliteUrls also for robolite
datakurre 77ccc5e
Add missing wheels
datakurre cbe7d7b
Update jupyter_lite_config.json
datakurre aac0dcd
Merge remote-tracking branch 'upstream/main' into robolite
datakurre 4e10ac8
Merge remote-tracking branch 'origin/robolite' into robolite
datakurre 92d8050
Merge branch 'main' into robolite
datakurre File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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
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
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
{ | ||
"metadata": { | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "robotframework", | ||
"version": 3 | ||
}, | ||
"file_extension": ".robot", | ||
"mimetype": "text/x-robotframework", | ||
"name": "robotframework", | ||
"nbconvert_exporter": "robotframework", | ||
"pygments_lexer": "robotframework", | ||
"version": "3.8" | ||
}, | ||
"kernelspec": { | ||
"name": "Robot Framework", | ||
"display_name": "Robot Framework", | ||
"language": "robotframework" | ||
} | ||
}, | ||
"nbformat_minor": 4, | ||
"nbformat": 4, | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"source": "## Robot Framework kernel for Jupyter Lite", | ||
"metadata": {} | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": "This notebook demonstrates the use of Robot Framework kernel for in-browser Jupyter Lite.", | ||
"metadata": {} | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": "At first we import `IPython.display` to have its display method as a keyword.", | ||
"metadata": {} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": "*** Settings ***\n\nLibrary IPython.display", | ||
"metadata": { | ||
"trusted": true | ||
}, | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": "Then we try out successful task that produces log and report:", | ||
"metadata": {} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": "*** Tasks ***\n\nThis task shall pass\n Should be equal 1 1", | ||
"metadata": { | ||
"tags": [], | ||
"trusted": true | ||
}, | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": "So, happy path works. Let's see next how the failing task also shows us stderr from the execution:", | ||
"metadata": {} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": "*** Tasks ***\n\nThis task shall fail\n Should be equal 1 2", | ||
"metadata": { | ||
"trusted": true | ||
}, | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": "It is also possible to define custom keywords. And make them require arguments.\n\nRobot Framework kernel injects widgets for the keywords to make it easier to try them out:", | ||
"metadata": {} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": "*** Keywords ***\n\nThis keyword displays a word\n [Arguments] ${word}=Hello world\n Display ${word}", | ||
"metadata": { | ||
"trusted": true | ||
}, | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": "Unfortunately, due to [a bug](https://github.com/jupyterlite/jupyterlite/issues/303) in Jupyter Lite ipywidgets integration, the button output does not fully work: output may replace button or appear in wrong location.\n\nAlso, the failing keyword below does not show its stderr as it should:", | ||
"metadata": {} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": "*** Keywords ***\n\nThis keyword should fail\n [Arguments] ${word}=Hello world\n Don't display ${word}", | ||
"metadata": { | ||
"trusted": true | ||
}, | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": "We expect these to be fixed pretty soon...", | ||
"metadata": {} | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": "Next, to the fancier features. Let's define inline Python module for custom Python keyword library:", | ||
"metadata": {} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": "%%python module HelloWorld\n\nclass HelloWorld:\n def hello_world(self):\n return \"Hello World!\"", | ||
"metadata": { | ||
"trusted": true | ||
}, | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": "Now this module can be safely imported as a keyword library:", | ||
"metadata": {} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": "*** Settings ***\n\nLibrary HelloWorld", | ||
"metadata": { | ||
"trusted": true | ||
}, | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": "And used in a task:", | ||
"metadata": {} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": "*** Tasks ***\n\nTry out HelloWorld keywords\n Hello world", | ||
"metadata": { | ||
"trusted": true | ||
}, | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": "Adding existing 3rd party keyword libraries is more tricky, though.\n\nAt first, in-browser Jupyter Lite can only support pure Python packages (or packages pre-compiled to WASM). At second, Robot Framework kernel in this integration does not expose API to interact with the underlying Python environment.\n\nA workaround is to define a custom in-line module and import it twice by executing the cell. The first execution will trigger asynchronous package download. Once the package has been downloaded, execution should work.", | ||
"metadata": {} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": "%%python module PackageManager\n\ntry:\n import OTP\nexcept ImportError:\n import micropip\n micropip.install([\"pyotp\", \"robotframework-otp\"])\n import OTP", | ||
"metadata": { | ||
"trusted": true | ||
}, | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": "*** Settings ***\n\nLibrary OTP", | ||
"metadata": { | ||
"trusted": true | ||
}, | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": "*** Tasks ***\n\nGet OTP from secret\n ${otp}= Get OTP base32secret3232", | ||
"metadata": { | ||
"trusted": true | ||
}, | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": "Finally, we learn to interact with the world from in-browser Jupyter Lite. Because the underlying Python implementation does not yet have `http.client`, we can only do request with JavaScript API, only using synchronous version of XMLHttpRequest, only for resources that support CORS.", | ||
"metadata": {} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": "%%python module API\n\nfrom js import XMLHttpRequest\n\nimport json\n\n\nclass API:\n def get_data(self):\n url = f\"https://reqres.in/api/users\"\n request = XMLHttpRequest.new()\n request.open(\"GET\", url, False)\n request.send(None)\n assert request.status == 200\n return json.loads(request.responseText)", | ||
"metadata": { | ||
"trusted": true | ||
}, | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": "*** Settings ***\n\nLibrary API", | ||
"metadata": { | ||
"trusted": true | ||
}, | ||
"execution_count": null, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": "*** Tasks ***\n\nGet some data\n ${data}= Get data", | ||
"metadata": { | ||
"trusted": true | ||
}, | ||
"execution_count": null, | ||
"outputs": [] | ||
} | ||
] | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# https://github.com/nmattia/niv | ||
{ sources ? import ./sources.nix | ||
, nixpkgs ? sources."nixpkgs" | ||
}: | ||
|
||
let | ||
|
||
overlay = _: pkgs: rec { | ||
jupyterWith = pkgs.callPackage ./pkgs/jupyterWith {}; | ||
poetry2nix = pkgs.callPackage ./pkgs/poetry2nix { inherit nixpkgs; }; | ||
jupyterLiteEnv = pkgs.callPackage ./pkgs/jupyterLiteEnv{}; | ||
}; | ||
|
||
pkgs = import nixpkgs { | ||
overlays = [ overlay ]; | ||
}; | ||
|
||
in pkgs |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ poetry2nix }: | ||
|
||
poetry2nix.mkPoetryEnv { | ||
projectDir = ./.; | ||
overrides = poetry2nix.overrides.withDefaults (self: super: { | ||
jupyterlite = super.jupyterlite.overridePythonAttrs(old: { | ||
src = ../../../py/jupyterlite; | ||
nativeBuildInputs = [ self.flit-core ]; | ||
}); | ||
}); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this isn't necessary, as it's entirely possible to package up a lite kernel as a pip-installable, prebuilt extension... it's a much smaller webpack burden, for sure, which is always good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bollwyvl Yes! The pip-packages are already hatching here https://github.com/robots-from-jupyter/robotkernel/tree/robolite/lite/jupyterlite-robotkernel/packages and will be merged into master once I'm ready.
You may recall that initially I just grepped everything
pyolite
and copied them torobolite
to makerobotkernel
work :)I still need this fork for the hack for Camunda integration, until I learn to make it otherwise: 1) I want to have a custom JS package available for pyolite 2) I need to populate os.environ with a few variables from Camunda. (I could pinpoint those lines ones I have manged to update that branch.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right, so your kernel extension will have a
worker.ts
, which is what can actually touchpyodide
. It is somewhat limiting, as it doesn't get webpacked, it can't reallyimport
anything, directly, and you'll need to get it the absolute URL of the library you're importing, and inkernel.ts
, add anotherimportScripts
.Then, inside
worker.ts
, after everything else gets set up, you'll have access to the readypyodide
andpyolite
. On pidgy, we happen to only need to hack python stuff, but having JS works as well.Note that some of the scoping is a little wonky: if you want somehting to be imported for real, you might have to put it into
user_ns
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now I resolved my Camunda-needs by following pidgy / robotkernel approach for custom lite package and copy & pasted custom pyolite and robotkernels with required hacks.