Skip to content

Construct-editor Error when quickly browsing the Construct Gallery of the Construct Editor GUI #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Ircama opened this issue Feb 19, 2023 · 4 comments · May be fixed by #38
Open

Construct-editor Error when quickly browsing the Construct Gallery of the Construct Editor GUI #28

Ircama opened this issue Feb 19, 2023 · 4 comments · May be fixed by #38

Comments

@Ircama
Copy link
Contributor

Ircama commented Feb 19, 2023

An error appears if the top left panel of the Construct Editor GUI is quickly changed by selecting a construct sample and then pressing a UP or DOWN arrow key, keeping it pressed.

Often (but possibly not always) a KeyError is shown. E.g., the GetSize() or Render() methods of the ObjectRenderer class in wx_construct_editor.py are often impacted.

Example:

  File "...\Python39\site-packages\construct_editor\wx_widgets\wx_construct_editor.py", line 54, in GetSize
    return self.entry_renderer_helper.get_size(self)
  File "...\Python39\site-packages\construct_editor\wx_widgets\wx_obj_view.py", line 376, in get_size
    obj_str = self.entry.obj_str if self.entry else ""
  File "...\Python39\site-packages\construct_editor\core\entries.py", line 1789, in obj_str
    return self.conv_obj_to_str(self.obj)
  File "...\Python39\site-packages\construct_editor\core\entries.py", line 252, in obj
    obj = obj[p]

Uncaught exception: KeyError: 'days2'

The frequency of the error depends on how many elements are consecutively browsed in sequence (many are needed for the error to occur, not just some) and on the speed of the computer.

@timrid
Copy link
Owner

timrid commented Feb 19, 2023

I am not quite sure how you are generating the error. I can not reproduce it, but I am not sure if I do it the same like you.
Can you take a screenshot of the panel where you hold down the UP and DOWN buttons?

@Ircama
Copy link
Contributor Author

Ircama commented Feb 19, 2023

You either need to browse many construct elements in the gallery (a testing program is needed and this allows checking that the issue occurs every time with fast browsing) or you have to be extremely fast with the ones included in the default sample and perform this testing various times. I will develop a small program that generates the error.

@Ircama
Copy link
Contributor Author

Ircama commented Feb 20, 2023

This is a simplified version of main.py. To test it, keep the DOWN arrow key pressed and then the UP arrow key pressed at the end of the travel and repeat this many times. In my Windows 11 setup, Python 3.10.10, I systematically get the error after less than 10 attempts.

import wx
from construct_editor.wx_widgets import WxConstructHexEditor
from pkgutil import iter_modules
from importlib import import_module
import construct_editor.gallery


class ConstructGalleryFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.SetSize(1000, 500)
        self.Center()
        self.status_bar: wx.StatusBar = self.CreateStatusBar()
        self.main_panel = ConstructGallery(self)


class ConstructGallery(wx.Panel):
    def __init__(self, parent: ConstructGalleryFrame):
        super().__init__(parent)

        sample_modules = {
            submodule.name: import_module(
                "construct_editor.gallery." + submodule.name)
                for submodule in iter_modules(
                    construct_editor.gallery.__path__,)
        }
        self.construct_gallery = {
            f"{i}_{module}" : sample_modules[module].gallery_item
                for i in range(10)
                    for module in sample_modules
        }
        self.gallery_selection = 0
        default_gallery = list(self.construct_gallery.keys())[self.gallery_selection]
        default_gallery_item = self.construct_gallery[default_gallery]

        # Define GUI elements #############################################
        self.sizer = wx.BoxSizer(wx.HORIZONTAL)
        vsizer = wx.BoxSizer(wx.VERTICAL)

        # gallery selctor
        self.gallery_selector_lbx = wx.ListBox(
            self,
            wx.ID_ANY,
            wx.DefaultPosition,
            wx.DefaultSize,
            list(self.construct_gallery.keys()),
            0,
            name="gallery_selector",
        )
        self.gallery_selector_lbx.SetStringSelection(default_gallery)
        vsizer.Add(self.gallery_selector_lbx, 1, wx.ALL, 1)

        # example selctor
        self.example_selector_lbx = wx.ListBox(
            self,
            wx.ID_ANY,
            wx.DefaultPosition,
            wx.Size(-1, 100),
            list(default_gallery_item.example_binarys.keys()),
            0,
            name="gallery_selector",
        )
        if len(default_gallery_item.example_binarys) > 0:
            self.example_selector_lbx.SetStringSelection(
                list(default_gallery_item.example_binarys.keys())[0]
            )
        vsizer.Add(self.example_selector_lbx, 0, wx.ALL | wx.EXPAND, 1)

        self.sizer.Add(vsizer, 0, wx.ALL | wx.EXPAND, 0)

        # construct hex editor
        self.construct_hex_editor = WxConstructHexEditor(
            self,
            construct=default_gallery_item.construct,
            contextkw=default_gallery_item.contextkw,
        )
        # self.construct_hex_editor.construct_editor.expand_all()
        self.sizer.Add(self.construct_hex_editor, 1, wx.ALL | wx.EXPAND, 0)

        self.SetSizer(self.sizer)

        # Connect Events ##################################################
        self.gallery_selector_lbx.Bind(
            wx.EVT_LISTBOX, self.on_gallery_selection_changed
        )
        self.example_selector_lbx.Bind(
            wx.EVT_LISTBOX, self.on_example_selection_changed
        )


        # Emulate Selection Click
        self.on_gallery_selection_changed(None)

    def on_gallery_selection_changed(self, event):
        selection = self.gallery_selector_lbx.GetStringSelection()
        gallery_item = self.construct_gallery[selection]
        if gallery_item is None:
            self.gallery_selector_lbx.SetSelection(
                self.gallery_selection
            )  # restore old selection
            return

        # save currently shown selection
        self.gallery_selection = self.gallery_selector_lbx.GetSelection()

        self.example_selector_lbx.Clear()
        if len(gallery_item.example_binarys) > 0:
            self.example_selector_lbx.InsertItems(
                list(gallery_item.example_binarys.keys()), 0
            )
            self.example_selector_lbx.SetStringSelection(
                list(gallery_item.example_binarys.keys())[0]
            )

            example = self.example_selector_lbx.GetStringSelection()
            example_binary = self.construct_gallery[selection].example_binarys[example]
        else:
            example_binary = bytes(0)

        self.Freeze()
        self.construct_hex_editor.change_construct(gallery_item.construct)
        self.construct_hex_editor.change_contextkw(gallery_item.contextkw)
        self.construct_hex_editor.binary = example_binary
        self.construct_hex_editor.construct_editor.expand_all()
        self.Thaw()

    def on_example_selection_changed(self, event):
        selection = self.gallery_selector_lbx.GetStringSelection()
        example = self.example_selector_lbx.GetStringSelection()
        example_binary = self.construct_gallery[selection].example_binarys[example]

        # Set example binary
        self.construct_hex_editor.binary = example_binary
        self.construct_hex_editor.construct_editor.expand_all()


def main():
    app = wx.App(False)
    frame = ConstructGalleryFrame(None)
    frame.Show(True)
    app.MainLoop()


if __name__ == "__main__":
    main()

@Ircama
Copy link
Contributor Author

Ircama commented Dec 8, 2023

This problem almost always occurs with WSL Ubuntu and with Raspberry Pi and makes this framework unusable. There is something that refreshes old values after changing the construct sample or gallery and with Windows it only occurs very rarely.


At the end I found that the issue occurs with wx.Yield(). It looks like Gtk does not like it there. By commenting out that line, the issue disappears.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants