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]> diff --git a/meta/classes/devshell.bbclass b/meta/classes/devshell.bbclass index 92edb9e..a8e707d 100644 --- a/meta/classes/devshell.bbclass +++ b/meta/classes/devshell.bbclass @@ -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" diff --git a/scripts/oepydevshell-internal.py b/scripts/oepydevshell-internal.py new file mode 100755 index 0000000..11bb828 --- /dev/null +++ b/scripts/oepydevshell-internal.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python + +import os +import sys +import time +import select +import fcntl + +def nonblockingfd(fd): + fcntl.fcntl(fd, fcntl.F_SETFL, fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK) + +if len(sys.argv) != 2: + print("Incorrect parameters") + sys.exit(1) + +try: + pty = open(sys.argv[1], "w+b", 0) + nonblockingfd(pty) + nonblockingfd(sys.stdin) + # Don't buffer output by line endings + sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) + + i = "" + o = "" + + while True: + writers = [] + if i: + writers.append(sys.stdout) + if o: + writers.append(pty) + (ready, _, _) = select.select([pty, sys.stdin], writers , [], 1) + try: + if pty in ready: + i = i + pty.read() + if i: + # Write a page at a time to avoid overflowing output + # d.keys() is a good way to do that + sys.stdout.write(i[:4096]) + i = i[4096:] + if sys.stdin in ready: + o = o + sys.stdin.read() + if o: + pty.write(o) + o = "" + except (IOError, OSError) as e: + if e.errno == 11: + continue + raise +except Exception as e: + print("Exception in oepydehshell-internal: " + str(e)) + time.sleep(5) + + -- _______________________________________________ Openembedded-core mailing list [email protected] http://lists.openembedded.org/mailman/listinfo/openembedded-core
