Saturday, July 24, 2021

New interactive friendly tracebacks for Jupyter

 Summary: I have a draft version of a new and arguably better way to display information from friendly for Jupyter labs/notebooks. For now, it only works with the default light theme.

The following screen captures illustrate a new way to display the information from friendly inside Jupyter lab/notebooks.  Instead of having to type some commands, the user can click on buttons.  Initially only the error message is shown.

Clicking on "More ..." reveals the friendly traceback (notice how the traditional file names are replaced by references to code blocks) and a few more buttons.

One can click on individual buttons to show or hide the desired information.

Using the default formatter, instead of this new one, works somewhat acceptably with the dark theme.

Most unfortunately, the new interactive display just does not pick up the dark theme appropriately; I have not been able to figure out why.

Ideally, I would like to be able to use the custom dark theme that I have created to work with Rich, but have not figured out how to do it yet.

Anyone having some insights as to how to fix these problems should not hesitate to comment here or on the Github issue.

Wednesday, July 21, 2021

Friendly-traceback 0.4 and PyConAu

 Just a quick update ...

After over 150 commits, most of which included new traceback cases explained by Friendly-traceback, it is time to go from version 0.3 to 0.4.  There are too many changes to mention in this blog post and the documentation needs to be updated.  

The version change is also to allow me to switch gear and focus on preparing a talk for the next PyConAu. I'm hoping that this can be done reasonably quickly (say, within a week) so that I can have the time to write a proper blog post about all the new features of Friendly-traceback.

Monday, July 12, 2021

Friendlier tracebacks in REPLs (including Jupyter)

Traceback:  Determination of origin; the process of tracing something back to its source.

I have been working towards release 0.4 of friendly/friendly_traceback as well as preparing for a talk at the upcoming PyconAU. Those familiar with PyconAU might be interested to note that I plan to include an example related to the flipfloperator.  :-)

In this preparatory work, I have been revisiting almost all aspects of friendly/friendly-traceback, making various improvements. Unfortunately, this means that many of the screenshots included in the documentation will have to be updated.

In this blog post, I want to illustrate some of the changes that I have finished implementing with regards to the traceback themselves. By this, I mean the sequence of calls that were done and not the message, such as "IndexError: list index out of range".  I will look at the same simple example using a variety of interpreters. Since this is a simple example, the traceback is not going to be very long ... but I want you to imagine situations where it could be much longer.

First, let me introduce this example using the CPython REPL:

We see a reference to a "file" named "<stdin>" which appears many times. While we have some line numbers indicated, CPython does not tell us anything about the content of these lines.  Thus, it could be difficult to trace back the source of the error.

The situation is slightly better with IDLE, as it keeps track of different "<pyshell> files" and show us the relevant lines of code.

Up until recently, this was the strategy I was using by default with the friendly console. Here we see it running within IDLE.

For longer traceback, the user might have difficulty identifying the block of code corresponding to each "<friendly-console> file".  Fortunately, friendly includes the function where() which can provide some help in this situation.

For perhaps a slightly better approach, we can look at what IPython does.

Each code block is identified by a number in brackets, [1], [2], etc..  The traceback includes a weird name of the form "<ipython-input-N-...>".  By looking closely at enough examples, we can conclude that the "N" correspond to the digit between the square brackets in a code block.

Moving on to Jupyter (lab). Up until fairly recently, Jupyter lab (and notebooks), which are based on IPython, were using "filenames" of the form "<ipython-input-N-...>".  However, this seems to have been changed recently, and we now have "real" filenames ... with names that do not contain any clue about their origin. [I filed an issue suggesting an improvement.]

However, it is possible to do better.  Here's how friendly now shows this information within Jupyter lab.

Instead of a "File" we see mention of "Code block" which might be less confusing, especially to beginners that are starting with Jupyter and never dealt with Python code in separate files before.

Of course, this being friendly, we can show much more than simply the traceback.  Here's the complete information available:

To properly format tracebacks with "Code block" instead of "File", I had to monkey patch pygment's lexer.

Since I thought that such numbered code blocks were more informative than fake filenames like "<friendly-console>", I decided to adopt them by default in friendly's REPL:

This new REPL style is also available in friendly.idle (not shown in this post).

Finally, here's an example showing a mixture of code from files and code blocks.

If you have any suggestion for possible improvements to friendly/friendly-traceback, please do not hesitate to let me know by filing an issue.  I am especially interested to hearing from teachers/mentors that work with beginners.


Thursday, July 08, 2021

friendly-traceback is back!

 A few months ago, I mentioned that friendly-traceback had been renamed friendly. As friendly/friendly-traceback evolved, the number of dependencies increased. For some third-party projects that use friendly/friendly-traceback, such as futurecoder and HackInScience, many of these dependencies are simply redundant and represent a performance hit.  For this reason, I have split friendly/friendly-traceback into two separate projects, and created a new "organization" on Github [1] with separate repositories:  one for friendly-traceback, and a separate one for friendly (which has friendly-traceback as a dependency). I even temporarily added a third project (friendly_idle) but folded it back into friendly as the extra burden of maintaining a relatively small project with lots of duplication was too much work for very little benefit.

Much progress has been done with these projects since the last minor release (0.3) and I am in the process of doing a major update to the documentation prior to the 0.4 release; friendly-traceback is currently at version 0.3.154.

If you are a user of friendly/friendly-traceback, you likely need to do "pip install friendly".  If you want to use the information provided by friendly/friendly-traceback into your own project, you likely only need to do "pip install friendly-back".

[1] This change meant going back to zero stars on Github!