Skip to content

Commit

Permalink
Merge pull request #5039 from Textualize/inline-exit-fix
Browse files Browse the repository at this point in the history
fix error when exiting inline more prematurely
  • Loading branch information
willmcgugan authored Sep 24, 2024
2 parents 322a85c + 8212f4c commit c3e00ae
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 4 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## Unreleased

### Fixed

- Fixed crash when exiting the app prematurely https://github.com/Textualize/textual/pull/5039

## [0.80.0] - 2024-09-23

### Added
Expand Down
1 change: 1 addition & 0 deletions src/textual/drivers/linux_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ def process_selector_events(
try:
while not self.exit_event.is_set():
process_selector_events(selector.select(0.1))
selector.unregister(self.fileno)
process_selector_events(selector.select(0.1), final=True)

finally:
Expand Down
7 changes: 5 additions & 2 deletions src/textual/drivers/linux_inline_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,11 @@ def process_selector_events(
self.cursor_origin = (event.x, event.y)
else:
self.process_event(event)
self.process_event(event)

try:
while not self.exit_event.is_set():
process_selector_events(selector.select(0.1))
selector.unregister(self.fileno)
process_selector_events(selector.select(0.1), final=True)

finally:
Expand Down Expand Up @@ -296,7 +296,10 @@ def disable_input(self) -> None:
if self._key_thread is not None:
self._key_thread.join()
self.exit_event.clear()
termios.tcflush(self.fileno, termios.TCIFLUSH)
try:
termios.tcflush(self.fileno, termios.TCIFLUSH)
except termios.error:
pass

except Exception as error:
# TODO: log this
Expand Down
2 changes: 1 addition & 1 deletion src/textual/screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ def render(self) -> RenderableType:
background = self.styles.background
try:
base_screen = visible_screen_stack.get().pop()
except IndexError:
except LookupError:
base_screen = None

if base_screen is not None and background.a < 1:
Expand Down
1 change: 1 addition & 0 deletions src/textual/widgets/_directory_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class DirectoryTree(Tree[DirEntry]):
ICON_NODE_EXPANDED = "📂 "
ICON_NODE = "📁 "
ICON_FILE = "📄 "
"""Unicode 'icon' to represent a file."""

COMPONENT_CLASSES: ClassVar[set[str]] = {
"directory-tree--extension",
Expand Down
2 changes: 2 additions & 0 deletions src/textual/widgets/_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,9 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True):
"""A widget for displaying and navigating data in a tree."""

ICON_NODE = "▶ "
"""Unicode 'icon' to use for an expandable node."""
ICON_NODE_EXPANDED = "▼ "
"""Unicode 'icon' to use for an expanded node."""

BINDINGS: ClassVar[list[BindingType]] = [
Binding("shift+left", "cursor_parent", "Cursor to parent", show=False),
Expand Down
35 changes: 34 additions & 1 deletion tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from rich.terminal_theme import DIMMED_MONOKAI, MONOKAI, NIGHT_OWLISH

from textual.app import App, ComposeResult
from textual.widgets import Button, Input
from textual.widgets import Button, Input, Static


def test_batch_update():
Expand Down Expand Up @@ -140,3 +140,36 @@ async def test_ansi_theme():

app.dark = True
assert app.ansi_theme == DIMMED_MONOKAI


async def test_early_exit():
"""Test exiting early doesn't cause issues."""
from textual.app import App

class AppExit(App):
def compose(self):
yield Static("Hello")

def on_mount(self) -> None:
# Exit after creating app
self.exit()

app = AppExit()
async with app.run_test():
pass


def test_early_exit_inline():
"""Test exiting early in inline mode doesn't break."""
from textual.app import App

class AppExit(App):
def compose(self):
yield Static("Hello")

def on_mount(self) -> None:
# Exit after creating app
self.exit()

app = AppExit()
app.run(inline=True, inline_no_clear=True)

0 comments on commit c3e00ae

Please sign in to comment.