Runs user code in an interpreter. Running code requests a refresh by calling request_from_main_context(force_refresh=True), which suspends execution of the code and switches back to the main greenlet After load_code() is called with the source code to be run, the run_code() met
| 57 | |
| 58 | |
| 59 | class CodeRunner: |
| 60 | """Runs user code in an interpreter. |
| 61 | |
| 62 | Running code requests a refresh by calling |
| 63 | request_from_main_context(force_refresh=True), which |
| 64 | suspends execution of the code and switches back to the main greenlet |
| 65 | |
| 66 | After load_code() is called with the source code to be run, |
| 67 | the run_code() method should be called to start running the code. |
| 68 | The running code may request screen refreshes and user input |
| 69 | by calling request_from_main_context. |
| 70 | When this are called, the running source code cedes |
| 71 | control, and the current run_code() method call returns. |
| 72 | |
| 73 | The return value of run_code() determines whether the method ought |
| 74 | to be called again to complete execution of the source code. |
| 75 | |
| 76 | Once the screen refresh has occurred or the requested user input |
| 77 | has been gathered, run_code() should be called again, passing in any |
| 78 | requested user input. This continues until run_code returns Done. |
| 79 | |
| 80 | The code greenlet is responsible for telling the main greenlet |
| 81 | what it wants returned in the next run_code call - CodeRunner |
| 82 | just passes whatever is passed in to run_code(for_code) to the |
| 83 | code greenlet |
| 84 | """ |
| 85 | |
| 86 | def __init__(self, interp=None, request_refresh=lambda: None): |
| 87 | """ |
| 88 | interp is an interpreter object to use. By default a new one is |
| 89 | created. |
| 90 | |
| 91 | request_refresh is a function that will be called each time the running |
| 92 | code asks for a refresh - to, for example, update the screen. |
| 93 | """ |
| 94 | self.interp = interp or code.InteractiveInterpreter() |
| 95 | self.source = None |
| 96 | self.main_context = greenlet.getcurrent() |
| 97 | self.code_context = None |
| 98 | self.request_refresh = request_refresh |
| 99 | # waiting for response from main thread |
| 100 | self.code_is_waiting = False |
| 101 | # sigint happened while in main thread |
| 102 | self.sigint_happened_in_main_context = False |
| 103 | self.orig_sigint_handler = None |
| 104 | |
| 105 | @property |
| 106 | def running(self): |
| 107 | """Returns greenlet if code has been loaded greenlet has been |
| 108 | started""" |
| 109 | return self.source and self.code_context |
| 110 | |
| 111 | def load_code(self, source): |
| 112 | """Prep code to be run""" |
| 113 | assert self.source is None, ( |
| 114 | "you shouldn't load code when some is " "already running" |
| 115 | ) |
| 116 | self.source = source |
no outgoing calls