slint icon indicating copy to clipboard operation
slint copied to clipboard

Python: Make `__str__` work for `CompileError`'s `diagnostics` field

Open tronical opened this issue 1 year ago • 2 comments
trafficstars

As seen in #5469, when printing the CompileError struct, the diagnostics are not correctly transformed to a readable representation. While __str__ is implemented on PyDiagnostics, somehow it doesn't transcend into the list that's created from it.

Fixing this would make it easier to quickly discover the root cause for a run-time generated Slint compile error.

tronical avatar Jun 25 '24 08:06 tronical

The Demo works, but when packaged with pyinstaller, it doesn't

python 3.10 slint 1.6.0a8 package command : pyinstaller -FD main.py --add-data "appwindow.slint:./"

Traceback (most recent call last):
  File "main.py", line 5, in <module>
  File "slint/__init__.py", line 182, in load_file
slint.CompileError: ('Could not compile appwindow.slint', [<builtins.PyDiagnostic object at 0x109ff1ac0>])
[53112] Failed to execute script 'main' due to unhandled exception!
import slint
components = slint.load_file("appwindow.slint")
main_window = components.MainWindow()
main_window.run()

cooliean avatar Jun 26 '24 09:06 cooliean

I think that may be because when passing a relative path to load_file() will it be resolved against the process' working directory. You could try something like this instead: slint.load_file(os.path.join(os.path.dirname(__file__), "appwindow.slint"))

tronical avatar Jun 26 '24 11:06 tronical

I worked around this issue by just calling the slint class twice, but it would be nice if I didn't have to do this workaround

try:
    slint.loader.ui.alarm_list_window.AlarmListWindow
except slint.CompileError as e:
    print(e.message)
    for diagnostic in e.diagnostics:
        print(diagnostic)
    sys.exit(1)

class AlarmListWindow(slint.loader.ui.alarm_list_window.AlarmListWindow):

gaycodegal avatar Sep 14 '25 14:09 gaycodegal

Might be worth using PEP 678 for this: https://peps.python.org/pep-0678/

whitequark avatar Sep 14 '25 14:09 whitequark

In addition, I think the line number and column number fields are interchanged when initialising the object.

Sample slint file:

import {
    Button, StandardTableView, ProgressIndicator, ListView,
    VerticalBox, HorizontalBox,
} from "std-widgets.slint"; // deliberate error in next line
j 

Python:

import slint
try:
    slint_gui = slint.load_file(pathlib.Path(__file__).parents[0]/"app-window.slint")
except slint.CompileError as e:
    for i in e.diagnostics:
        e.add_note(f"{i.column_number = }, {i.line_number = }, {i.message = }")
    raise

Traceback:

...
slint.CompileError: ('Could not compile /home/isoraqathedh/Documents/Programming/GitHub/autowordle/autowordle/app-window.slint', [<builtins.PyDiagnostic object at 0x7f68bdd62240>])
i.column_number = 5, i.line_number = 1, i.message = 'Parse error: expected a top-level item such as a component, a struct, or a global'

Note the column number is 5 and the line number is 1 but it should be the other way around.

isoraqathedh avatar Oct 09 '25 06:10 isoraqathedh

Oh gosh, you're right - they're swapped.

Thanks for the suggestions! ❤️ I agree, PEP 678 seems like a nice feature to use for this.

tronical avatar Oct 09 '25 06:10 tronical