Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

NoActiveAppError when DataTable add_column is invoked from worker thread #3926

Closed
gubenkoved opened this issue Dec 24, 2023 · 0 comments
Closed

Comments

@gubenkoved
Copy link

gubenkoved commented Dec 24, 2023

When DataTable add_column method is invoked from thread worker application crashes.

I am wondering if this as designed or not? It is understandable that interacting with the application UI elements is inherently not thread safe. I assumed however that creating new widgets in another worker thread is acceptable.

Could someone please clarify on this one?

The use-case I am trying to use it with is following - I am trying to construct a big table and keep application responsive in the mean time, then as soon as table is ready I was going to mount it using call_from_thread.

textual 0.46.0

PS. Thank you for very nice project, it is a pleasure to experiment with!

from textual import work
from textual.app import App
from textual.widgets import Static, DataTable


class MyApp(App):
    def compose(self):
        self.start_work()
        yield Static('HELLO')

    @work(exclusive=True, thread=True)
    def start_work(self):
        dt = DataTable()
        dt.add_column('foo')
        self.call_from_thread(
            lambda: self.mount(Static('DONE!'))
        )


if __name__ == '__main__':
    app = MyApp()
    app.run()

Here is traceback part:

│ .................................................../bug.py:14 in start_work                                          │
│                                                                                                                      │
│   11 │   @work(exclusive=True, thread=True)                                                                          │
│   12 │   def start_work(self):                                                                                       │
│   13 │   │   dt = DataTable()                                                                                        │
│ ❱ 14 │   │   dt.add_column('foo')                                                                                    │
│   15 │   │   self.call_from_thread(                                                                                  │
│   16 │   │   │   lambda: self.mount(Static('DONE!'))                                                                 │
│   17 │   │   )                                                                                                       │
│                                                                                                                      │
│ ╭────────────────────── locals ───────────────────────╮                                                              │
│ │   dt = DataTable()                                  │                                                              │
│ │ self = MyApp(title='MyApp', classes={'-dark-mode'}) │                                                              │
│ ╰─────────────────────────────────────────────────────╯                                                              │
│                                                                                                                      │
│ .................................................../venv/lib/python3.11/site-packages/textual/widgets/_data_table.py │
│ :1491 in add_column                                                                                                  │
│                                                                                                                      │
│   1488 │   │   │   raise DuplicateKey(f"The column key {key!r} already exists.")                                     │
│   1489 │   │   column_index = len(self.columns)                                                                      │
│   1490 │   │   label = Text.from_markup(label) if isinstance(label, str) else label                                  │
│ ❱ 1491 │   │   content_width = measure(self.app.console, label, 1)                                                   │
│   1492 │   │   if width is None:                                                                                     │
│   1493 │   │   │   column = Column(                                                                                  │
│   1494 │   │   │   │   column_key,                                                                                   │
│                                                                                                                      │
│ ╭─────────────── locals ───────────────╮                                                                             │
│ │ column_index = 0                     │                                                                             │
│ │   column_key = ColumnKey(value=None) │                                                                             │
│ │      default = None                  │                                                                             │
│ │          key = None                  │                                                                             │
│ │        label = <text 'foo' []>       │                                                                             │
│ │         self = DataTable()           │                                                                             │
│ │        width = None                  │                                                                             │
│ ╰──────────────────────────────────────╯                                                                             │
│                                                                                                                      │
│ .................................................../venv/lib/python3.11/site-packages/textual/message_pump.py:210 in │
│ app                                                                                                                  │
│                                                                                                                      │
│   207 │   │   │   node: MessagePump | None = self                                                                    │
│   208 │   │   │   while not isinstance(node, App):                                                                   │
│   209 │   │   │   │   if node is None:                                                                               │
│ ❱ 210 │   │   │   │   │   raise NoActiveAppError()                                                                   │
│   211 │   │   │   │   node = node._parent                                                                            │
│   212 │   │   │   active_app.set(node)                                                                               │
│   213 │   │   │   return node                                                                                        │
│                                                                                                                      │
│ ╭───────────── locals ─────────────╮                                                                                 │
│ │  App = <class 'textual.app.App'> │                                                                                 │
│ │ node = None                      │                                                                                 │
│ │ self = DataTable()               │                                                                                 │
│ ╰──────────────────────────────────╯                                                                                 │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
@Textualize Textualize deleted a comment from github-actions bot Dec 24, 2023
@Textualize Textualize locked and limited conversation to collaborators Dec 24, 2023
@davep davep converted this issue into discussion #3927 Dec 24, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant