pythonexceptionformattingrichtextrich

Python rich not formatting markup in custom exception


I'm trying to add formatting in a custom exception with rich. The same string when printed as a string works (the carat becomes bold red), but as an exception it doesn't. It's stranger because the foo=123 gets highlighted automatically in both situations. What am I missing here?

In [7]: class InvalidSpec(ValueError):
   ...:     def __init__(self, args):
   ...:         loc = args.find("=")
   ...:         hdr = "invalid spec: "
   ...:         self.args = (f"{hdr}{args}\n[red][bold]{' ' * (len(hdr) + loc)}^", )
   ...:         

In [8]: rich.print(InvalidSpec("foo=123").args[0])
invalid spec: foo=123
                 ^

In [9]: rich.print(InvalidSpec("foo=123"))
invalid spec: foo=123
[red][bold]                 ^

enter image description here


Solution

  • Looks like the solution is to convert to string first. Not sure why:

    In [102]: try:
         ...:     raise InvalidSpec("foo=1")
         ...: except Exception as err:
         ...:     c.print(err)
         ...:     c.print(str(err))
         ...:     
    invalid spec: foo=1
     [red][bold]                ^
    invalid spec: foo=1
                     ^
    

    enter image description here


    Update: thanks to the comment by @InSync, I understand it. when it's not a str already rich will only do some simple highlighting, not full console markup. For full markup, you have to implement __rich__.

    In [19]: class InvalidSpec(ValueError):
        ...:     def __init__(self, args):
        ...:         super().__init__(args)
        ...:         hdr = "invalid spec: "
        ...:         loc = len(hdr) + args.find("=")
        ...:         self.args = (f"{hdr}{args}\n{' ' * loc}^", )
        ...:     def __rich__(self):
        ...:         loc = self.args[0].find("^")
        ...:         return self.args[0][:loc] + "[red][bold]" + self.args[0][loc:]
        ...:         
    
    In [20]: pprint(InvalidSpec("foo=123"))
    invalid spec: foo=123
                     ^
    
    In [21]: print(InvalidSpec("foo=123"))
    invalid spec: foo=123
                     ^
    

    enter image description here