aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Lib/asyncio/__main__.py
blob: abe8e722dda04b2e76348c27b977b032c749696a (plain) (blame)
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import ast 
import asyncio 
import code 
import concurrent.futures 
import inspect 
import sys 
import threading 
import types 
import warnings 
 
from . import futures 
 
 
class AsyncIOInteractiveConsole(code.InteractiveConsole): 
 
    def __init__(self, locals, loop): 
        super().__init__(locals) 
        self.compile.compiler.flags |= ast.PyCF_ALLOW_TOP_LEVEL_AWAIT 
 
        self.loop = loop 
 
    def runcode(self, code): 
        future = concurrent.futures.Future() 
 
        def callback(): 
            global repl_future 
            global repl_future_interrupted 
 
            repl_future = None 
            repl_future_interrupted = False 
 
            func = types.FunctionType(code, self.locals) 
            try: 
                coro = func() 
            except SystemExit: 
                raise 
            except KeyboardInterrupt as ex: 
                repl_future_interrupted = True 
                future.set_exception(ex) 
                return 
            except BaseException as ex: 
                future.set_exception(ex) 
                return 
 
            if not inspect.iscoroutine(coro): 
                future.set_result(coro) 
                return 
 
            try: 
                repl_future = self.loop.create_task(coro) 
                futures._chain_future(repl_future, future) 
            except BaseException as exc: 
                future.set_exception(exc) 
 
        loop.call_soon_threadsafe(callback) 
 
        try: 
            return future.result() 
        except SystemExit: 
            raise 
        except BaseException: 
            if repl_future_interrupted: 
                self.write("\nKeyboardInterrupt\n") 
            else: 
                self.showtraceback() 
 
 
class REPLThread(threading.Thread): 
 
    def run(self): 
        try: 
            banner = ( 
                f'asyncio REPL {sys.version} on {sys.platform}\n' 
                f'Use "await" directly instead of "asyncio.run()".\n' 
                f'Type "help", "copyright", "credits" or "license" ' 
                f'for more information.\n' 
                f'{getattr(sys, "ps1", ">>> ")}import asyncio' 
            ) 
 
            console.interact( 
                banner=banner, 
                exitmsg='exiting asyncio REPL...') 
        finally: 
            warnings.filterwarnings( 
                'ignore', 
                message=r'^coroutine .* was never awaited$', 
                category=RuntimeWarning) 
 
            loop.call_soon_threadsafe(loop.stop) 
 
 
if __name__ == '__main__': 
    loop = asyncio.new_event_loop() 
    asyncio.set_event_loop(loop) 
 
    repl_locals = {'asyncio': asyncio} 
    for key in {'__name__', '__package__', 
                '__loader__', '__spec__', 
                '__builtins__', '__file__'}: 
        repl_locals[key] = locals()[key] 
 
    console = AsyncIOInteractiveConsole(repl_locals, loop) 
 
    repl_future = None 
    repl_future_interrupted = False 
 
    try: 
        import readline  # NoQA 
    except ImportError: 
        pass 
 
    repl_thread = REPLThread() 
    repl_thread.daemon = True 
    repl_thread.start() 
 
    while True: 
        try: 
            loop.run_forever() 
        except KeyboardInterrupt: 
            if repl_future and not repl_future.done(): 
                repl_future.cancel() 
                repl_future_interrupted = True 
            continue 
        else: 
            break