Skip to content
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

Speculative fix for intermittent Wayland issue. #2891

Closed
wants to merge 3 commits into from

Conversation

freakboy3742
Copy link
Member

A speculative fix for the intermittent Wayland issue. Experimentally from #2873, the issue appears to be that no widget has focus as a result of the other.focus() call; one theory is that due to the timing on some machines, the "other" widget isn't quite ready to receive focus. Add a short delay before assigning focus to test that theory.

Fixes #2871.

PR Checklist:

  • All new features have been tested
  • All new features have been documented
  • I have read the CONTRIBUTING.md file
  • I will abide by the code of conduct

@rmartin16
Copy link
Member

As another datapoint, this delay was my first strategy...but I didn't have any luck :/

@freakboy3742
Copy link
Member Author

As another datapoint, this delay was my first strategy...but I didn't have any luck :/

Hrm... your original PR has collapsed all its commit history - I don't suppose you have any records of the specific change you made? In particular, did you do a probe.redraw() or probe.redraw(delay=0.1)? Because this PR seems to be fairly resilient - 5 attempts over an hour have all passed... if you did the former, maybe the trick is the longer pause...

@rmartin16
Copy link
Member

I never actually pushed changes that included a delay because no matter how I incorporated a delay locally changed anything. In #2873, I was mostly just trying to confirm that none of the widgets had focus when the test failed in CI...which is what I was seeing locally.

Also, FWIW, this is how I test locally:

while true; do WAYLAND_DISPLAY=toga briefcase run --test -- tests/widgets/; sleep 3; done

I delete first tests/widgets/test_mapview.py since it's too slow and doesn't seem to impact testing.

Additional FWIW, it fails very often on my machine....so, slower machines like CI may be even less likely to experience this failure.

@freakboy3742
Copy link
Member Author

Additional FWIW, it fails very often on my machine....so, slower machines like CI may be even less likely to experience this failure.

Could I ask you to take the latest commit on this branch for a spin? It's takes a bit more of a persistent retry approach; if you've got a case that reproduces it (or, at least, more reliably reproduces it than CI), that would be helpful - I don't see it locally.

@rmartin16
Copy link
Member

rmartin16 commented Oct 8, 2024

failing currently

AttributeError: 'TextInput' object has no attribute 'has_focus'
_______________________________ test_focus_noop ________________________________
Traceback (most recent call last):
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/_pytest/runner.py", line 341, in from_call
    result: TResult | None = func()
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/_pytest/runner.py", line 242, in <lambda>
    lambda: runtest_hook(item=item, **kwds), when=when, reraise=reraise
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/pluggy/_hooks.py", line 513, in __call__
    return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/pluggy/_manager.py", line 120, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/pluggy/_callers.py", line 139, in _multicall
    raise exception.with_traceback(exception.__traceback__)
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/pluggy/_callers.py", line 122, in _multicall
    teardown.throw(exception)  # type: ignore[union-attr]
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/_pytest/threadexception.py", line 92, in pytest_runtest_call
    yield from thread_exception_runtest_hook()
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/_pytest/threadexception.py", line 68, in thread_exception_runtest_hook
    yield
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/pluggy/_callers.py", line 122, in _multicall
    teardown.throw(exception)  # type: ignore[union-attr]
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/_pytest/unraisableexception.py", line 95, in pytest_runtest_call
    yield from unraisable_exception_runtest_hook()
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/_pytest/unraisableexception.py", line 70, in unraisable_exception_runtest_hook
    yield
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/pluggy/_callers.py", line 122, in _multicall
    teardown.throw(exception)  # type: ignore[union-attr]
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/_pytest/logging.py", line 846, in pytest_runtest_call
    yield from self._runtest_for(item, "call")
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/_pytest/logging.py", line 829, in _runtest_for
    yield
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/pluggy/_callers.py", line 122, in _multicall
    teardown.throw(exception)  # type: ignore[union-attr]
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/_pytest/capture.py", line 880, in pytest_runtest_call
    return (yield)
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/pluggy/_callers.py", line 122, in _multicall
    teardown.throw(exception)  # type: ignore[union-attr]
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/_pytest/skipping.py", line 257, in pytest_runtest_call
    return (yield)
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/pluggy/_callers.py", line 103, in _multicall
    res = hook_impl.function(*args)
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/_pytest/runner.py", line 174, in pytest_runtest_call
    item.runtest()
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/pytest_asyncio/plugin.py", line 457, in runtest
    super().runtest()
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/_pytest/python.py", line 1627, in runtest
    self.ihook.pytest_pyfunc_call(pyfuncitem=self)
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/pluggy/_hooks.py", line 513, in __call__
    return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/pluggy/_manager.py", line 120, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/pluggy/_callers.py", line 182, in _multicall
    return outcome.get_result()
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/pluggy/_result.py", line 100, in get_result
    raise exc.with_traceback(exc.__traceback__)
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/pluggy/_callers.py", line 103, in _multicall
    res = hook_impl.function(*args)
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/_pytest/python.py", line 159, in pytest_pyfunc_call
    result = testfunction(**testargs)
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app_packages/pytest_asyncio/plugin.py", line 929, in inner
    _loop.run_until_complete(task)
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app/tests/conftest.py", line 142, in run_until_complete
    return asyncio.run_coroutine_threadsafe(coro, self.loop).result()
  File "/usr/lib/python3.10/concurrent/futures/_base.py", line 458, in result
    return self.__get_result()
  File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
    raise self._exception
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app/tests/widgets/properties.py", line 120, in test_focus_noop
    await ensure_initial_focus(other, other_probe)
  File "/home/russell/github/beeware/toga/testbed/build/testbed/pop/jammy/testbed-0.0.1/usr/lib/testbed/app/tests/widgets/properties.py", line 68, in ensure_initial_focus
    if widget.has_focus:
AttributeError: 'TextInput' object has no attribute 'has_focus'

@freakboy3742
Copy link
Member Author

AttributeError: 'TextInput' object has no attribute 'has_focus'

🤦

Save all the file before pushing, Russell...

Try it now.

@rmartin16
Copy link
Member

🤣 no worries

Got this on my 2nd or 3rd run:

=========================== short test summary info ============================
FAILED tests/widgets/test_slider.py::test_focus - Failed: Unable to give initial focus to widget
FAILED tests/widgets/test_splitcontainer.py::test_focus_noop - Failed: Unable to give initial focus to widget
FAILED tests/widgets/test_switch.py::test_focus_noop - Failed: Unable to give initial focus to widget
FAILED tests/widgets/test_table.py::test_focus_noop - Failed: Unable to give initial focus to widget
FAILED tests/widgets/test_textinput.py::test_focus - Failed: Unable to give initial focus to widget
FAILED tests/widgets/test_tree.py::test_focus_noop - Failed: Unable to give initial focus to widget
FAILED tests/widgets/test_webview.py::test_focus - Failed: Unable to give initial focus to widget
======= 7 failed, 306 passed, 47 skipped, 1 xfailed, 1 xpassed in 51.49s =======

@freakboy3742
Copy link
Member Author

Got this on my 2nd or 3rd run:

Whelp. And the first run in CI.

This one is a doozy...

@freakboy3742
Copy link
Member Author

Closing on the basis that #2893 fixes the problem.

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 this pull request may close these issues.

Intermittent CI failure on linux-wayland testbed
2 participants