From a611c053f3a474a3604ae551bb27c061cbc43dad Mon Sep 17 00:00:00 2001 From: Eric Gallager Date: Wed, 25 Oct 2023 19:57:33 -0400 Subject: [PATCH] some python fixups --- .github/workflows/codeql.yml | 3 + .github/workflows/emacs-apple.yml | 2 +- etc/.gitignore | 2 + etc/emacs.py | 132 ++++++++++++++++-------------- etc/emacs.py_2to3.diff | 96 ++++++++++++++++++++++ etc/emacs_lldb.py | 94 +++++++++++++-------- 6 files changed, 233 insertions(+), 96 deletions(-) create mode 100644 etc/emacs.py_2to3.diff diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 34e574cb7296..0a55362ae9dc 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -105,6 +105,9 @@ jobs: fi; \ fi + - name: Syntax check + if: matrix.language == 'python' + run: echo "Checking syntax... $(python -m py_compile etc/emacs.py)" - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 with: diff --git a/.github/workflows/emacs-apple.yml b/.github/workflows/emacs-apple.yml index 552f4eaa5697..2d99473ca278 100644 --- a/.github/workflows/emacs-apple.yml +++ b/.github/workflows/emacs-apple.yml @@ -11,7 +11,7 @@ jobs: - name: checkout uses: actions/checkout@v4.1.1 - run: brew update - - run: brew install make automake gettext texinfo gawk gdb coreutils gnu-sed gnu-which llvm clang-build-analyzer clang-format + - run: brew install make automake gettext texinfo gawk gdb coreutils gnu-sed gnu-which clang-build-analyzer clang-format env: HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1 HOMEBREW_VERBOSE_USING_DOTS: 1 diff --git a/etc/.gitignore b/etc/.gitignore index 827562e08500..0f69b4116738 100644 --- a/etc/.gitignore +++ b/etc/.gitignore @@ -6,3 +6,5 @@ images/icons/* *.log refcards/emacsver.tex refcards/*.pdf +*.pyc +__pycache__/* diff --git a/etc/emacs.py b/etc/emacs.py index 3f34c3a22691..cb16c23f7f67 100644 --- a/etc/emacs.py +++ b/etc/emacs.py @@ -1,5 +1,6 @@ """Definitions used by commands sent to inferior Python in python.el.""" +# -*- coding: utf-8; mode: python; indent-tabs-mode: nil; -*- # Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. # Author: Dave Love @@ -21,92 +22,103 @@ # Boston, MA 02110-1301, USA. import os, sys, traceback, inspect, rlcompleter, __main__ +import importlib __all__ = ["eexecfile", "args", "complete", "ehelp", "eimport"] -def eexecfile (file): + +def eexecfile(file): """Execute FILE and then remove it. If we get an exception, print a traceback with the top frame (oursleves) excluded.""" - try: - try: execfile (file, globals (), globals ()) - except: - (type, value, tb) = sys.exc_info () - # Lose the stack frame for this location. - tb = tb.tb_next - if tb is None: # print_exception won't do it - print "Traceback (most recent call last):" - traceback.print_exception (type, value, tb) + try: + exec(compile(open(file, "rb").read(), file, "exec"), globals(), globals()) + except: + (type, value, tb) = sys.exc_info() + # Lose the stack frame for this location. + tb = tb.tb_next + if tb is None: # print_exception fails to do it + print("Traceback (most recent call last):") + traceback.print_exception(type, value, tb) finally: - os.remove (file) + os.remove(file) + -def eargs (name): +def eargs(name): "Get arglist of NAME for Eldoc &c." try: - parts = name.split ('.') - if len (parts) > 1: - exec 'import ' + parts[0] # might fail - func = eval (name) - if inspect.isbuiltin (func): - doc = func.__doc__ - if doc.find (' ->') != -1: - print '_emacs_out', doc.split (' ->')[0] - elif doc.find ('\n') != -1: - print '_emacs_out', doc.split ('\n')[0] - return - if inspect.ismethod (func): - func = func.im_func - if not inspect.isfunction (func): + parts = name.split(".") + if len(parts) > 1: + exec("import " + parts[0]) # might fail + func = eval(name) + if inspect.isbuiltin(func): + doc = func.__doc__ + if doc.find(" ->") != -1: + print("_emacs_out", doc.split(" ->")[0]) + elif doc.find("\n") != -1: + print("_emacs_out", doc.split("\n")[0]) return - (args, varargs, varkw, defaults) = inspect.getargspec (func) - # No space between name and arglist for consistency with builtins. - print '_emacs_out', \ - func.__name__ + inspect.formatargspec (args, varargs, varkw, - defaults) - except: pass - -def complete (text, namespace = None): + if inspect.ismethod(func): + func = func.__func__ + if not inspect.isfunction(func): + return + (args, varargs, varkw, defaults) = inspect.getargspec(func) + # No space between name and arglist for consistency with builtins. + print( + "_emacs_out", + func.__name__ + inspect.formatargspec(args, varargs, varkw, defaults), + ) + except: + pass + + +def complete(text, namespace=None): """Complete TEXT in NAMESPACE and print a Lisp list of completions. NAMESPACE is currently not used.""" - if namespace is None: namespace = __main__.__dict__ - c = rlcompleter.Completer (namespace) + if namespace is None: + namespace = __main__.__dict__ + c = rlcompleter.Completer(namespace) try: - if '.' in text: - matches = c.attr_matches (text) - else: - matches = c.global_matches (text) - print '_emacs_out (', - for elt in matches: - print '"%s"' % elt, - print ')' + if "." in text: + matches = c.attr_matches(text) + else: + matches = c.global_matches(text) + print("_emacs_out (", end=" ") + for elt in matches: + print('"%s"' % elt, end=" ") + print(")") except: - print '_emacs_out ()' + print("_emacs_out ()") + -def ehelp (name, g, l): +def ehelp(name, g, l): """Get help on string NAME using globals G and locals L. First try to eval name for, e.g. user definitions where we need the object. Otherwise try the string form.""" - try: help (eval (name, g, l)) - except: help (name) + try: + help(eval(name, g, l)) + except: + help(name) -def eimport (mod, dir): + +def eimport(mod, dir): """Import module MOD with directory DIR at the head of the search path. NB doesn't load from DIR if MOD shadows a system module.""" path0 = sys.path[0] sys.path[0] = dir try: - try: - if globals().has_key(mod) and inspect.ismodule (eval (mod)): - reload(eval (mod)) - else: - globals ()[mod] = __import__ (mod) - except: - (type, value, tb) = sys.exc_info () - print "Traceback (most recent call last):" - traceback.print_exception (type, value, tb.tb_next) + if mod in globals() and inspect.ismodule(eval(mod)): + importlib.reload(eval(mod)) + else: + globals()[mod] = __import__(mod) + except: + (type, value, tb) = sys.exc_info() + print("Traceback (most recent call last):") + traceback.print_exception(type, value, tb.tb_next) finally: - sys.path[0] = path0 + sys.path[0] = path0 + -print '_emacs_ok' # ready for input and can call continuation +print("_emacs_ok") # ready for input and can call continuation # arch-tag: d90408f3-90e2-4de4-99c2-6eb9c7b9ca46 diff --git a/etc/emacs.py_2to3.diff b/etc/emacs.py_2to3.diff new file mode 100644 index 000000000000..dc61eaec81ec --- /dev/null +++ b/etc/emacs.py_2to3.diff @@ -0,0 +1,96 @@ +--- emacs.py (original) ++++ emacs.py (refactored) +@@ -22,6 +22,7 @@ + # Boston, MA 02110-1301, USA. + + import os, sys, traceback, inspect, rlcompleter, __main__ ++import importlib + + __all__ = ["eexecfile", "args", "complete", "ehelp", "eimport"] + +@@ -29,13 +30,13 @@ + """Execute FILE and then remove it. + If we get an exception, print a traceback with the top frame + (oursleves) excluded.""" +- try: execfile (file, globals (), globals ()) ++ try: exec(compile(open(file, "rb").read(), file, 'exec'), globals (), globals ()) + except: + (type, value, tb) = sys.exc_info () + # Lose the stack frame for this location. + tb = tb.tb_next + if tb is None: # print_exception fails to do it +- print "Traceback (most recent call last):" ++ print("Traceback (most recent call last):") + traceback.print_exception (type, value, tb) + finally: + os.remove (file) +@@ -45,24 +46,24 @@ + try: + parts = name.split ('.') + if len (parts) > 1: +- exec 'import ' + parts[0] # might fail ++ exec('import ' + parts[0]) # might fail + func = eval (name) + if inspect.isbuiltin (func): + doc = func.__doc__ + if doc.find (' ->') != -1: +- print '_emacs_out', doc.split (' ->')[0] ++ print('_emacs_out', doc.split (' ->')[0]) + elif doc.find ('\n') != -1: +- print '_emacs_out', doc.split ('\n')[0] ++ print('_emacs_out', doc.split ('\n')[0]) + return + if inspect.ismethod (func): +- func = func.im_func ++ func = func.__func__ + if not inspect.isfunction (func): + return + (args, varargs, varkw, defaults) = inspect.getargspec (func) + # No space between name and arglist for consistency with builtins. +- print '_emacs_out', \ ++ print('_emacs_out', \ + func.__name__ + inspect.formatargspec (args, varargs, varkw, +- defaults) ++ defaults)) + except: pass + + def complete (text, namespace = None): +@@ -75,12 +76,12 @@ + matches = c.attr_matches (text) + else: + matches = c.global_matches (text) +- print '_emacs_out (', ++ print('_emacs_out (', end=' ') + for elt in matches: +- print '"%s"' % elt, +- print ')' ++ print('"%s"' % elt, end=' ') ++ print(')') + except: +- print '_emacs_out ()' ++ print('_emacs_out ()') + + def ehelp (name, g, l): + """Get help on string NAME using globals G and locals L. +@@ -96,17 +97,17 @@ + sys.path[0] = dir + try: + try: +- if globals().has_key(mod) and inspect.ismodule (eval (mod)): +- reload(eval (mod)) ++ if mod in globals() and inspect.ismodule (eval (mod)): ++ importlib.reload(eval (mod)) + else: + globals ()[mod] = __import__ (mod) + except: + (type, value, tb) = sys.exc_info () +- print "Traceback (most recent call last):" ++ print("Traceback (most recent call last):") + traceback.print_exception (type, value, tb.tb_next) + finally: + sys.path[0] = path0 + +-print '_emacs_ok' # ready for input and can call continuation ++print('_emacs_ok') # ready for input and can call continuation + + # arch-tag: d90408f3-90e2-4de4-99c2-6eb9c7b9ca46 diff --git a/etc/emacs_lldb.py b/etc/emacs_lldb.py index fa8d95d7b5bd..607c97a37111 100644 --- a/etc/emacs_lldb.py +++ b/etc/emacs_lldb.py @@ -25,11 +25,12 @@ import lldb - + ######################################################################## # Utilities ######################################################################## + # Return the name of enumerator ENUM as a string. def enumerator_name(enum): enumerators = enum.GetType().GetEnumMembers() @@ -38,6 +39,7 @@ def enumerator_name(enum): return enum_member.GetName() return None + # A class wrapping an SBValue for a Lisp_Object, providing convenience # functions. class Lisp_Object: @@ -73,7 +75,7 @@ class Lisp_Object: "PVEC_SUB_CHAR_TABLE": "void", "PVEC_RECORD": "struct Lisp_Vector", "PVEC_FONT": "struct font", - "PVEC_NORMAL_VECTOR": "struct Lisp_Vector" + "PVEC_NORMAL_VECTOR": "struct Lisp_Vector", } # Object construction/initialization. @@ -100,9 +102,11 @@ def init_unsigned(self): # the pvec_type enumerator if the object is a vector-like, as a # string. def init_lisp_types(self): - t = self.eval(f"(enum Lisp_Type)" - f"((EMACS_INT) {self.unsigned} " - f"& (1 << GCTYPEBITS) - 1)") + t = self.eval( + f"(enum Lisp_Type)" + f"((EMACS_INT) {self.unsigned} " + f"& (1 << GCTYPEBITS) - 1)" + ) self.lisp_type = enumerator_name(t) if self.lisp_type == "Lisp_Vectorlike": self.pvec_type = "PVEC_NORMAL_VECTOR" @@ -114,16 +118,17 @@ def init_lisp_types(self): typ = self.eval( f"(enum pvec_type) (({size} " f"& More_Lisp_Bits::PVEC_TYPE_MASK) " - f">> More_Lisp_Bits::PSEUDOVECTOR_AREA_BITS)") + f">> More_Lisp_Bits::PSEUDOVECTOR_AREA_BITS)" + ) self.pvec_type = enumerator_name(typ) # Initialize self.untagged according to lisp_type and pvec_type. def init_values(self): if self.lisp_type == "Lisp_Symbol": offset = self.get_lisp_pointer("char").GetValueAsUnsigned() - self.untagged = self.eval(f"(struct Lisp_Symbol *)" - f" ((char *) &lispsym + {offset})", - True) + self.untagged = self.eval( + f"(struct Lisp_Symbol *)" f" ((char *) &lispsym + {offset})", True + ) elif self.lisp_type == "Lisp_String": self.untagged = self.get_lisp_pointer("struct Lisp_String", True) elif self.lisp_type == "Lisp_Vectorlike": @@ -134,8 +139,9 @@ def init_values(self): elif self.lisp_type == "Lisp_Float": self.untagged = self.get_lisp_pointer("struct Lisp_Float", True) elif self.lisp_type in ("Lisp_Int0", "Lisp_Int1"): - self.untagged = self.eval(f"((EMACS_INT) {self.unsigned}) " - f">> (GCTYPEBITS - 1)", True) + self.untagged = self.eval( + f"((EMACS_INT) {self.unsigned}) " f">> (GCTYPEBITS - 1)", True + ) elif self.lisp_type == "Lisp_Type_Unused0": self.untagged = self.unsigned else: @@ -153,9 +159,9 @@ def eval(self, expr, make_var=False): # Return an SBValue for this object denoting a pointer of type # TYP*. def get_lisp_pointer(self, typ, make_var=False): - return self.eval(f"({typ}*) (((EMACS_INT) " - f"{self.unsigned}) & VALMASK)", - make_var) + return self.eval( + f"({typ}*) (((EMACS_INT) " f"{self.unsigned}) & VALMASK)", make_var + ) # If this is a Lisp_String, return an SBValue for its string data. # Return None otherwise. @@ -176,16 +182,18 @@ def get_symbol_name(self): def summary(self): return str(self.untagged) - + ######################################################################## # LLDB Commands ######################################################################## + def xbacktrace(debugger, command, ctx, result, internal_dict): """Print Emacs Lisp backtrace""" frame = ctx.GetFrame() n = frame.EvaluateExpression( - "current_thread->m_specpdl_ptr - current_thread->m_specpdl") + "current_thread->m_specpdl_ptr - current_thread->m_specpdl" + ) for i in reversed(range(0, n.GetValueAsUnsigned())): s = frame.EvaluateExpression(f"current_thread->m_specpdl[{i}]") kind = enumerator_name(s.GetChildMemberWithName("kind")) @@ -199,22 +207,26 @@ def xbacktrace(debugger, command, ctx, result, internal_dict): else: result.AppendMessage(function.lisp_type) + def xdebug_print(debugger, command, result, internal_dict): """Print Lisp_Objects using safe_debug_print()""" debugger.HandleCommand(f"expr safe_debug_print({command})") - + ######################################################################## # Formatters ######################################################################## + def type_summary_Lisp_Object(obj, internal_dict): return Lisp_Object(obj).summary() + class Lisp_Object_Provider: """Synthetic children provider for Lisp_Objects. Supposedly only used by 'frame variable', where -P can be used - to specify a printing depth. """ + to specify a printing depth.""" + def __init__(self, valobj, internal_dict): self.valobj = valobj self.children = {} @@ -255,38 +267,46 @@ def get_child_at_index(self, index): key = list(self.children)[index] return self.children[key] - + ######################################################################## # Initialization ######################################################################## + # Define Python FUNCTION as an LLDB command. -def define_command (debugger, function): +def define_command(debugger, function): lldb_command = function.__name__ python_function = __name__ + "." + function.__name__ interpreter = debugger.GetCommandInterpreter() + def define(overwrite): res = lldb.SBCommandReturnObject() - interpreter.HandleCommand(f"command script add " - f"{overwrite} " - f"--function {python_function} " - f"{lldb_command}", - res) + interpreter.HandleCommand( + f"command script add " + f"{overwrite} " + f"--function {python_function} " + f"{lldb_command}", + res, + ) return res.Succeeded() + if not define("--overwrite"): define("") + # Define Python FUNCTION as an LLDB type summary provider for types # matching REGEX. Type summaries defined here are defined in the # category Emacs, and can be seen with 'type summary list -w Emacs', # and deleted in a similar way. def define_type_summary(debugger, regex, function): python_function = __name__ + "." + function.__name__ - debugger.HandleCommand(f"type summary add --expand " - f"--cascade true " - f"--category Emacs " - f"--python-function {python_function} " - + regex) + debugger.HandleCommand( + f"type summary add --expand " + f"--cascade true " + f"--category Emacs " + f"--python-function {python_function} " + regex + ) + # Define Python class CLS as a children provider for the types # matching REFEXP. Providers are defined in the category Emacs, and @@ -294,15 +314,18 @@ def define_type_summary(debugger, regex, function): # similar way. def define_type_synthetic(debugger, regex, cls): python_class = __name__ + "." + cls.__name__ - debugger.HandleCommand(f"type synthetic add " - f"--category Emacs " - f"--python-class {python_class} " - + regex) + debugger.HandleCommand( + f"type synthetic add " + f"--category Emacs " + f"--python-class {python_class} " + regex + ) + # Enable a given category of type summary providers. def enable_type_category(debugger, category): debugger.HandleCommand(f"type category enable {category}") + # This function is called by LLDB to initialize the module. def __lldb_init_module(debugger, internal_dict): define_command(debugger, xbacktrace) @@ -310,6 +333,7 @@ def __lldb_init_module(debugger, internal_dict): define_type_summary(debugger, "Lisp_Object", type_summary_Lisp_Object) define_type_synthetic(debugger, "Lisp_Object", Lisp_Object_Provider) enable_type_category(debugger, "Emacs") - print('Emacs debugging support has been installed.') + print("Emacs debugging support has been installed.") + # end.