Refactored linter to support linting Python code with py_compile.

This commit is contained in:
Paul Gauthier 2024-05-18 17:38:25 -07:00
parent b26969ea90
commit 30c9c4c319

View file

@ -1,9 +1,13 @@
import os import os
import traceback
import subprocess import subprocess
import sys import sys
import warnings import warnings
import py_compile
from pathlib import Path from pathlib import Path
from aider.dump import dump
from grep_ast import TreeContext, filename_to_lang from grep_ast import TreeContext, filename_to_lang
# tree_sitter is throwing a FutureWarning # tree_sitter is throwing a FutureWarning
@ -20,7 +24,7 @@ class Linter:
py_cmd = f"flake8 --select={fatal} --show-source" # noqa: F841 py_cmd = f"flake8 --select={fatal} --show-source" # noqa: F841
self.languages = dict( self.languages = dict(
# python=py_cmd, python=self.py_lint,
) )
def set_linter(self, lang, cmd): def set_linter(self, lang, cmd):
@ -47,16 +51,43 @@ class Linter:
return return
rel_fname = self.get_rel_fname(fname) rel_fname = self.get_rel_fname(fname)
code = Path(fname).read_text(self.encoding)
cmd = self.languages.get(lang) cmd = self.languages.get(lang)
if callable(cmd):
return cmd(fname, rel_fname, code)
if cmd: if cmd:
return self.run_cmd(cmd, rel_fname) return self.run_cmd(cmd, rel_fname)
# fall back to tree sitter / tree context linter
code = Path(fname).read_text(self.encoding)
return basic_lint(rel_fname, code) return basic_lint(rel_fname, code)
def py_lint(self, fname, rel_fname, code):
res = basic_lint(rel_fname, code)
if res:
return res
return lint_pycompile(fname, code)
def lint_pycompile(fname, code):
try:
#py_compile.compile(fname, doraise=True)
compile(code, fname, 'exec')
return
except Exception as err:
dump(dir(err))
dump(err.text)
res = f"{type(err)}: {err}\n"
line_numbers = list(range(err.lineno - 1, err.end_lineno))
dump(line_numbers)
#last_call_stack = tb[-1] # Get the last call stack
#file_name = last_call_stack.filename
#line_number = last_call_stack.lineno
res += tree_context(fname, code, line_numbers)
return res
def basic_lint(fname, code): def basic_lint(fname, code):
""" """
@ -74,11 +105,14 @@ def basic_lint(fname, code):
if not errors: if not errors:
return return
return tree_context(fname, code, errors)
def tree_context(fname, code, line_nums):
context = TreeContext( context = TreeContext(
fname, fname,
code, code,
color=False, color=False,
line_number=False, line_number=True,
child_context=False, child_context=False,
last_line=False, last_line=False,
margin=0, margin=0,
@ -87,9 +121,11 @@ def basic_lint(fname, code):
# header_max=30, # header_max=30,
show_top_of_file_parent_scope=False, show_top_of_file_parent_scope=False,
) )
context.add_lines_of_interest(errors) line_nums = set(line_nums)
context.add_lines_of_interest(line_nums)
context.add_context() context.add_context()
output = "# Syntax Errors found on the lines marked with █\n\n" s = "s" if len(line_nums) > 1 else ""
output = f"# Fix the syntax error{s} found on the line{s} marked with █.\n\n"
output += fname + ":\n" output += fname + ":\n"
output += context.format() output += context.format()