mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-10 01:34:12 +00:00
Add ipython shell to proxyclient
Same functionality as the readline shell, but based on ipython so that it has nicer help/autocomplete/etc Signed-off-by: Daniel Berlin <dberlin@dberlin.org>
This commit is contained in:
parent
232836bd64
commit
b48c6d2ea4
3 changed files with 212 additions and 0 deletions
177
proxyclient/m1n1/ishell.py
Normal file
177
proxyclient/m1n1/ishell.py
Normal file
|
@ -0,0 +1,177 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
import builtins
|
||||
import sys
|
||||
|
||||
import __main__
|
||||
from IPython import embed
|
||||
from traitlets.config import get_config
|
||||
|
||||
c = get_config()
|
||||
c.InteractiveShellEmbed.colors = "Linux"
|
||||
from inspect import signature
|
||||
|
||||
from . import sysreg
|
||||
from .proxy import *
|
||||
from .proxyutils import *
|
||||
from .utils import *
|
||||
|
||||
__all__ = ["run_ishell"]
|
||||
|
||||
|
||||
cmd_list = {}
|
||||
subcmd_list = {}
|
||||
# Debug levels
|
||||
DBL_NONE = 0
|
||||
DBL_INFO = 1
|
||||
DBL_TRACE = 2
|
||||
DBL_DEBUG = 3
|
||||
DBL_EDEBUG = 4
|
||||
|
||||
db_level = DBL_NONE
|
||||
|
||||
|
||||
def debug_cmd(db=None):
|
||||
"""Set debug level to integer %d(none)...%d(extreme debug)""" % (
|
||||
DBL_NONE,
|
||||
DBL_EDEBUG,
|
||||
)
|
||||
global db_level
|
||||
if db:
|
||||
db_level = db
|
||||
print("debug level=%d" % db_level)
|
||||
|
||||
|
||||
def help_cmd(arg=None):
|
||||
if db_level >= DBL_DEBUG:
|
||||
print("arg=%s" % repr(arg))
|
||||
if arg:
|
||||
# cmd = arg.__qualname__
|
||||
if callable(arg):
|
||||
cmd = arg.__name__
|
||||
elif isinstance(arg, str):
|
||||
cmd = arg
|
||||
else:
|
||||
print("Unknown command: %s" % repr(arg))
|
||||
return
|
||||
if db_level >= DBL_DEBUG:
|
||||
print("cmd=%s" % repr(cmd))
|
||||
if cmd not in cmd_list:
|
||||
print("Undocumented command %s" % cmd)
|
||||
return
|
||||
hinfo = cmd_list[cmd]
|
||||
if isinstance(hinfo, str):
|
||||
print("%-10s : %s" % (cmd, hinfo))
|
||||
return
|
||||
if cmd in subcmd_list:
|
||||
clist = subcmd_list[cmd]
|
||||
aname = cmd
|
||||
if db_level >= DBL_DEBUG:
|
||||
print("subcmd_list[%s] = %s" % (repr(cmd), repr(clist)))
|
||||
else:
|
||||
print("command %s is not documented" % cmd)
|
||||
return
|
||||
else:
|
||||
clist = cmd_list
|
||||
aname = "top level"
|
||||
print("Note: To display a category's commands quote the name e.g. help('HV')")
|
||||
print("List of %s commands:" % aname)
|
||||
for cmd in clist.keys():
|
||||
hinfo = clist[cmd]
|
||||
if isinstance(hinfo, str):
|
||||
msg = hinfo.strip().split("\n", 1)[0]
|
||||
elif isinstance(hinfo, int):
|
||||
msg = "%s category - %d subcommands" % (cmd, hinfo)
|
||||
else:
|
||||
print("%s ?" % cmd)
|
||||
continue
|
||||
if len(cmd) <= 10:
|
||||
print("%-10s : %s" % (cmd, msg))
|
||||
else:
|
||||
print("%s:\n %s" % (cmd, msg))
|
||||
|
||||
|
||||
# commands is a dictionary for constructing the
|
||||
# InteractiveConsole with. It adds in the callables
|
||||
# in proxy utils iface and sysreg into commands
|
||||
def run_ishell(commands, msg=""):
|
||||
saved_display = sys.displayhook
|
||||
try:
|
||||
|
||||
def display(val):
|
||||
if isinstance(val, int) and not isinstance(val, bool):
|
||||
builtins._ = val
|
||||
print(hex(val))
|
||||
elif callable(val):
|
||||
val()
|
||||
else:
|
||||
saved_display(val)
|
||||
|
||||
sys.displayhook = display
|
||||
|
||||
# convenience
|
||||
commands["h"] = hex
|
||||
commands["sysreg"] = sysreg
|
||||
|
||||
if "proxy" in commands and "p" not in commands:
|
||||
commands["p"] = commands["proxy"]
|
||||
if "utils" in commands and "u" not in commands:
|
||||
commands["u"] = commands["utils"]
|
||||
|
||||
for obj_name in ("iface", "p", "u"):
|
||||
obj = commands.get(obj_name)
|
||||
obj_class = type(obj)
|
||||
if obj is None:
|
||||
continue
|
||||
|
||||
for attr in dir(obj_class):
|
||||
if attr in commands or attr.startswith("_"):
|
||||
continue
|
||||
|
||||
member = getattr(obj_class, attr)
|
||||
if callable(member) and not isinstance(member, property):
|
||||
cmd = getattr(obj, attr)
|
||||
commands[attr] = cmd
|
||||
|
||||
for attr in dir(sysreg):
|
||||
commands[attr] = getattr(sysreg, attr)
|
||||
|
||||
commands["help"] = help_cmd
|
||||
commands["debug"] = debug_cmd
|
||||
for obj_name in commands.keys():
|
||||
obj = commands.get(obj_name)
|
||||
if obj is None or obj_name.startswith("_"):
|
||||
continue
|
||||
if callable(obj) and not isinstance(obj, property):
|
||||
try:
|
||||
desc = obj_name + str(signature(obj))
|
||||
except:
|
||||
continue
|
||||
qn = obj.__qualname__
|
||||
if qn.find(".") > 0:
|
||||
a = qn.split(".")
|
||||
if a[0] not in subcmd_list:
|
||||
subcmd_list[a[0]] = {}
|
||||
if a[0] not in cmd_list:
|
||||
cmd_list[a[0]] = 1
|
||||
else:
|
||||
cmd_list[a[0]] += 1
|
||||
clist = subcmd_list[a[0]]
|
||||
else:
|
||||
clist = None
|
||||
if commands[obj_name].__doc__:
|
||||
desc += " - " + commands[obj_name].__doc__
|
||||
cmd_list[obj_name] = desc
|
||||
if isinstance(clist, dict):
|
||||
clist[obj_name] = desc
|
||||
|
||||
embed(config=c, extensions=["m1n1.ishell_ext"], header=msg, user_ns=commands)
|
||||
finally:
|
||||
sys.displayhook = saved_display
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from .setup import *
|
||||
|
||||
commands = dict(__main__.__dict__)
|
||||
|
||||
run_ishell(commands, msg="Have fun!")
|
24
proxyclient/m1n1/ishell_ext.py
Normal file
24
proxyclient/m1n1/ishell_ext.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
# Extension for ipython to handle monitor polling
|
||||
# and simd context after each executed line
|
||||
|
||||
|
||||
class PostExecuteWatcher(object):
|
||||
def __init__(self, ip):
|
||||
self.shell = ip
|
||||
|
||||
def post_execute(self):
|
||||
mon = self.shell.user_ns.get("mon", None)
|
||||
if mon != None:
|
||||
try:
|
||||
mon.poll()
|
||||
except Exception as e:
|
||||
print(f"mon.poll() failed: {e!r}")
|
||||
u = self.shell.user_ns.get("u", None)
|
||||
if u != None:
|
||||
u.push_simd()
|
||||
|
||||
|
||||
def load_ipython_extension(ip):
|
||||
pew = PostExecuteWatcher(ip)
|
||||
ip.events.register("post_execute", pew.post_execute)
|
11
proxyclient/tools/ishell.py
Executable file
11
proxyclient/tools/ishell.py
Executable file
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: MIT
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
sys.path.append(str(pathlib.Path(__file__).resolve().parents[1]))
|
||||
|
||||
from m1n1.setup import *
|
||||
from m1n1.ishell import run_ishell
|
||||
|
||||
run_ishell(globals(), msg="Have fun!")
|
Loading…
Reference in a new issue