-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request kivy#6368 from matham/async-support
Add async support to kivy App
- Loading branch information
Showing
24 changed files
with
1,533 additions
and
162 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
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,90 @@ | ||
'''Example shows the recommended way of how to run Kivy with the Python built | ||
in asyncio event loop as just another async coroutine. | ||
''' | ||
import asyncio | ||
|
||
from kivy.app import App | ||
from kivy.lang.builder import Builder | ||
|
||
kv = ''' | ||
BoxLayout: | ||
orientation: 'vertical' | ||
BoxLayout: | ||
ToggleButton: | ||
id: btn1 | ||
group: 'a' | ||
text: 'Sleeping' | ||
allow_no_selection: False | ||
on_state: if self.state == 'down': label.status = self.text | ||
ToggleButton: | ||
id: btn2 | ||
group: 'a' | ||
text: 'Swimming' | ||
allow_no_selection: False | ||
on_state: if self.state == 'down': label.status = self.text | ||
ToggleButton: | ||
id: btn3 | ||
group: 'a' | ||
text: 'Reading' | ||
allow_no_selection: False | ||
state: 'down' | ||
on_state: if self.state == 'down': label.status = self.text | ||
Label: | ||
id: label | ||
status: 'Reading' | ||
text: 'Beach status is "{}"'.format(self.status) | ||
''' | ||
|
||
|
||
class AsyncApp(App): | ||
|
||
other_task = None | ||
|
||
def build(self): | ||
return Builder.load_string(kv) | ||
|
||
def app_func(self): | ||
'''This will run both methods asynchronously and then block until they | ||
are finished | ||
''' | ||
self.other_task = asyncio.ensure_future(self.waste_time_freely()) | ||
|
||
async def run_wrapper(): | ||
# we don't actually need to set asyncio as the lib because it is | ||
# the default, but it doesn't hurt to be explicit | ||
await self.async_run(async_lib='asyncio') | ||
print('App done') | ||
self.other_task.cancel() | ||
|
||
return asyncio.gather(run_wrapper(), self.other_task) | ||
|
||
async def waste_time_freely(self): | ||
'''This method is also run by the asyncio loop and periodically prints | ||
something. | ||
''' | ||
try: | ||
i = 0 | ||
while True: | ||
if self.root is not None: | ||
status = self.root.ids.label.status | ||
print('{} on the beach'.format(status)) | ||
|
||
# get some sleep | ||
if self.root.ids.btn1.state != 'down' and i >= 2: | ||
i = 0 | ||
print('Yawn, getting tired. Going to sleep') | ||
self.root.ids.btn1.trigger_action() | ||
|
||
i += 1 | ||
await asyncio.sleep(2) | ||
except asyncio.CancelledError as e: | ||
print('Wasting time was canceled', e) | ||
finally: | ||
# when canceled, print that it finished | ||
print('Done wasting time') | ||
|
||
|
||
if __name__ == '__main__': | ||
loop = asyncio.get_event_loop() | ||
loop.run_until_complete(AsyncApp().app_func()) | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
'''Example shows the recommended way of how to run Kivy with the Python built | ||
in asyncio event loop as just another async coroutine. | ||
''' | ||
import asyncio | ||
|
||
from kivy.app import async_runTouchApp | ||
from kivy.lang.builder import Builder | ||
|
||
kv = ''' | ||
BoxLayout: | ||
orientation: 'vertical' | ||
Button: | ||
id: btn | ||
text: 'Press me' | ||
BoxLayout: | ||
Label: | ||
id: label | ||
text: 'Button is "{}"'.format(btn.state) | ||
''' | ||
|
||
|
||
async def run_app_happily(root, other_task): | ||
'''This method, which runs Kivy, is run by the asyncio loop as one of the | ||
coroutines. | ||
''' | ||
# we don't actually need to set asyncio as the lib because it is the | ||
# default, but it doesn't hurt to be explicit | ||
await async_runTouchApp(root, async_lib='asyncio') # run Kivy | ||
print('App done') | ||
# now cancel all the other tasks that may be running | ||
other_task.cancel() | ||
|
||
|
||
async def waste_time_freely(): | ||
'''This method is also run by the asyncio loop and periodically prints | ||
something. | ||
''' | ||
try: | ||
while True: | ||
print('Sitting on the beach') | ||
await asyncio.sleep(2) | ||
except asyncio.CancelledError as e: | ||
print('Wasting time was canceled', e) | ||
finally: | ||
# when canceled, print that it finished | ||
print('Done wasting time') | ||
|
||
if __name__ == '__main__': | ||
def root_func(): | ||
'''This will run both methods asynchronously and then block until they | ||
are finished | ||
''' | ||
root = Builder.load_string(kv) # root widget | ||
other_task = asyncio.ensure_future(waste_time_freely()) | ||
return asyncio.gather(run_app_happily(root, other_task), other_task) | ||
|
||
loop = asyncio.get_event_loop() | ||
loop.run_until_complete(root_func()) | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
'''Example shows the recommended way of how to run Kivy with a trio | ||
event loop as just another async coroutine. | ||
''' | ||
import trio | ||
|
||
from kivy.app import App | ||
from kivy.lang.builder import Builder | ||
|
||
kv = ''' | ||
BoxLayout: | ||
orientation: 'vertical' | ||
BoxLayout: | ||
ToggleButton: | ||
id: btn1 | ||
group: 'a' | ||
text: 'Sleeping' | ||
allow_no_selection: False | ||
on_state: if self.state == 'down': label.status = self.text | ||
ToggleButton: | ||
id: btn2 | ||
group: 'a' | ||
text: 'Swimming' | ||
allow_no_selection: False | ||
on_state: if self.state == 'down': label.status = self.text | ||
ToggleButton: | ||
id: btn3 | ||
group: 'a' | ||
text: 'Reading' | ||
allow_no_selection: False | ||
state: 'down' | ||
on_state: if self.state == 'down': label.status = self.text | ||
Label: | ||
id: label | ||
status: 'Reading' | ||
text: 'Beach status is "{}"'.format(self.status) | ||
''' | ||
|
||
|
||
class AsyncApp(App): | ||
|
||
nursery = None | ||
|
||
def build(self): | ||
return Builder.load_string(kv) | ||
|
||
async def app_func(self): | ||
'''trio needs to run a function, so this is it. ''' | ||
|
||
async with trio.open_nursery() as nursery: | ||
'''In trio you create a nursery, in which you schedule async | ||
functions to be run by the nursery simultaneously as tasks. | ||
This will run all two methods starting in random order | ||
asynchronously and then block until they are finished or canceled | ||
at the `with` level. ''' | ||
self.nursery = nursery | ||
|
||
async def run_wrapper(): | ||
# trio needs to be set so that it'll be used for the event loop | ||
await self.async_run(async_lib='trio') | ||
print('App done') | ||
nursery.cancel_scope.cancel() | ||
|
||
nursery.start_soon(run_wrapper) | ||
nursery.start_soon(self.waste_time_freely) | ||
|
||
async def waste_time_freely(self): | ||
'''This method is also run by trio and periodically prints something. | ||
''' | ||
try: | ||
i = 0 | ||
while True: | ||
if self.root is not None: | ||
status = self.root.ids.label.status | ||
print('{} on the beach'.format(status)) | ||
|
||
# get some sleep | ||
if self.root.ids.btn1.state != 'down' and i >= 2: | ||
i = 0 | ||
print('Yawn, getting tired. Going to sleep') | ||
self.root.ids.btn1.trigger_action() | ||
|
||
i += 1 | ||
await trio.sleep(2) | ||
except trio.Cancelled as e: | ||
print('Wasting time was canceled', e) | ||
finally: | ||
# when canceled, print that it finished | ||
print('Done wasting time') | ||
|
||
|
||
if __name__ == '__main__': | ||
trio.run(AsyncApp().app_func) |
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,58 @@ | ||
'''Example shows the recommended way of how to run Kivy with a trio | ||
event loop as just another async coroutine. | ||
''' | ||
import trio | ||
from kivy.app import async_runTouchApp | ||
from kivy.lang.builder import Builder | ||
|
||
kv = ''' | ||
BoxLayout: | ||
orientation: 'vertical' | ||
Button: | ||
id: btn | ||
text: 'Press me' | ||
BoxLayout: | ||
Label: | ||
id: label | ||
text: 'Button is "{}"'.format(btn.state) | ||
''' | ||
|
||
|
||
async def run_app_happily(root, nursery): | ||
'''This method, which runs Kivy, is run by trio as one of the coroutines. | ||
''' | ||
# trio needs to be set so that it'll be used for the event loop | ||
await async_runTouchApp(root, async_lib='trio') # run Kivy | ||
print('App done') | ||
# now cancel all the other tasks that may be running | ||
nursery.cancel_scope.cancel() | ||
|
||
|
||
async def waste_time_freely(): | ||
'''This method is also run by trio and periodically prints something.''' | ||
try: | ||
while True: | ||
print('Sitting on the beach') | ||
await trio.sleep(2) | ||
except trio.Cancelled as e: | ||
print('Wasting time was canceled', e) | ||
finally: | ||
# when canceled, print that it finished | ||
print('Done wasting time') | ||
|
||
if __name__ == '__main__': | ||
async def root_func(): | ||
'''trio needs to run a function, so this is it. ''' | ||
|
||
root = Builder.load_string(kv) # root widget | ||
async with trio.open_nursery() as nursery: | ||
'''In trio you create a nursery, in which you schedule async | ||
functions to be run by the nursery simultaneously as tasks. | ||
This will run all two methods starting in random order | ||
asynchronously and then block until they are finished or canceled | ||
at the `with` level. ''' | ||
nursery.start_soon(run_app_happily, root, nursery) | ||
nursery.start_soon(waste_time_freely) | ||
|
||
trio.run(root_func) |
Oops, something went wrong.