Skip to content

Commit

Permalink
Merge pull request #185 from altendky/example_rework
Browse files Browse the repository at this point in the history
replace the readme example with a dialog example
  • Loading branch information
altendky committed Nov 16, 2020
2 parents 0520841 + 51e3c04 commit 15bd8e7
Show file tree
Hide file tree
Showing 9 changed files with 315 additions and 25 deletions.
78 changes: 53 additions & 25 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,39 +41,67 @@ and PyQt5 are supported.

By enabling use of ``async`` and ``await`` it is possible in some cases to write related
code more concisely and clearly than you would get with the signal and slot mechanisms
of Qt concurrency.
of Qt concurrency. See the ``README`` examples in the docs for the full code. The
first example here shows classic pure Qt code.

.. code-block:: python
class TwoStep:
def __init__(self, a_signal, some_path):
self.signal = a_signal
self.file = None
self.some_path = some_path
class Main:
def __init__(
self,
input_dialog: typing.Optional[QtWidgets.QInputDialog] = None,
output_dialog: typing.Optional[QtWidgets.QMessageBox] = None,
):
if input_dialog is None: # pragma: nocover
input_dialog = create_input()
def before(self):
self.file = open(some_path, 'w')
self.signal.connect(self.after)
self.file.write('before')
if output_dialog is None: # pragma: nocover
output_dialog = create_output()
def after(self, value):
self.signal.disconnect(self.after)
self.file.write(f'after {value!r}')
self.file.close()
self.input_dialog = input_dialog
self.output_dialog = output_dialog
def setup(self) -> None:
self.input_dialog.accepted.connect(self.input_accepted)
self.input_dialog.rejected.connect(self.input_rejected)
self.input_dialog.show()
def input_accepted(self) -> None:
name = self.input_dialog.textValue()
self.output_dialog.setText(f"Hi {name}, welcome to the team!")
self.output_dialog.finished.connect(self.output_finished)
self.output_dialog.show()
def input_rejected(self) -> None:
QtCore.QCoreApplication.instance().quit()
def output_finished(self) -> None:
QtCore.QCoreApplication.instance().quit()
The second example, below, shows how using ``async`` and ``await`` allows for more
concise and clearly description of the sequenced activity.

.. code-block:: python
async def together(a_signal):
with open(self.some_path, 'w') as file:
async with qtrio.enter_emissions_channel(signals=[a_signal]) as emissions:
file.write('before')
emission = await emissions.channel.receive()
[value] = emission.args
file.write(f'after {value!r}')
Note how by using ``async`` and ``await`` we are not only able to more clearly and
concisely describe the sequenced activity, we also get to use ``with`` to manage the
context of the open file to be sure it gets closed.
async def main(
input_dialog: typing.Optional[qtrio.dialogs.TextInputDialog] = None,
output_dialog: typing.Optional[qtrio.dialogs.MessageBox] = None,
) -> None:
if input_dialog is None: # pragma: nocover
input_dialog = create_input()
if output_dialog is None: # pragma: nocover
output_dialog = create_output()
with contextlib.suppress(qtrio.UserCancelledError):
name = await input_dialog.wait()
output_dialog.text = f"Hi {name}, welcome to the team!"
await output_dialog.wait()
.. _chat: https://gitter.im/python-trio/general
.. |chat badge| image:: https://img.shields.io/badge/chat-join%20now-blue.svg?color=royalblue&logo=Gitter&logoColor=whitesmoke
Expand Down
1 change: 1 addition & 0 deletions docs/source/examples/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ Examples
:maxdepth: 2

emissions.rst
readme.rst
12 changes: 12 additions & 0 deletions docs/source/examples/readme.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
README
======

Qt
--

.. literalinclude:: ../../../qtrio/examples/readme/qt.py

QTrio
-----

.. literalinclude:: ../../../qtrio/examples/readme/qtrio.py
Empty file.
63 changes: 63 additions & 0 deletions qtrio/_tests/examples/readme/test_qt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from qtpy import QtWidgets

import qtrio.examples.readme.qt


def test_main(qtbot):
input_dialog = qtrio.examples.readme.qt.create_input()
output_dialog = qtrio.examples.readme.qt.create_output()

qtbot.add_widget(input_dialog)
qtbot.add_widget(output_dialog)

text_to_enter = "everyone"

main_object = qtrio.examples.readme.qt.Main(
input_dialog=input_dialog,
output_dialog=output_dialog,
)

main_object.setup()

qtbot.wait_for_window_shown(input_dialog)

[line_edit] = input_dialog.findChildren(QtWidgets.QLineEdit)
line_edit.setText(text_to_enter)
input_dialog.accept()

qtbot.wait_for_window_shown(output_dialog)

output_text = output_dialog.text()

output_dialog.accept()

assert text_to_enter in output_text


def test_main_cancelled(qtbot):
input_dialog = qtrio.examples.readme.qt.create_input()
output_dialog = qtrio.examples.readme.qt.create_output()

qtbot.add_widget(input_dialog)
qtbot.add_widget(output_dialog)

text_to_enter = "everyone"

main_object = qtrio.examples.readme.qt.Main(
input_dialog=input_dialog,
output_dialog=output_dialog,
)

main_object.setup()

qtbot.wait_for_window_shown(input_dialog)

[line_edit] = input_dialog.findChildren(QtWidgets.QLineEdit)
line_edit.setText(text_to_enter)
input_dialog.reject()

# qtbot.wait(1_000)

output_text = output_dialog.text()

assert output_text == ""
72 changes: 72 additions & 0 deletions qtrio/_tests/examples/readme/test_qtrio.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import trio

import qtrio.examples.readme.qtrio


async def test_main():
input_dialog = qtrio.examples.readme.qtrio.create_input()
output_dialog = qtrio.examples.readme.qtrio.create_output()

text_to_enter = "everyone"

async def user(task_status):
async with qtrio._core.wait_signal_context(input_dialog.shown):
task_status.started()

assert input_dialog.line_edit is not None
input_dialog.line_edit.setText(text_to_enter)

assert input_dialog.accept_button is not None
async with qtrio._core.wait_signal_context(output_dialog.shown):
input_dialog.accept_button.click()

assert output_dialog.dialog is not None
output_text = output_dialog.dialog.text()

assert output_dialog.accept_button is not None
output_dialog.accept_button.click()

assert text_to_enter in output_text

async with trio.open_nursery() as nursery:
await nursery.start(user)

await qtrio.examples.readme.qtrio.main(
input_dialog=input_dialog,
output_dialog=output_dialog,
)


async def test_main_cancelled():
input_dialog = qtrio.examples.readme.qtrio.create_input()
output_dialog = qtrio.examples.readme.qtrio.create_output()

text_to_enter = "everyone"

output_shown = False

def output_was_shown():
nonlocal output_shown
output_shown = True # pragma: no cover

output_dialog.shown.connect(output_was_shown)

async def user(task_status):
async with qtrio._core.wait_signal_context(input_dialog.shown):
task_status.started()

assert input_dialog.line_edit is not None
input_dialog.line_edit.setText(text_to_enter)

assert input_dialog.reject_button is not None
input_dialog.reject_button.click()

async with trio.open_nursery() as nursery:
await nursery.start(user)

await qtrio.examples.readme.qtrio.main(
input_dialog=input_dialog,
output_dialog=output_dialog,
)

assert not output_shown
Empty file.
69 changes: 69 additions & 0 deletions qtrio/examples/readme/qt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import typing

from qtpy import QtCore
from qtpy import QtWidgets


def create_input() -> QtWidgets.QInputDialog:
dialog = QtWidgets.QInputDialog()
dialog.setWindowTitle("Hello")
dialog.setLabelText("Enter your name:")

return dialog


def create_output() -> QtWidgets.QMessageBox:
return QtWidgets.QMessageBox(
QtWidgets.QMessageBox.Icon.Question,
"Hello",
"",
QtWidgets.QMessageBox.Ok,
)


class Main:
def __init__(
self,
input_dialog: typing.Optional[QtWidgets.QInputDialog] = None,
output_dialog: typing.Optional[QtWidgets.QMessageBox] = None,
):
if input_dialog is None: # pragma: no cover
input_dialog = create_input()

if output_dialog is None: # pragma: no cover
output_dialog = create_output()

self.input_dialog = input_dialog
self.output_dialog = output_dialog

def setup(self) -> None:
self.input_dialog.accepted.connect(self.input_accepted)
self.input_dialog.rejected.connect(self.input_rejected)

self.input_dialog.show()

def input_accepted(self) -> None:
name = self.input_dialog.textValue()

self.output_dialog.setText(f"Hi {name}, welcome to the team!")

self.output_dialog.finished.connect(self.output_finished)
self.output_dialog.show()

def input_rejected(self) -> None:
QtCore.QCoreApplication.instance().quit()

def output_finished(self) -> None:
QtCore.QCoreApplication.instance().quit()


def main() -> None: # pragma: no cover
application = QtWidgets.QApplication([])
application.setQuitOnLastWindowClosed(False)
main_object = Main()
main_object.setup()
application.exec_()


if __name__ == "__main__": # pragma: no cover
main()
45 changes: 45 additions & 0 deletions qtrio/examples/readme/qtrio.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import contextlib
import typing

from qtpy import QtWidgets

import qtrio
import qtrio.dialogs


def create_input() -> qtrio.dialogs.TextInputDialog:
return qtrio.dialogs.create_text_input_dialog(
title="Hello",
label="Enter your name:",
)


def create_output() -> qtrio.dialogs.MessageBox:
return qtrio.dialogs.create_message_box(
title="Hello",
text="",
icon=QtWidgets.QMessageBox.Icon.Question,
buttons=QtWidgets.QMessageBox.Ok,
)


async def main(
input_dialog: typing.Optional[qtrio.dialogs.TextInputDialog] = None,
output_dialog: typing.Optional[qtrio.dialogs.MessageBox] = None,
) -> None:
if input_dialog is None: # pragma: no cover
input_dialog = create_input()

if output_dialog is None: # pragma: no cover
output_dialog = create_output()

with contextlib.suppress(qtrio.UserCancelledError):
name = await input_dialog.wait()

output_dialog.text = f"Hi {name}, welcome to the team!"

await output_dialog.wait()


if __name__ == "__main__": # pragma: no cover
qtrio.run(main)

0 comments on commit 15bd8e7

Please sign in to comment.