ENB: @jupytext will simplify everything

46 views
Skip to first unread message

Edward K. Ream

unread,
Oct 23, 2024, 12:39:56 PM10/23/24
to leo-editor

This Engineering Notebook post describes a breakthrough that will radically simply #4117 support jupytext. As a result of this Aha, I've just renamed this issue. This ENB will be pre-writing for a thorough revision of that issue's first comment.


Background: syncing files


Work on #4117 has gone smoothly. Nevertheless, one detail keeps complicating the code. How should Leo keep a notebook file, say x.ipynb, in sync with its paired jupytext file, x.py?


Aha: Don't sync files!!!


Leo should support @jupytext nodes. The following will be equivalent:


  @jupytext x.py

  @jupytext x.ipynb

  @jupytext x


The file's extension doesn't matter because:


- When Leo reads an @jupytext x node, Leo will use jupytext to re-create that node and all its descendants from x.ipynb.

- When Leo writes the @jupytext x node, Leo will use jupytext to re-create x.ipynb from the entire @jupytext tree.

- When Leo checks for an externally changed .ipynb file, Leo will re-create the corresponding @jupytext x node, assuming such a node exists.


@jupytext collapses the complexity of all the jupytext-related code:


- Leo will only read and write .ipynb files.

- Within Leo, jupytext will never create .py files!

- As a result, Jupyter users won't need to use jupytext!


Use cases within Leo


Users can edit @jupytext nodes as usual. They can insert, delete and rearrange nodes.


A Leo option might specify whether to treat @jupytext nodes as @clean or @file. However, it's an open question whether Leo's sentinels are tolerable within Jupyter itself. I'll experiment soon.


Summary


@jupytext simplifies everything:


- Only @jupytext nodes update .ipynb files automatically.

- Leo will only read and write .ipynb files.

- There are no paired files to sync!

- There are no syntactically incorrect paired .py files!

- Jupyter users don't need to use jupytext!


All your questions and comments are welcome.


Edward


P.S. Writing this ENB has convinced me that @jupytext is the way forward. I would be shocked if @jupytext isn't the best solution for both Leo's users and maintainers.


EKR

Edward K. Ream

unread,
Oct 23, 2024, 12:56:51 PM10/23/24
to leo-editor
On Wednesday, October 23, 2024 at 11:39:56 AM UTC-5 Edward K. Ream wrote:

> This Engineering Notebook post describes a breakthrough that will radically simply #4117 support jupytext.

I elided some important details:

> When Leo reads an @jupytext x node, Leo will use jupytext to re-create that node and all its descendants from x.ipynb.

Recreating the node implies using jupytext to create a temporary .py file. But this file will exist only as a string. It will never become a real external file:

- If the user regards @jupytext as a wrapper for @clean, Leo will use the Leo's @clean read code to update the @jupytext tree.

- If the user regards @jupytext as a wrapper for @file, then the .ipynb file should contain Leo sentinels. In that case, Leo will recreate the @jupytext tree using Leo's @file read code.

> When Leo writes the @jupytext x node, Leo will use jupytext to re-create x.ipynb from the entire @jupytext tree.

Again, Leo must first convert the entire @jupytext node to a string before invoking jupytext.

Summary

Reading and writing .ipynb nodes will involve behind-the-scenes complications.

Leo will create temporary .py files when reading or writing @jupytext nodes.

Nevertheless I foresee no unusual problems.

Edward

HaveF HaveF

unread,
Oct 23, 2024, 7:43:55 PM10/23/24
to leo-editor
> This Engineering Notebook post describes a breakthrough that will radically simply #4117 support jupytext.

I elided some important details:

> When Leo reads an @jupytext x node, Leo will use jupytext to re-create that node and all its descendants from x.ipynb.

Recreating the node implies using jupytext to create a temporary .py file. But this file will exist only as a string. It will never become a real external file:


I have to say @jupytext is an amazing idea.  I wonder if it would be better to let the user choose whether to write to an external file or not? Considering the purpose of jupytext:

> Have you always wished Jupyter notebooks were plain text documents? Wished you could edit them in your favorite IDE? And get clear and meaningful diffs when doing version control? Then, Jupytext may well be the tool you’re looking for!

If we just save it in Leo as string, we may lose this advantage.

Of course, it seems that the logic is more complicated. In this case,

@jupytext x.py
@jupytext x.ipynb
@jupytext x

will make a difference.

I don’t have a clear preference for this idea, just an idea.

HaveF HaveF

unread,
Oct 23, 2024, 8:25:56 PM10/23/24
to leo-e...@googlegroups.com
I have to say @jupytext is an amazing idea.  I wonder if it would be better to let the user choose whether to write to an external file or not? 

I rethought this question and I think it might be easier to support it only in Leo instead of writing it to an external file. 

- jupytext supports many languages. If we support write to external file, we need to ensure that a variety of potential paired language files are read.
- jupytext also supports placing paired files in other folders. If we want to support writing to external files, it will be more troublesome. 

So I think Edward's original idea is great!


Edward K. Ream

unread,
Oct 23, 2024, 8:39:10 PM10/23/24
to leo-editor
On Wednesday, October 23, 2024 at 11:39:56 AM UTC-5 Edward K. Ream wrote:

> This Engineering Notebook post describes a breakthrough that will radically simplify #4117.

Today has been a golden day of programming. Pr  #4119, renamed "Support @jupytext," now demonstrates all facets of the project.


Here are the highlights:


Dead easy collaboration


The present code demonstrates round-tripping of .ipynb files between Leo and Jupyter.


Everything "just works" without using jupytext in Jupyter!


Dead easy class design


- leoJupytext.py defines the JupytextManager (jtm) class. The LeoApp class instantiates a singleton instance of the jtm in the usual way.

- The AtFile class supports reading and writing @jupytext nodes with prosaic code, delegating all significant operations to the jtm.

- The ExternalFilesController class supports updating @jupytext nodes when external editors (including Jupyter) write .ipynb files.


Dead easy code


The JupytextManager class is remarkably concise. For example, here is jtm.read:


def read(self, c: Cmdr, p: Position) -> str: # pragma: no cover

    """

    p must be an @jupytext node describing an .ipynb file.

    Convert x.ipynb to a string and return that string.

    """

    path = self.full_path(c, p)

    if not path:

        return '' # full_path gives any errors.

    # Read .ipynb file into contents.

    notebook = jupytext.read(path, fmt='py:percent')

    contents = jupytext.writes(notebook, fmt="py:percent")

    return contents


Nothing could be simpler! And here is the client, AtFile.readOneAtJupytextNode:


def readOneAtJupytextNode(self, p: Position) -> None:

    """

    p must be an @jupytext node.

    - Convert the .ipynb file to a string s.

    - Update p.b's tree using s.

    """

    c = self.c

    contents = g.app.jupytextManager.read(c, p)

    if contents:

        p.b = '@language json\n\n' + contents


This code is a prototype. Instead of setting p.b, this method should use the @clean update code to set p's entire tree.


Summary


The present code demonstrates the round-tripping of .ipynb files between Leo and Jupyter. Everything "just works" without using jupytext in Jupyter!


The JupytextManager and AtFile classes work together to support reading and writing @jupytext nodes. The jtm and the ExternalFilesController classes collaborate to update @jupytext nodes when .ipynb files change externally.


The only remaining task is to have @jupytext nodes work like @clean nodes. Perhaps only a few more lines of code will suffice!


It's probably been five years since I have had such a significant and productive day of programming. None of this progress would have been possible without jupytext's spectacularly simple API!


Edward

Edward K. Ream

unread,
Oct 23, 2024, 8:52:54 PM10/23/24
to leo-e...@googlegroups.com
On Wed, Oct 23, 2024 at 7:25 PM HaveF HaveF <iamap...@gmail.com> wrote:

> I have to say @jupytext is an amazing idea.

Thanks. Our two posts crossed in the ether. It's been a great day. @jupytext has already proven its worth.

> I wonder if it would be better to let the user choose whether to write to an external file or not?

@jupytext always reads from an .ipynb file and writes to an .ipynb file.

The paired .py files that jupytext writes (when using Jupyter) no longer exist!
Indeed, it's best to delete any paired (.py) files. Their timestamps confuse Jupyter.

As a bonus, Jupyter users should NOT use jupytext from within Jupyter!
It doesn't get any better than that.

Edward

P.S. I'll soon augment the present prototype code with Leonine settings that control jupytext formats, etc.

Everything important works right now except for round-tripping outline structure. That is, the present code only reads and writes the body text of @jupytext nodes. Leo's @clean logic will soon read, write and update the entire @jupytext tree.

But not today. It's time for a break!

Edward

Edward K. Ream

unread,
Oct 23, 2024, 8:58:54 PM10/23/24
to leo-editor
On Wednesday, October 23, 2024 at 6:43:55 PM UTC-5 iamap...@gmail.com wrote:

Of course, it seems that the logic is more complicated. In this case,

@jupytext x.py
@jupytext x.ipynb
@jupytext x

will make a difference.

Thanks for reminding me.  Since @jupytext nodes only read and write .ipynb nodes the only reasonable valid form is now:

     @jupytext x.ipynb

This change eliminates confusion and significantly simplifies the code.

Days like this don't come around very often. Everything I tried worked.

Edward

Edward K. Ream

unread,
Oct 23, 2024, 9:08:19 PM10/23/24
to leo-editor
On Wednesday, October 23, 2024 at 7:39:10 PM UTC-5 Edward K. Ream wrote:

> Today has been a golden day of programming.

LeoInteg will be able to use this project with minimal changes to Leo's client.

Even better, LeoJS should also be able to use these ideas. There is a jupytext plugin for vs-code!

Edward

HaveF HaveF

unread,
Oct 24, 2024, 3:19:32 AM10/24/24
to leo-e...@googlegroups.com

It's probably been five years since I have had such a significant and productive day of programming. 


I can feel your emotions across the screen and I'm happy for you :-D
 

Edward K. Ream

unread,
Oct 24, 2024, 5:49:13 AM10/24/24
to leo-e...@googlegroups.com
On Thu, Oct 24, 2024 at 2:19 AM HaveF HaveF <iamap...@gmail.com> wrote:

It's probably been five years since I have had such a significant and productive day of programming. 


I can feel your emotions across the screen and I'm happy for you :-D

Thanks! It's been quite a ride.

Edward
Reply all
Reply to author
Forward
0 new messages