robots-from-jupyter / robotkernel

Robot Framework IPython kernel for Jupyter Notebook and JupyterLab
BSD 3-Clause "New" or "Revised" License
74 stars 16 forks source link

Consider adding live demo with binder? #2

Closed bollwyvl closed 6 years ago

bollwyvl commented 6 years ago

Howdy! I must confess, I was looking for kernels that already ran on, you know, robots, but am glad I found this. This is really great work! The embedded, base64-encoded reports are a truly glorious hack.

Anyhow, Binder is a service from Jupyter (uses JupyterHub under the hood) that builds on-demand images and serves them up to whoever wants them from any github repo.

Here's a branch that started off adding a live binder demo, but ended up adding some more stuff: icon, package structure, install command, probably other stuff. If you're interested, I can work it up into a better PR that doesn't stomp all over your existing stuff.

While JupyterLab doesn't support kernel.js, and upstreaming to CM is the Right Thing To Do, in the nearterm we could likely hack up a lab extension to support that. Everything else works fine, including those marvelous reports!

screenshot from 2018-04-04 00-24-09

Keep up the good work!

datakurre commented 6 years ago

@bollwyvl Thank you for the nice words! I'm sorry that I forgot to follow this repository and your work fell under my radar.

I have some opinions, which prevent me to merge your work as such, but please keep your branch alive so that I can use it as a reference when I get chance to work on this again.

I definitely want to make this usable with Jupyterlab.

bollwyvl commented 6 years ago

Oh, no worries! Real quick: would you mind throwing a license on the work? Happy to contribute back individual pieces that are interesting!

On Sun, Aug 12, 2018 at 5:50 AM Asko Soukka notifications@github.com wrote:

@bollwyvl https://github.com/bollwyvl Thank you for the nice words! I'm sorry that I forgot to follow this repository and your work fell under my radar.

I have some opinions, which prevent me to merge your work as such, but please keep your branch alive so that I can use it as a reference when I get chance to work on this again.

I definitely want to make this usable with Jupyterlab.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/datakurre/robotkernel/issues/2#issuecomment-412331190, or mute the thread https://github.com/notifications/unsubscribe-auth/AACxRAqBdqV2CwZr0QbLso0HwToSWu-mks5uP_pXgaJpZM4TGKDH .

datakurre commented 6 years ago

@bollwyvl Thanks for asking for the license. It's now licensed under BSD 3-Clause.

bollwyvl commented 6 years ago

Hooray!

The only real thing that doesn't work in Jupyterlab is the syntax highlighting... It takes a bit of wrapping and registering. I'll try to get a labextension together quickly that just does that...

On Sun, Aug 12, 2018, 10:20 Asko Soukka notifications@github.com wrote:

@bollwyvl https://github.com/bollwyvl Thanks for asking for the license. It's now licensed under BSD 3-Clause.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/datakurre/robotkernel/issues/2#issuecomment-412346145, or mute the thread https://github.com/notifications/unsubscribe-auth/AACxRNJ3AwBO9xXcGarjBiDjEWEt6YVcks5uQDmogaJpZM4TGKDH .

datakurre commented 6 years ago

@bollwyvl Thanks for your help. I have now migrated your recommendations for kernel installation and binder support.

README also has now Binder links for Notebook and Lab

Jupyter Notebook: https://mybinder.org/v2/gh/datakurre/robotkernel/master?urlpath=tree/example.ipynb

Jupyter Lab: https://mybinder.org/v2/gh/datakurre/robotkernel/master?urlpath=lab/tree/example.ipynb

I've not managed to create working Jupyter lab extension for CodeMirror mode yet. The code is here https://github.com/datakurre/robotkernel/tree/master/src/jupyterlab_robotmode and it is installed with Binder.

Also those fancy log links don't seem to work for me with Jupyter Lab.

datakurre commented 6 years ago

I opened issues for the lab issues https://github.com/datakurre/robotkernel/issues/5

bollwyvl commented 6 years ago

Very exciting!

I've been working on a Day Job in-house fork of robotkernel that I am hoping to get open sourced soon... it is subclasses ipykernel, rather than base, and does:

  • inspection & completion driven by libdoc
  • rewritten syntax highlighting
  • rewritten status during run
  • linting & formatting (as magics)
  • unit and integration tests
  • rich display

I'm into an internal beta test with it, and then have to do some documentation work, but would like to share it soon!

datakurre commented 6 years ago

@bollwyvl Thanks for the update. That's even more exciting! Sounds like you have made JupyterLab a fully featured robot IDE... Please, keep me up-to-date how the open sourcing progresses. If you kept the name, I should probably pass the PyPI reservation for you when that happens :)

datakurre commented 6 years ago

@bollwyvl Any chance that you are planning to submit a talk to http://robocon.io/ (next January in Finland, CFP opens within the next weeks) about your robotkernel work and use-cases? If not, I'll submit mine.

bollwyvl commented 6 years ago

Thanks for the update

Shame on me for not updating sooner! It's too bad we're duplicating work, but there is definitely value in multiple implementations and perspectives: I'm carrying a lot of conda and Jupyter baggage, and am relatively new to robot... though I tell you, writing a faithful syntax highlighter and completer with tests will get you up to speed REAL FAST.

If you kept the name, I should probably pass the PyPI reservation for you when that happens :)

I was actually thinking of ipyrobotframework, to more concretely reflect that it still has all the IPython goodies under the hood...

Sounds like you have made JupyterLab a fully featured robot IDE...

That's the goal! I desperately want to get my code out there, but since The Man is paying for the work, I have to follow procedures.

Any chance that you are planning to submit a talk

Actually I was! However, the cost might be prohibitive for me to attend in person, so it would make sense to collaborate. Indeed, it would be a sporty 30 minutes plus questions, as I have a whole boatload of in-house work around Robot going on. Maybe also submit a training session?

Not on company time, but would like to present some how, I'm also doing some exploratory work (also in JupyterLab) for rich input types including blockly.

The idea here would be to have a libdoc -> blockly JSON -> blockly blocks -> Robot workflow to allow visual authoring. The first cut will be to get it to work, but the long con is having additional output types that can register new blocks and code generators from kernels... like ipyrobotframework.

Exciting times!

bollwyvl commented 6 years ago

Oh, and another thing which I intend to work with: Execute_request from lab also sends the client-only cell id (a uuid) in the metadata. This would allow robot_history (which I have kept, for lack of anything better) to become an OrderedDict, with subsequent executions replacing rather than appending... This is good, as some settings don't like being applied multiple times, which makes interactive tuning hard.

For the nbconvert case, this shouldn't matter...

bollwyvl commented 6 years ago

Yeah, so turns out you get not only clientId, but also deletedCells.

I put it in, and no longer get Setting was already set, etc. when interactively building things.

Basically,

bollwyvl commented 6 years ago

(whoops, sent too early)

... to pass in the parent['metadata'] around here

And away you go!

Anyhow, I got some buy-in from The Man on submitting the talk (with a requisite open-sourcing prior), so who knows! I'm sure Helsinki in January is lovely!

datakurre commented 6 years ago

@bollwyvl I recall I was really missing cell id's and deleted cells. That's great news! But those are only in Lab, so the kernel needs to fallback to previous behavior without them?

Blocky / visual editing sounds interesting also from "RPA" perspective (there is some push currently for Robot Framework into "RPA" markets). Do you have anything public on that yet?

I'm sure it is enough to send one talk submission about Jupyter. Ping me if you need a co-author :-)

Helsinki sure is lovely in January if it happens to get snow in time. Otherwise, not that much (dark, wet, chilly and windy)...

bollwyvl commented 6 years ago

fallback to previous behavior without them?

Right: the fallback (random cellid) is first in, first replayed... The ordereddict takes care of the rest, preserving the original behavior. I suppose you could also use the hash of the content, to avoid trivial repetition.

Do you have anything public on that yet?

Just this branch... Doesn't even work on binder, yet, because I'm still figuring out how to do it, and don't want to check in 50k of generated xml and json:

Initially, I am building it offline and bundling into the front end along with a hacked python generator. The idea, however, is to have the kernel emit content types for:

Which would update a custom generator (e.g Blockly.RobotFramework). This could be taught how to make python and javascript for keywords that spoke those languages.

Then there are a number of ways to model a domain with blocks

For example, a suite "hat" block could have two "shelves" which accept settings and variables, while each test or keyword "hat" block could have a "shelf" for bracket settings, and another for keywords and variable assignments. As usual, templates mess everything up, so you'd need a whole separate approach for them.

Anyhow, tons to do there, but not on anybody's critical path, so it will be slow going.... But would definitely add some validation of the robotkernel model.

Another rich output straight out of RIDE would be the tables, a la

https://github.com/quantopian/qgrid

Ping me if you need a co-author :-)

Right! Will do!

datakurre commented 6 years ago

Thanks for the insight into your blocky work.

So, blocky editor itself could be a JupyterLab extension, but it requires support from the kernel to parse robot libraries and keywords into blocky models?

Should the blocky extension parse robot syntax or should robot have parser for blocky json?

bollwyvl commented 6 years ago

Thanks for the insight into your blocky work.

Thanks for listening!

So, blocky editor itself could be a JupyterLab extension, but it requires support from the kernel to parse robot libraries and keywords into blocky models?

Requires is a strong word: heck, i'm pretty sure you could run robot right in the browser. But ignoring that for a moment, I'm trying to reuse existing machinery to the extent possible.

In Lab, you have a few choices for getting new ui in:

Should the blocky extension parse robot syntax or should robot have parser for blocky json?

bollwyvl commented 6 years ago

(oops, sent too early, again)

Aside from BuiltIn (which maybe could be, well, built in), everything else is so dynamic, and might not be readily accessible to the notebook contents server. So having the js side do too much of that work is probably a lot to ask, but could step in for certain cases, e.g. multiple open notebooks.

Should the blocky extension parse robot syntax or should robot have parser for blocky json?

Aye, there's the rub. Blockly blocks are defined in JSON, but a configuration of a blockly workspace is defined in XML, and I feel like there are enough unschema-ed XML documents flying around at this point. Blockly desperately wants to not be a language, and instead a code generator, though folks have gone pretty far down that road, as well.

Anyhow, I feel like keeping the kernel (and robot) parsing the almost-human-readable content as a priority, with things like blockly, or RIDE-style spreadsheets, as purely authoring tools.

datakurre commented 6 years ago

@bollwyvl Thanks again. I’ll return to this in a couple of weeks. I’ll probably expriment with these topics myself already with robotkernel, because we started to use it for RPA development by ourselves and all this would fit perfectly also with our use case.

bollwyvl commented 6 years ago

Upps, looks like the CFP is up:

https://groups.google.com/forum/m/#!topic/robotframework-users/op2im19Ifuc

So do we shoot for a 25 minute one and a workshop? I think the short one will be just enough time to introduce the work, but it would be interesting to roll up with a workshop that looked at how a team with a JupyterHub and a GitLab could work on ATDD and RPA problems together. I'll pretty up the abstract I started and add you as an editor.

I've done most of the busy work for our open source process, so I am pretty confident I can get something out there in time.

I've been giving some internal demos and getting feedback. People are very excited, but also want a lot! For example, some folks would like to start typing "click the [${button}] button on window [${window}]" and get completion of possible values for the two variables, where the values are stored in a JSON file. I haven't dug into the new types-based stuff in 3.1, but this seems pretty challenging... But a lot better than the previous regex-based stuff!

I also ended up redoing libdoc output to work in lab, and have been working on importing notebooks.... Ipython notebooks work fine, thanks to importnb, but importing robot notebooks will require some much deeper monkeypatching to Namespace, or something... It would be very unsatisfying to have to dump out to .robot (or .resource) files to be able to reuse things, but I might end up doing that first.

datakurre commented 6 years ago

@bollwyvl 25 minute talk and workshop sound good. Too bad that the workshops are before the talk. Would you also be able to stay for the sprints on Friday?

I'be been playing catchup on my legacy kernel: simple auto-completion, keyword / section documentation as inspections, and use of cellId and deletedCells.

A more interesting one was "sticky webdriver sessions" https://github.com/datakurre/robotkernel/blob/master/src/robotkernel/listeners.py#L149 so that when browsers are not closed in teardown, subsequent cell executions may re-use the created webdrivers until kernel is shutdown.

Maybe variable autocompletion could use those sticky webdriver sessions look the available selectros directly from the browser?

I was not aware of importnb. For parsing robot notebooks, why didn't the same TestCaseString parser work that robotkernel uses? https://github.com/datakurre/robotkernel/blob/master/src/robotkernel/model.py

datakurre commented 6 years ago

@bollwyvl Let me elaborate that "sticky webdriver sessions" option for element autocompletion:

When cell execution with test cases is completed, I save those SeleniumLibrary webdriver sessions that remain open, including the info of the current session. That sessions remains open as long as kernel is running. Kernel shutdown closes the sessions. When new cell with test cases is executed, I populate SeleniumLibrary webdriver cache (and current webdriver) from the kernel.

So, user could start with a dummy test with just Open browser or Go to and execute it. The opened browser remains open after shell execution. Kernel knows the current window and has access to it. And the completion call could make synchronous webdriver calls to get a list of available selectors (eg. list all ids to autocomplete id:-selector) from the open browser.

bollwyvl commented 6 years ago

Would you also be able to stay for the sprints on Friday?

If I'm crossing an ocean, I bet I can swing the full week.

why didn't the same TestCaseString parser work that robotkernel uses

Oh, that's one of the things that I haven't changed much, though I ended up adding a couple more things, and split them out as a set of in-memory string-based things that might eventually be worth proposing for inclusion in RF core.

The bigger issue becomes robot notebooks importing robot notebooks importing... with importnb, this is handled by patching the actual FileFinder in python itself, so it works without much innovation on my part, as everything ends up in a module. In the robot case, as additional magics become available, the kernel needs to be able to evaluate each cell as things get parsed.

"sticky webdriver sessions"

That's a pretty exciting case. Will check it out!

For library-by-library features (RESTInstance, SeleniumLibrary, etc.), I would see those as hooks into lifecycle events of the in-memory robot and the kernel... similar to the %reload_ext magic in IPython, and the various mechanims it can use.

There are advantages and disadvantages to a monorepo with a contrib folder: it's great if you can test them all together, but I wouldn't want to force someone doing AutoIt to install Selenium stuff, for example. Lots to think about!

datakurre commented 6 years ago

The bigger issue becomes robot notebooks importing robot notebooks importing...

Ok. For me this sounds like that robot notebooks could be handled as Resources in Robot Framework and they might work with implementing ipynb parsing support into Robot Framework itself. By following the implementation of ReST-parser it should not actually be too much of work (it is a bit similar in that it parses ReST-files with Docutils and then just exracts contents of .. code:: robotframework-directives. Here we would extract contents of robot cells.

datakurre commented 6 years ago

Auto-completion for simple selectors works quite ok

https://www.youtube.com/watch?v=YFIUP_Eno_U

I guess, you already have auto-completion for variables.

bollwyvl commented 6 years ago

Oh yeah, that's looking great. This is a very useful pattern for me to study to figure out how to encapsulate and reproduce for other execution environments. For example, say a user wants to use a GraphQLLibrary, SwaggerLibrary, or DBLibrary, all of which would have clients which would support good enumeration of values for different arguments of different keywords. I would see each of these as being separately installable (from both the kernel and the library), which use an Appropriate Mechanism (e.g. entry_points, namespace packages, or (shudder) magic naming) to enhance some aspect, be it completion or inspection, but would need access to the library's core capability outside of test execution.

On my side, local/automatic variable completion mostly works. there's only so much you can do once people start using extended syntax, though I do have a bit of logic in the syntax highlighting... Think it's just python, but I probably need regex, too.

I am not hooking a listener for global variable definition, yet, I don't think, e.g. from imported variables, but it's probably just another listener... Though I did start doing some eager importing, as it bothered me that I had to actually run a test before getting docs and completion. it might be many of my listeners aren't even doing anything anymore.

Similarly not enumerating environment variables... Not sure how useful that would actually be.

datakurre commented 6 years ago

Logical next step for selector auto-completion is probably to let user pick the element directly from the browser, though, UX is not trivial: https://www.youtube.com/watch?v=-gU4srzslpc

bollwyvl commented 6 years ago

Hm... Maybe inject a visible marker on the browser screen and move it around, do hit testing and selector building. Then update a display handle... Or set_next_input to some last known state (when completion started), completing the token. Or some entirely separate comms.

But yeah, pretty gross to get right, but very rewarding!

On Wed, Oct 17, 2018, 14:00 Asko Soukka notifications@github.com wrote:

Logical next step for selector auto-completion is probably to let user pick the element directly from the browser, though, UX is not trivial: https://www.youtube.com/watch?v=nW1bpBUOWrg

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/datakurre/robotkernel/issues/2#issuecomment-430728296, or mute the thread https://github.com/notifications/unsubscribe-auth/AACxRCoq7qTC6mpXIiNOvJQru9eVnM2Xks5ul3A8gaJpZM4TGKDH .

bollwyvl commented 6 years ago

Re: reverse selection:

https://github.com/gmmorris/simmerjs

datakurre commented 6 years ago

Already using simmerjs in that picker :)

I also looked that it might be possible to hook into JupyterLab completion menu in labextension and highlight elements while going through the options, but I left that for later... (picker was hanging lower...)

datakurre commented 6 years ago

Very rewarding. This makes already great demos, but next needs some time to see how simmerjs works in real life.

Meanwhile, I’ll look into ipynb robotframework parser support later this week. I expect that it would make ”Resource notebook.ipynb” work recursively. On 18 Oct 2018, 0.48 +0300, Nicholas Bollweg notifications@github.com, wrote:

Hm... Maybe inject a visible marker on the browser screen and move it around, do hit testing and selector building. Then update a display handle... Or set_next_input to some last known state (when completion started), completing the token. Or some entirely separate comms.

But yeah, pretty gross to get right, but very rewarding!

On Wed, Oct 17, 2018, 14:00 Asko Soukka notifications@github.com wrote:

Logical next step for selector auto-completion is probably to let user pick the element directly from the browser, though, UX is not trivial: https://www.youtube.com/watch?v=nW1bpBUOWrg

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/datakurre/robotkernel/issues/2#issuecomment-430728296, or mute the thread https://github.com/notifications/unsubscribe-auth/AACxRCoq7qTC6mpXIiNOvJQru9eVnM2Xks5ul3A8gaJpZM4TGKDH .

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub, or mute the thread.

datakurre commented 5 years ago

@bollwyvl With this robotframework branch it is possible to run "robot something.ipynb" or use "Resource something.ipynb" https://github.com/datakurre/robotframework/tree/feature/nbsupport

Probably it needs support for multikernels, but I'm not sure do they have standard way to define the language of the current cell.

Getting that upstream would need proper testing and documentation, but probably possible.

bollwyvl commented 5 years ago

Cool stuff!

On Tue, Oct 30, 2018, 14:14 Asko Soukka notifications@github.com wrote:

@bollwyvl https://github.com/bollwyvl With this robotframework branch it is possible to run "robot something.ipynb" or use "Resource something.ipynb" https://github.com/datakurre/robotframework/tree/feature/nbsupport

my only comment on the implementation:

I would be considerate of the nb version... You can up and down convert, so you may wish to read as whatever, then convert to 4.

Probably it needs support for multikernels, but I'm not sure do they have

standard way to define the language of the current cell.

Per cell language might be added in the future, but the language name, as distinct from the kernel name, only exists (in format 4) at the Notebook level, and is required, so you can tell on it:

https://github.com/jupyter/nbformat/blob/master/nbformat/v4/nbformat.v4.schema.json

So something like...

assert notebook.metadata.language_info.name == "robotframework"

Also, it's not going to support magics... So you may need to fail if it finds them. Otherwise, a fair amount of logic would have to bleed over from either implementation... But that's not the worst thing in the world, I suppose. Most of the non-kernel things (populaters) could be split off into a separate module, anyway. And indeed, this could house the machinery you've implemented rather than upstream, and provide the cli endpoint.

Getting that upstream would need proper testing and documentation, but

probably possible.

Awesome, though as suggested, it might be better to embrace and extend, at least initially! I certainly wouldn't hold up the progress!

Another interesting thing: you could also imagine loading the first markdown cell as the resource documentation... And even continuing the pattern, such that the cell above a single-keyword table would become that documentation.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/datakurre/robotkernel/issues/2#issuecomment-434409254, or mute the thread https://github.com/notifications/unsubscribe-auth/AACxRKB2eKT6TSXl4Em3iCQR0FMCf2Izks5uqJb9gaJpZM4TGKDH .

datakurre commented 5 years ago

Awesome, though as suggested, it might be better to embrace and extend, at least initially! I certainly wouldn't hold up the progress!

Now that you said it, yes, it would be easier to add and develop that reader in the kernel until it is ready. Just need to figure out if it is possible to get ”robot” cli support for ipynb that way...

bollwyvl commented 5 years ago

Yeah gets back the the classic Appropriate Extension Mechanism problem. on various Jupyter projects, I think we've tried them all, short of dedicated plugin frameworks like pluggy or stevedore.

I really like how namespace packages look from a consuming code perspective, but there are benefits to entry points as well.

Anyhow, I think getting ipynb into RF for tests/resources is a great idea, but might need to have some more corners explored, so that the use cases are really compelling. Over in conda 4.6, for example, they are about to cut ipynb as an environment specification format, because it wasn't being used much, and it wasn't conda's job to know about notebooks.

For example, if the language_info is not "robotframework", it could still look through, say, markdown cells and extract fenced code blocks marked as RF. In a sense, this would obviate the need for a dedicated kernel at all... except for the whole interactivity thing!

Or, maybe you could look for cell.metadata.robotframework... that would be a really cool way to build screenshots for documentation.

datakurre commented 5 years ago

@bollwyvl I realised that I needed this to run robot suites from notebooks without exporting them at first, so I added the simplest version into kernel for now https://github.com/datakurre/robotkernel/commit/efbf41e2b1e155c28b920a34fb8b549c39e5d7a3 with "nbrobot" and "nblibdoc" -entrypoints that enable the nbsupport for parsing.

Using markdown cells for documentation is interesting.

For more generic documentation I'm usually using Sphinx, where I do have https://pypi.org/project/sphinxcontrib-robotframework/ for generating screenshots from inline robot scripts. Although, I've got mixed response from inline robot screenshots (some would prefer them to be separated to keep documentation sources easier to read and maintain).