mu-editor / mu

A small, simple editor for beginner Python programmers. Written in Python and Qt5.
http://codewith.mu
GNU General Public License v3.0
1.4k stars 434 forks source link

Incorporate friendly-traceback into Mu #963

Open ntoll opened 4 years ago

ntoll commented 4 years ago

See: https://github.com/aroberge/friendly-traceback/issues/26#issuecomment-560049658 for context.

I imagine if the friendly-traceback flag in Mu is true, then when any Python3 code is run or debugged, then the wonderful friendly-traceback should wrap it so the user gets comprehensible error messages.

Thanks to @aroberge for all his amazing work on friendly-traceback (Mu is standing on the shoulders of giants etc...) :+1:

aroberge commented 4 years ago

I was wondering if some information could be provided to users of Mu (possibly targeted at teachers) asking them to report any Python error message that they or their students find confusing. Even if friendly-traceback is not available yet in Mu, such information could be useful for friendly-traceback's development and its future use in Mu.

Looking at the Mu website, perhaps this could be added on https://codewith.mu/en/howto/1.0/bugs or https://codewith.mu/en/tutorials/1.0/problems ... although these deal with problems specific to Mu, and not Python. Of course, once friendly-traceback is incorporated into Mu, I imagine that a specific "how to use" page will be created for it, which would be a more appropriate place to give such information.

And to anyone reading this: if you know of cases where Python tracebacks were not helpful in helping students find the cause of their problems, you might want to see if they would have been helped by existing cases in https://aroberge.github.io/friendly-traceback-docs/docs/html/ and, if not, feel free to file an issue here: https://github.com/aroberge/friendly-traceback/issues

aroberge commented 4 years ago

I did not realize that one could now install third-party package inside Mu. It did fail for some reason when I tried with the alpha version, but installing the regular version over it, worked.

So, perhaps for the more adventurous ...

friendly_mu

aroberge commented 4 years ago

The following results in something less confusing to the end user.

import friendly_traceback as fr

fr.install()
fr.exclude_file_from_traceback(__file__)

import test_mu

I should probably rename exclude_file_from_traceback to exclude_file, and possibly use __file__ as a default ...

aroberge commented 4 years ago

Ready to experiment with: https://aroberge.github.io/friendly-traceback-docs/docs/html/mu.html

aroberge commented 4 years ago

Question: what would be the "friendliest" code to ask people to write?

  1. 
    from friendly_traceback import run_program

result = run_program("my_program", file) locals.update(result)


2. 
```py
from friendly_traceback import run_program

locals.update( run_program("my_program", __file__) )
  1. 
    from friendly_traceback import run_program

run_program("my_program", file, locals())



I have tested locally a slightly different implementation that would work with the third one.
tmontes commented 4 years ago

@aroberge, I may be a bit out of context and, certainly, away from friendly-traceback's implementation details, but here are my impressions.

The options you shared feel very alien to beginners, IMO:

I wonder if importing friendly_traceback couldn't be made to be enough - that would be the friendliest possible (other than having Mu importing it automatically behind the scenes, which I just thought about but think would deserve discussion).

The idea is that import friendly_traceback would have the side-effect of setting sys.excepthook to its friendly traceback display implementation. So, as long as users import it right from the start -- something that's easy to do and that beginner's are taught early (imports at the top!) -- then they would benefit from it. :)

Does this make any sense or am I missing something?

aroberge commented 4 years ago

@tmontes Slapping my own forehead! ... Of course ... or rather, yes, but ... At the moment, my preference is for not doing this by default. I may change my mind later, based on users' experience, or further thoughts from you or from others reading this.

Do you think that the following would be an acceptable compromise?

from friendly_traceback import help_me

and, for French users,

from friendly_traceback import aide_moi

... and hopefully a Portuguese version as well! ;-)

Instead of help_me, perhaps explain might be a better choice if this type of import would be acceptable. (I already use explain for something else; I would have to change that.)

Or perhaps help_Mu ... :-)

I definitely can make something like that work: all that is required, is to create one module per language with something the following two lines:

from . import public_api
public_api.install(lang="fr")

If the installation is done automatically upon normal import, we'd have the following situation:

# English user
import friendly_traceback
# French user
import friendly_traceback
friendly_traceback.set_lang("fr")

= = = Regarding Mu importing friendly_traceback automatically: I'm thinking that it makes sense to not do this, at least not yet.

  1. I wouldn't want any potential bugs in Friendly-traceback create problems for Mu users. If such bugs are present, they can easily be avoided by not adding this explicit import.
  2. Given its simplicity compared with Mu, it is much simpler for me to make changes (based on feedback from users) and issue a new release which can be made readily available, sometimes in just a few hours after getting the feedback.

Perhaps when Friendly-traceback reaches version 1.0 (and Mu reaches version 2.0), this idea could be revisited.

tmontes commented 4 years ago

Do you think that the following would be an acceptable compromise?

from friendly_traceback import help_me

and, for French users,

from friendly_traceback import aide_moi

... and hopefully a Portuguese version as well! ;-)

I hadn't thought about the important per-language variations. I'd love to contribute to such a Portuguese one, but no commitments, for now, ok? :-)

If the installation is done automatically upon normal import, we'd have the following situation:

# English user
import friendly_traceback
# French user
import friendly_traceback
friendly_traceback.set_lang("fr")

Ideally it could default to detect the user's UI language preference and use that -- non-trivial to do in a cross-platform way, I suppose.

The vision is that a French user would get nice French explanations with just import friendly_traceback, while a Chinese one, running the same import, would get Chinese explanations. :) Of course, the possiblitiy of overriding such default with friendly_traceback.set_lang would be very welcome.

One thing to consider is language variations like "de_DE" vs "de_CH", "en_GB" vs "en_US", "pt_PT" vs. "pt_BR", "es_ES" vs "es_MX", etc. :)

aroberge commented 4 years ago

I hadn't thought about the important per-language variations. I'd love to contribute to such a Portuguese one, but no commitments, for now, ok? :-)

Ok, anytime. :-)

If the installation is done automatically upon normal import, we'd have the following situation:

English userimport friendly_traceback

French userimport friendly_traceback

friendly_traceback.set_lang("fr")

Ideally it could default to detect the user's UI language preference and use that -- non-trivial to do in a cross-platform way, I suppose.

In a very early version, I picked up the language settings from the locale (which meant French for me). I changed that as I believe it makes sense to use English as the language used for development and testing without having to specify it.

The vision is that a French user would get nice French explanations with just import friendly_traceback, while a Chinese one, running the same import, would get Chinese explanations. :) Of course, the possiblitiy of overriding such default with friendly_traceback.set_lang would be very welcome.

set_lang is already supported. Giving a user an easy way to select language is something I really wish Mu would offer.

One thing to consider is language variations like "de_DE" vs "de_CH", "en_GB" vs "en_US", "pt_PT" vs. "pt_BR", "es_ES" vs "es_MX", etc. :)

This is already supported - in theory anyway.

You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/mu-editor/mu/issues/963?email_source=notifications&email_token=AAEZXQWCNQAZUKEKJTJUWTDQZIBLTA5CNFSM4JTKNIF2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHFZOWI#issuecomment-566990681, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEZXQW26SXZKD7ICVS2Z5LQZIBLTANCNFSM4JTKNIFQ .

tmontes commented 4 years ago

set_lang is already supported. Giving a user an easy way to select language is something I really wish Mu would offer.

Agreed, much like your request in #518, comments in #692, and my proposal in this comment, there. :)

aroberge commented 4 years ago

@tmontes Thank you for pointing me in the right direction. I was thinking of a possible future version of Mu, where one might have an extra option to click on a button to "run with Friendly-traceback" without modifying the user's code. To do this, the original approach I implemented would have been unavoidable. Of course, it is much simpler to have students add a single import line at the top. The documentation (https://aroberge.github.io/friendly-traceback-docs/docs/html/mu.html) for Friendly-traceback has now been updated to reflect this simpler approach.

ZanderBrown commented 4 years ago

non-trivial to do in a cross-platform way, I suppose

Python has a module for everything, including locale

ZanderBrown recently wrote a neat little flask app and was reminded just how much python has a module for everything

tmontes commented 4 years ago

Python has a module for everything, including locale

It does, and it does somewhat of bad job for our needs, I'd say:

...but it kind of works! :-)

tmontes commented 4 years ago

@tmontes Thank you for pointing me in the right direction. I was thinking of a possible future version of Mu, where one might have an extra option to click on a button to "run with Friendly-traceback" without modifying the user's code. To do this, the original approach I implemented would have been unavoidable.

Agreed. That would be code that Mu would run under the hood to provide friendly tracebacks to beginners, regardless of users code, yes.

Of course, it is much simpler to have students add a single import line at the top. The documentation (https://aroberge.github.io/friendly-traceback-docs/docs/html/mu.html) for Friendly-traceback has now been updated to reflect this simpler approach.

Looking better and better. :)

aroberge commented 4 years ago

Unfortunately, the method described to use Friendly-traceback with Mu does not work for SyntaxErrors which is most unfortunate since these are likely the most common source of confusion for beginners.

For some reasons, SyntaxError are raised and reported before reaching Friendly syntax.
This can be seen by trying to run the simple program:

# test_problem.py
from friendly_traceback import explanations

1 = a

However, if one uses another file to run the same script indirectly, SyntaxErrors can be properly processed.

# runner.py
import runpy
import friendly_traceback as friendly

friendly.install()
friendly.exclude_file_from_traceback(__file__)
friendly.exclude_file_from_traceback("runpy.py")
result = runpy.run_module("test_problem.py", run_name="__main__")
locals.update(result)

This is the approach that would have to be used if a "run with Friendly-traceback" button or something similar were to be added to the UI.

aroberge commented 4 years ago

An easier way of using Friendly-traceback within Mu (and other editors, including IDLE) is now available. Friendly-traceback can now do more than simply providing helpful explanation when an exception is raised; it can also alert users about potential problems in their programs. For example, the following program has no problems when verified within Mu, and yet it prints nothing. image

It is based on something that really happened to a beginner: see https://aroberge.blogspot.com/2020/08/identifying-misleading-type-hints.html for details.

Here's the new method of running Friendly-traceback, using this test program. image

This simple run() method will provide the usual "friendly" tracebacks whether a syntax error is raise, or some runtime error, such as NameError. The latter information for this particular exception has been significantly improved.

Please, feel free to put it to the test. Do not rely on the documentation which is hopelessly out of date.

aroberge commented 3 years ago

For those interested in this issue, I have improved the way friendly (formally known as friendly-traceback) interacts with Mu. The documentation for friendly now includes 4 short pages specific to Mu, starting at https://aroberge.github.io/friendly-traceback-docs/docs/html/mu_about.html.

I am in the process of revising the entire documentation for friendly. Once this is done, the warning about the name change at the top of each page of friendly's documentation will be removed, and work to improve friendly will resume.

aroberge commented 2 years ago

Please, help me! :-)

A new version (0.5.2) of friendly has just been released with significantly improved support for Mu. I have tested it on Windows but would love to hear from people using Mac or Linux (or even some other Windows users that could confirm it also works for them.) Testing it should take you about the same amount of time as reading this message. ;-)

friendly should automatically pick up the theme (saved at the end of a session in session.json) and the locale used by Mu. [0]

While it usually "works better" if it is "installed" prior to any user code being executed, friendly can now retroactively analyze a traceback.

To test:

While this issue is tagged for Milestone 1.2, perhaps nothing needs to be done for Mu code itself.

[0] friendly includes full support for English and French, nearly full support for Spanish, and has some support for Italian.

[1] I've never tested the other modes.

[2] Not all possible exceptions are covered, but it's slowly improving; my test suite contains approximately 400 cases of code that raises exception - most of which are SyntaxError cases.

[3] Alternatively, you can do from friendly.mu import why, explain, ... or, perhaps preferably, from friendly.mu import Friendly and type Friendly at the terminal to get some short help.

Final note: the documentation for friendly has not been updated in a while and does not include some of the more interesting additions, including this recent improved support for Mu.

carlosperate commented 2 years ago

Hi @aroberge, we are looking at tickets to implement at the EuroPython sprints and it would be great to get friendly-traceback integrated in Mu. The info in this thread might be outdated. Do you have any tips about the best way to integrate it or any question for the Mu team to answer to move this forward?

aroberge commented 2 years ago

@carlosperate I have not changed anything for the Mu integration of friendly since the last comment I wrote here. Perhaps, the easiest way to show what can be done would be via some screenshots. First, starting with the interactive interpreter image Ideally, the REPL should start with the line of code from friendly.mu import * shown above prior to executing anything else. This puts some convenience function into the local namespace so that more information can be queried. image

For a better experience, the theme and the language should also be picked up and set prior to any other code being run. image image

The available theme for Mu are day, night, and, contrast. One can also try colourful() which has a background suitable for the high contrast Mu theme ... but is quite colourful.

For running a file in the "regular" (not IPython) terminal, one must use the run function provided by friendly, as follows: image

Since the output terminal does not support colours, it does not make sense to try to set a theme.

Hopefully, the above information is useful. Feel free to ask my help if you think that anything needs to be modified on the friendly/friendly-traceback side to facilitate the integration.

aroberge commented 2 years ago

Looking at the IPython documentation, one can apparently have a list of lines of code that are run at the beginning of a session; see https://ipython.readthedocs.io/en/stable/config/options/kernel.html#configtrait-InteractiveShellApp.exec_lines. However, I searched for InteractiveShellApp in the Mu repository, as well as in the QtConsole repository and could not find it. So, I don't know how one can go about and add the required code to be run at the beginning of an IPython session within Mu. :(