Skip to content

Commit

Permalink
Merge pull request #2692 from Textualize/switch-screen
Browse files Browse the repository at this point in the history
Fix issue with switch screen.
  • Loading branch information
rodrigogiraoserrao authored May 30, 2023
2 parents 3dea433 + ce771c1 commit ee6f1b9
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 9 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

- Fixed zero division error https://github.com/Textualize/textual/issues/2673
- Fix `scroll_to_center` when there were nested layers out of view (Compositor full_map not populated fully) https://github.com/Textualize/textual/pull/2684
- Issues with `switch_screen` not updating the results callback appropriately https://github.com/Textualize/textual/issues/2650

### Added

Expand All @@ -36,6 +37,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `Tree` and `DirectoryTree` Messages no longer accept a `tree` parameter, using `self.node.tree` instead. https://github.com/Textualize/textual/issues/2529
- Keybinding <kbd>right</kbd> in `Input` is also used to accept a suggestion if the cursor is at the end of the input https://github.com/Textualize/textual/pull/2604
- `Input.__init__` now accepts a `suggester` attribute for completion suggestions https://github.com/Textualize/textual/pull/2604
- Using `switch_screen` to switch to the currently active screen is now a no-op https://github.com/Textualize/textual/pull/2692

### Removed

Expand Down
22 changes: 13 additions & 9 deletions src/textual/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -1611,15 +1611,19 @@ def switch_screen(self, screen: Screen | str) -> AwaitMount:
raise TypeError(
f"switch_screen requires a Screen instance or str; not {screen!r}"
)
if self.screen is not screen:
previous_screen = self._replace_screen(self._screen_stack.pop())
previous_screen._pop_result_callback()
next_screen, await_mount = self._get_screen(screen)
self._screen_stack.append(next_screen)
self.screen.post_message(events.ScreenResume())
self.log.system(f"{self.screen} is current (SWITCHED)")
return await_mount
return AwaitMount(self.screen, [])

next_screen, await_mount = self._get_screen(screen)
if screen is self.screen or next_screen is self.screen:
self.log.system(f"Screen {screen} is already current.")
return AwaitMount(self.screen, [])

previous_screen = self._replace_screen(self._screen_stack.pop())
previous_screen._pop_result_callback()
self._screen_stack.append(next_screen)
self.screen.post_message(events.ScreenResume())
self.screen._push_result_callback(self.screen, None)
self.log.system(f"{self.screen} is current (SWITCHED)")
return await_mount

def install_screen(self, screen: Screen, name: str) -> None:
"""Install a screen.
Expand Down
52 changes: 52 additions & 0 deletions tests/test_screens.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,3 +298,55 @@ async def key_p(self) -> None:
await pilot.press("p")
with pytest.raises(ScreenStackError):
app.bottom.dismiss()


async def test_switch_screen_no_op():
"""Regression test for https://github.com/Textualize/textual/issues/2650"""

class MyScreen(Screen):
pass

class MyApp(App[None]):
SCREENS = {"screen": MyScreen()}

def on_mount(self):
self.push_screen("screen")

app = MyApp()
async with app.run_test():
screen_id = id(app.screen)
app.switch_screen("screen")
assert screen_id == id(app.screen)
app.switch_screen("screen")
assert screen_id == id(app.screen)


async def test_switch_screen_updates_results_callback_stack():
"""Regression test for https://github.com/Textualize/textual/issues/2650"""

class ScreenA(Screen):
pass

class ScreenB(Screen):
pass

class MyApp(App[None]):
SCREENS = {
"a": ScreenA(),
"b": ScreenB(),
}

def callback(self, _):
return 42

def on_mount(self):
self.push_screen("a", self.callback)

app = MyApp()
async with app.run_test():
assert len(app.screen._result_callbacks) == 1
assert app.screen._result_callbacks[-1].callback(None) == 42

app.switch_screen("b")
assert len(app.screen._result_callbacks) == 1
assert app.screen._result_callbacks[-1].callback is None

0 comments on commit ee6f1b9

Please sign in to comment.