question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. Itย collects links to all the places you might be looking at while hunting down a tough bug.

And, if youโ€™re still stuck at the end, weโ€™re happy to hop on a call to see how we can help out.

[BUG] rich.traceback: no lexer for filename X found

See original GitHub issue

Describe the bug

The rich.traceback doesnโ€™t know how to render tracebacks originating from inside jinja2 templates. The issue is twofold: (1) rich doesnโ€™t recognize the .yaml.j2 extension as jinja2+yaml, and (2) the fallback isnโ€™t to print the file contents without highlighting but instead to simply not print it at all. As such this bug likely also affects other languages to compile to python bytecode, such as dg, Hylang and hissp/hebigo.

Repro:

test.py:

import jinja2, os
from rich.traceback import install
install()
def raiser():
    raise Exception
env = jinja2.Environment(
    loader = jinja2.FileSystemLoader([os.getcwd(), "/"], followlinks=True),
)
env.globals["raiser"] = raiser    
template = env.get_template("test.yaml.j2")
print(template.render())

test.yaml.j2:

foobar:
    something: {{ raiser() }}
    else: {{ 5 + 5 }}

Vanilla traceback:

Traceback (most recent call last):
  File "/home/pbsds/tmp/repro/test.py", line 13, in <module>
    print(template.render())
  File "/usr/lib/python3.10/site-packages/jinja2/environment.py", line 1291, in render
    self.environment.handle_exception()
  File "/usr/lib/python3.10/site-packages/jinja2/environment.py", line 925, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "/home/pbsds/tmp/repro/test.yaml.j2", line 2, in top-level template code
    something: {{ raiser() }}
  File "/home/pbsds/tmp/repro/test.py", line 4, in raiser
    raise Exception
Exception

rich.traceback:

โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Traceback (most recent call last) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚                                                                                                  โ”‚
โ”‚ /home/pbsds/tmp/repro/test.py:15 in <module>                                                     โ”‚
โ”‚                                                                                                  โ”‚
โ”‚   12                                                                                             โ”‚
โ”‚   13 template = env.get_template("test.yaml.j2")                                                 โ”‚
โ”‚   14                                                                                             โ”‚
โ”‚ โฑ 15 print(template.render())                                                                    โ”‚
โ”‚   16                                                                                             โ”‚
โ”‚ /usr/lib/python3.10/site-packages/jinja2/environment.py:1291 in render                           โ”‚
โ”‚                                                                                                  โ”‚
โ”‚   1288 โ”‚   โ”‚   try:                                                                              โ”‚
โ”‚   1289 โ”‚   โ”‚   โ”‚   return concat(self.root_render_func(ctx))  # type: ignore                     โ”‚
โ”‚   1290 โ”‚   โ”‚   except Exception:                                                                 โ”‚
โ”‚ โฑ 1291 โ”‚   โ”‚   โ”‚   self.environment.handle_exception()                                           โ”‚
โ”‚   1292 โ”‚                                                                                         โ”‚
โ”‚   1293 โ”‚   async def render_async(self, *args: t.Any, **kwargs: t.Any) -> str:                   โ”‚
โ”‚   1294 โ”‚   โ”‚   """This works similar to :meth:`render` but returns a coroutine                   โ”‚
โ”‚                                                                                                  โ”‚
โ”‚ /usr/lib/python3.10/site-packages/jinja2/environment.py:925 in handle_exception                  โ”‚
โ”‚                                                                                                  โ”‚
โ”‚    922 โ”‚   โ”‚   """                                                                               โ”‚
โ”‚    923 โ”‚   โ”‚   from .debug import rewrite_traceback_stack                                        โ”‚
โ”‚    924 โ”‚   โ”‚                                                                                     โ”‚
โ”‚ โฑ  925 โ”‚   โ”‚   raise rewrite_traceback_stack(source=source)                                      โ”‚
โ”‚    926 โ”‚                                                                                         โ”‚
โ”‚    927 โ”‚   def join_path(self, template: str, parent: str) -> str:                               โ”‚
โ”‚    928 โ”‚   โ”‚   """Join a template with the parent.  By default all the lookups are               โ”‚
โ”‚                                                                                                  โ”‚
โ”‚ /home/pbsds/tmp/repro/test.yaml.j2:2 in top-level template code                                  โ”‚
โ”‚                                                                                                  โ”‚
โ”‚ no lexer for filename 'test.yaml.j2' found                                                       โ”‚
โ”‚                                                                                                  โ”‚
โ”‚ /home/pbsds/tmp/repro/test.py:6 in raiser                                                        โ”‚
โ”‚                                                                                                  โ”‚
โ”‚    3 install()                                                                                   โ”‚
โ”‚    4                                                                                             โ”‚
โ”‚    5 def raiser():                                                                               โ”‚
โ”‚ โฑ  6 โ”‚   raise Exception                                                                         โ”‚
โ”‚    7                                                                                             โ”‚
โ”‚    8 env = jinja2.Environment(                                                                   โ”‚
โ”‚    9 โ”‚   loader = jinja2.FileSystemLoader([os.getcwd(), "/"], followlinks=True),                 โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

Platform

Click to expand

What platform (Win/Linux/Mac) are you running on? What terminal software are you using?

Manjaro GNOME, python 3.10.2, lxterminal

I may ask you to copy and paste the output of the following commands. It may save some time if you do it now.

If youโ€™re using Rich in a terminal:

โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ <class 'rich.console.Console'> โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚ A high level console interface.                                              โ”‚
โ”‚                                                                              โ”‚
โ”‚ โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ โ”‚
โ”‚ โ”‚ <console width=80 ColorSystem.TRUECOLOR>                                 โ”‚ โ”‚
โ”‚ โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ โ”‚
โ”‚                                                                              โ”‚
โ”‚     color_system = 'truecolor'                                               โ”‚
โ”‚         encoding = 'utf-8'                                                   โ”‚
โ”‚             file = <_io.TextIOWrapper name='<stdout>' mode='w'               โ”‚
โ”‚                    encoding='utf-8'>                                         โ”‚
โ”‚           height = 24                                                        โ”‚
โ”‚    is_alt_screen = False                                                     โ”‚
โ”‚ is_dumb_terminal = False                                                     โ”‚
โ”‚   is_interactive = True                                                      โ”‚
โ”‚       is_jupyter = False                                                     โ”‚
โ”‚      is_terminal = True                                                      โ”‚
โ”‚   legacy_windows = False                                                     โ”‚
โ”‚         no_color = False                                                     โ”‚
โ”‚          options = ConsoleOptions(                                           โ”‚
โ”‚                        size=ConsoleDimensions(width=80, height=24),          โ”‚
โ”‚                        legacy_windows=False,                                 โ”‚
โ”‚                        min_width=1,                                          โ”‚
โ”‚                        max_width=80,                                         โ”‚
โ”‚                        is_terminal=True,                                     โ”‚
โ”‚                        encoding='utf-8',                                     โ”‚
โ”‚                        max_height=24,                                        โ”‚
โ”‚                        justify=None,                                         โ”‚
โ”‚                        overflow=None,                                        โ”‚
โ”‚                        no_wrap=False,                                        โ”‚
โ”‚                        highlight=None,                                       โ”‚
โ”‚                        markup=None,                                          โ”‚
โ”‚                        height=None                                           โ”‚
โ”‚                    )                                                         โ”‚
โ”‚            quiet = False                                                     โ”‚
โ”‚           record = False                                                     โ”‚
โ”‚         safe_box = True                                                      โ”‚
โ”‚             size = ConsoleDimensions(width=80, height=24)                    โ”‚
โ”‚        soft_wrap = False                                                     โ”‚
โ”‚           stderr = False                                                     โ”‚
โ”‚            style = None                                                      โ”‚
โ”‚         tab_size = 8                                                         โ”‚
โ”‚            width = 80                                                        โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
rich==11.0.0

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
wasi-mastercommented, Mar 22, 2022

Iโ€™ve found the cause of this problem, the guess_lexer_for_filename method from the pygments.lexers module raises a ClassNotFound upon not being able to find a suitable lexer. And that function is used in the rich Traceback._guess_lexer function:

https://github.com/Textualize/rich/blob/master/rich/traceback.py#L513-L527

Upon getting a error, the traceback printer just prints the error gotten as a string which most of the times prints the error message:

https://github.com/Textualize/rich/blob/master/rich/traceback.py#L625-L627

The error gotten in this case is pygmentsโ€™ ClassNotFound error with the message no lexer for filename '...' found.

This can be fixed by adding another except statement for handling ClassNotFound and using the text lexer as a fallback
try:
    ...
except ClassNotFound as error:
    yield Syntax(
        code,
        "text",
        theme=theme,
        line_numbers=True,
        line_range=(
            frame.lineno - self.extra_lines,
            frame.lineno + self.extra_lines,
        ),
        highlight_lines={frame.lineno},
        word_wrap=self.word_wrap,
        code_width=88,
        indent_guides=self.indent_guides,
        dedent=False,
    )
except Exception as error:
    ...
else:
    ...

This would create some duplicate code, Iโ€™m sure the brilliant minds at @Textualize can figure something out

Applying these changes fixes the issue

image

cc: @willmcgugan @darrenburns

1reaction
darrenburnscommented, Mar 30, 2022

Rich delegates a lot of this stuff to Pygments, which itself doesnโ€™t recognise .yaml.j2 as an extension. If your files have the .sls extension, Pygments will use the YAML+Jinja lexer. Hereโ€™s the code from Pygments that does this: https://github.com/pygments/pygments/blob/64e8e05307689fe726ce9df2d5907e9c2fb67405/pygments/lexers/templates.py#L1861

It may be worth opening an issue/PR with Pygments, requesting to add this extension if itโ€™s one that is commonly used - weโ€™d rather not start adding workarounds/logic for this sort of thing on our side.

On the Rich side, we can certainly fix the bug where no text was being output.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Traceback โ€” Rich 12.6.0 documentation
Rich tracebacks are easier to read and show more code than standard Python tracebacks. To see an example of a Rich traceback, running...
Read more >
[BUG] Rich traceback not working proprely within notebook
Describe the bug When the rich traceback is enabled in a notebook, the traceback is almost unreadable and show a criptic message:ย ...
Read more >
No Lexer For Alias Found - python - Stack Overflow
I'm attempting to use Pygments and Beautiful Soup as a code highlighting solution for the blog software I'm building for Google App Engine....
Read more >
CudaText plugins - Free Pascal wiki
Files can be placed in any subfolder of "data/snippets" folder, file/folder names have no meaning, but it's recommended to name subfolders likeย ...
Read more >
rich: Traceback - Calmcode
rich : traceback. Better tracebacks in Python via Rich. ... it much more easthetically pleasing and will also make bug-finding a less painful...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found