File: async_call.py

package info (click to toggle)
cmd2 3.2.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 2,664 kB
  • sloc: python: 17,488; makefile: 114; sh: 39; javascript: 7
file content (80 lines) | stat: -rwxr-xr-x 2,062 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/usr/bin/env python
"""A simple example demonstrating calling an async function from a cmd2 app."""

import asyncio
import concurrent.futures
import threading

import cmd2

_event_loop = None
_event_lock = threading.Lock()


def run_async(coro) -> concurrent.futures.Future:
    """
    Await a coroutine from a synchronous function/method.
    """

    global _event_loop  # noqa: PLW0603

    if _event_loop is None:
        with _event_lock:
            if _event_loop is None:
                _event_loop = asyncio.new_event_loop()
                thread = threading.Thread(
                    target=_event_loop.run_forever,
                    name='Async Runner',
                    daemon=True,
                )
                thread.start()

    return asyncio.run_coroutine_threadsafe(coro, _event_loop)


async def async_wait(duration: float) -> float:
    """
    Example async function that is called from a synchronous cmd2 command
    """
    await asyncio.sleep(duration)
    return duration


class AsyncCallExample(cmd2.Cmd):
    """
    A simple cmd2 application.
    Demonstrates how to run an async function from a cmd2 command.
    """

    def do_async_wait(self, _: str) -> None:
        """
        Waits asynchronously.  Example cmd2 command that calls an async function.
        """

        waitable = run_async(async_wait(0.1))
        self.poutput('Begin waiting...')
        # Wait for coroutine to complete and get its return value:
        res = waitable.result()
        self.poutput(f'Done waiting: {res}')
        return

    def do_hello_world(self, _: str) -> None:
        """
        Prints a simple greeting.  Just a typical (synchronous) cmd2 command
        """
        self.poutput('Hello World')


async def main() -> int:
    """
    Having this async ensures presence of the top level event loop.
    """
    app = AsyncCallExample()
    app.set_window_title("Call to an Async Function Test")
    return app.cmdloop()


if __name__ == '__main__':
    import sys

    sys.exit(asyncio.run(main(), debug=True))