devshell: Add interactive python shell
PATCH 1/1 devshell: Add interactive python shell
Being able to interact with the python context in the Bitbake task execution environment has long been desirable. This patch introduces such a mechanism. Executing "bitbake X -c devpyshell" will open a terminal connected to a python interactive interpretor in the task context so for example you can run commands like "d.getVar('WORKDIR')"
This version fixes various issues with the previous RFC version from a while ago and generally seems to work effectively.
Signed-off-by Richard Purdie <[email protected]>
meta/classes/devshell.bbclass +76 -0
@@ -31,3 +31,79 @@ python () { d.setVarFlag("do_devshell", "manualfakeroot", "1") d.delVarFlag("do_devshell", "fakeroot") } + +python do_devpyshell() { + m, s = os.openpty() + sname = os.ttyname(s) + os.system('stty cs8 -icanon min 1 -isig -echo -F %s > /dev/null 2> /dev/null' % sname) + pid = os.fork() + if pid: + oe_terminal("oepydevshell-internal.py %s" % sname, 'OpenEmbedded Developer PyShell', d) + os._exit(0) + else: + os.dup2(m, sys.stdin.fileno()) + os.dup2(m, sys.stdout.fileno()) + os.dup2(m, sys.stderr.fileno()) + os.close(s) + + sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) + + bb.utils.nonblockingfd(sys.stdout) + bb.utils.nonblockingfd(sys.stderr) + bb.utils.nonblockingfd(sys.stdin) + + _context = { + "os": os, + "bb": bb, + "time": time, + "d": d, + } + + import code, select + + ps1 = "pydevshell> " + ps2 = "... " + buf = [] + more = False + try: + i = code.InteractiveInterpreter(locals=_context) + print("OE PyShell (PN = %s)\n" % d.getVar("PN", True)) + + def prompt(more): + if more: + prompt = ps2 + else: + prompt = ps1 + sys.stdout.write(prompt) + + prompt(more) + while True: + try: + try: + (r, _, _) = select.select([sys.stdin], [], [], 1) + if not r: + continue + line = sys.stdin.readline().strip() + except EOFError as e: + sys.stdout.write("\n") + except (OSError, IOError) as e: + if e.errno == 11: + continue + raise + else: + buf.append(line) + source = "\n".join(buf) + more = i.runsource(source, "<pyshell>") + if not more: + buf = [] + prompt(more) + except KeyboardInterrupt: + i.write("\nKeyboardInterrupt\n") + buf = [] + more = False + except Exception as e: + bb.fatal(str(e)) +} +addtask devpyshell after do_patch + +do_devpyshell[nostamp] = "1"
scripts/oepydevshell-internal.py new file +54 -0
54 lines not on this page · raw message