Helper to execute code in a given interpreter, e.g. to implement the behavior of python3 [-i] file.py args should be a [faked] sys.argv.
(
interpreter: code.InteractiveInterpreter, args: list[str]
)
| 256 | |
| 257 | |
| 258 | def exec_code( |
| 259 | interpreter: code.InteractiveInterpreter, args: list[str] |
| 260 | ) -> None: |
| 261 | """ |
| 262 | Helper to execute code in a given interpreter, e.g. to implement the behavior of python3 [-i] file.py |
| 263 | |
| 264 | args should be a [faked] sys.argv. |
| 265 | """ |
| 266 | try: |
| 267 | with open(args[0]) as sourcefile: |
| 268 | source = sourcefile.read() |
| 269 | except OSError as e: |
| 270 | # print an error and exit (if -i is specified the calling code will continue) |
| 271 | print(f"bpython: can't open file '{args[0]}: {e}", file=sys.stderr) |
| 272 | raise SystemExit(e.errno) |
| 273 | old_argv, sys.argv = sys.argv, args |
| 274 | sys.path.insert(0, os.path.abspath(os.path.dirname(args[0]))) |
| 275 | spec = importlib.util.spec_from_loader("__main__", loader=None) |
| 276 | assert spec |
| 277 | mod = importlib.util.module_from_spec(spec) |
| 278 | sys.modules["__main__"] = mod |
| 279 | interpreter.locals.update(mod.__dict__) # type: ignore # TODO use a more specific type that has a .locals attribute |
| 280 | interpreter.locals["__file__"] = args[0] # type: ignore # TODO use a more specific type that has a .locals attribute |
| 281 | interpreter.runsource(source, args[0], "exec") |
| 282 | sys.argv = old_argv |