-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Update and organize examples * Remove an unused class variable * Use Python's type hint * Make executor example actually work * Make the linter happy with tests * Improve code readability * Fix a wrong comment * Simplify code * Simplify code * Fix variable names * Fix the warning from session creation * Simplify code * Organize code * Restore some variables for compatibility * Improve README * Improve guides * Fix a title * Improve details * Make the basic example copy paste complete, tidy up the intro * Add an example using QML * Revert accidentally removed hunk --------- Co-authored-by: Alex March <[email protected]>
- Loading branch information
Showing
8 changed files
with
281 additions
and
71 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,98 +1,82 @@ | ||
import asyncio | ||
import functools | ||
import sys | ||
|
||
import aiohttp | ||
|
||
# from PyQt5.QtWidgets import ( | ||
from PySide2.QtWidgets import ( | ||
QWidget, | ||
# from PyQt6.QtWidgets import ( | ||
from PySide6.QtWidgets import ( | ||
QApplication, | ||
QLabel, | ||
QLineEdit, | ||
QTextEdit, | ||
QPushButton, | ||
QTextEdit, | ||
QVBoxLayout, | ||
QWidget, | ||
) | ||
|
||
import qasync | ||
from qasync import asyncSlot, asyncClose, QApplication | ||
from qasync import QEventLoop, asyncClose, asyncSlot | ||
|
||
|
||
class MainWindow(QWidget): | ||
"""Main window.""" | ||
|
||
_DEF_URL = "https://jsonplaceholder.typicode.com/todos/1" | ||
"""str: Default URL.""" | ||
|
||
_SESSION_TIMEOUT = 1.0 | ||
"""float: Session timeout.""" | ||
_DEF_URL: str = "https://jsonplaceholder.typicode.com/todos/1" | ||
"""Default URL.""" | ||
|
||
def __init__(self): | ||
super().__init__() | ||
|
||
self.setLayout(QVBoxLayout()) | ||
|
||
self.lblStatus = QLabel("Idle", self) | ||
self.layout().addWidget(self.lblStatus) | ||
self.lbl_status = QLabel("Idle", self) | ||
self.layout().addWidget(self.lbl_status) | ||
|
||
self.editUrl = QLineEdit(self._DEF_URL, self) | ||
self.layout().addWidget(self.editUrl) | ||
self.edit_url = QLineEdit(self._DEF_URL, self) | ||
self.layout().addWidget(self.edit_url) | ||
|
||
self.editResponse = QTextEdit("", self) | ||
self.layout().addWidget(self.editResponse) | ||
self.edit_response = QTextEdit("", self) | ||
self.layout().addWidget(self.edit_response) | ||
|
||
self.btnFetch = QPushButton("Fetch", self) | ||
self.btnFetch.clicked.connect(self.on_btnFetch_clicked) | ||
self.layout().addWidget(self.btnFetch) | ||
self.btn_fetch = QPushButton("Fetch", self) | ||
self.btn_fetch.clicked.connect(self.on_btn_fetch_clicked) | ||
self.layout().addWidget(self.btn_fetch) | ||
|
||
self.session = aiohttp.ClientSession( | ||
loop=asyncio.get_event_loop(), | ||
timeout=aiohttp.ClientTimeout(total=self._SESSION_TIMEOUT), | ||
) | ||
self.session: aiohttp.ClientSession | ||
|
||
@asyncClose | ||
async def closeEvent(self, event): | ||
async def closeEvent(self, event): # noqa:N802 | ||
await self.session.close() | ||
|
||
async def boot(self): | ||
self.session = aiohttp.ClientSession() | ||
|
||
@asyncSlot() | ||
async def on_btnFetch_clicked(self): | ||
self.btnFetch.setEnabled(False) | ||
self.lblStatus.setText("Fetching...") | ||
async def on_btn_fetch_clicked(self): | ||
self.btn_fetch.setEnabled(False) | ||
self.lbl_status.setText("Fetching...") | ||
|
||
try: | ||
async with self.session.get(self.editUrl.text()) as r: | ||
self.editResponse.setText(await r.text()) | ||
async with self.session.get(self.edit_url.text()) as r: | ||
self.edit_response.setText(await r.text()) | ||
except Exception as exc: | ||
self.lblStatus.setText("Error: {}".format(exc)) | ||
self.lbl_status.setText("Error: {}".format(exc)) | ||
else: | ||
self.lblStatus.setText("Finished!") | ||
self.lbl_status.setText("Finished!") | ||
finally: | ||
self.btnFetch.setEnabled(True) | ||
|
||
|
||
async def main(): | ||
def close_future(future, loop): | ||
loop.call_later(10, future.cancel) | ||
future.cancel() | ||
self.btn_fetch.setEnabled(True) | ||
|
||
loop = asyncio.get_event_loop() | ||
future = asyncio.Future() | ||
|
||
app = QApplication.instance() | ||
if hasattr(app, "aboutToQuit"): | ||
getattr(app, "aboutToQuit").connect( | ||
functools.partial(close_future, future, loop) | ||
) | ||
|
||
mainWindow = MainWindow() | ||
mainWindow.show() | ||
if __name__ == "__main__": | ||
app = QApplication(sys.argv) | ||
|
||
await future | ||
return True | ||
event_loop = QEventLoop(app) | ||
asyncio.set_event_loop(event_loop) | ||
|
||
app_close_event = asyncio.Event() | ||
app.aboutToQuit.connect(app_close_event.set) | ||
|
||
main_window = MainWindow() | ||
main_window.show() | ||
|
||
if __name__ == "__main__": | ||
try: | ||
qasync.run(main()) | ||
except asyncio.exceptions.CancelledError: | ||
sys.exit(0) | ||
event_loop.create_task(main_window.boot()) | ||
event_loop.run_until_complete(app_close_event.wait()) | ||
event_loop.close() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import sys | ||
import asyncio | ||
from pathlib import Path | ||
|
||
from qasync import QEventLoop, QApplication | ||
from PySide6.QtCore import QUrl | ||
from PySide6.QtQml import QQmlApplicationEngine, qmlRegisterType | ||
|
||
from service import ExampleService | ||
|
||
QML_PATH = Path(__file__).parent.absolute().joinpath("qml") | ||
|
||
|
||
if __name__ == "__main__": | ||
app = QApplication(sys.argv) | ||
|
||
engine = QQmlApplicationEngine() | ||
engine.addImportPath(QML_PATH) | ||
|
||
app.aboutToQuit.connect(engine.deleteLater) | ||
engine.quit.connect(app.quit) | ||
|
||
# register our service, making it usable directly in QML | ||
qmlRegisterType(ExampleService, "qasync", 1, 0, ExampleService.__name__) | ||
|
||
# alternatively, instantiate the service and inject it into the QML engine | ||
# service = ExampleService() | ||
# engine.rootContext().setContextProperty("service", service) | ||
|
||
event_loop = QEventLoop(app) | ||
asyncio.set_event_loop(event_loop) | ||
|
||
app_close_event = asyncio.Event() | ||
app.aboutToQuit.connect(app_close_event.set) | ||
engine.quit.connect(app_close_event.set) | ||
|
||
qml_entry = QUrl.fromLocalFile(str(QML_PATH.joinpath("Main.qml"))) | ||
engine.load(qml_entry) | ||
|
||
with event_loop: | ||
event_loop.run_until_complete(app_close_event.wait()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import QtQuick 2.15 | ||
import QtQuick.Controls 2.15 | ||
import QtQuick.Layouts 1.15 | ||
import QtQuick.Window 2.15 | ||
|
||
ApplicationWindow { | ||
id: root | ||
title: "qasync" | ||
visible: true | ||
width: 420 | ||
height: 240 | ||
|
||
Loader { | ||
id: mainLoader | ||
anchors.fill: parent | ||
source: "Page.qml" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import QtQuick 2.15 | ||
import QtQuick.Controls 2.15 | ||
import QtQuick.Controls.Material 2.15 | ||
import QtQuick.Layouts 1.15 | ||
|
||
Item { | ||
ExampleService { | ||
id: service | ||
|
||
// handle value changes inside the service object | ||
onValueChanged: { | ||
// use value | ||
} | ||
} | ||
|
||
Connections { | ||
target: service | ||
|
||
// handle value changes with an external Connection | ||
function onValueChanged(value) { | ||
// use value | ||
} | ||
} | ||
|
||
ColumnLayout { | ||
anchors { | ||
fill: parent | ||
margins: 10 | ||
} | ||
|
||
RowLayout { | ||
Layout.fillWidth: true | ||
|
||
Button { | ||
id: button | ||
Layout.preferredWidth: 100 | ||
enabled: !service.isLoading | ||
|
||
text: { | ||
return service.isLoading ? qsTr("Loading...") : qsTr("Fetch") | ||
} | ||
onClicked: function() { | ||
service.fetch(url.text) | ||
} | ||
} | ||
|
||
TextField { | ||
id: url | ||
Layout.fillWidth: true | ||
enabled: !service.isLoading | ||
text: qsTr("https://jsonplaceholder.typicode.com/todos/1") | ||
} | ||
} | ||
|
||
TextEdit { | ||
id: text | ||
Layout.fillHeight: true | ||
Layout.fillWidth: true | ||
|
||
// react to value changes from other widgets | ||
text: service.value | ||
} | ||
} | ||
|
||
} |
Oops, something went wrong.