| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- from typing import List
- from openhands.core.logger import openhands_logger as logger
- from openhands.linter.base import BaseLinter, LintResult
- from openhands.linter.utils import run_cmd
- def python_compile_lint(fname: str) -> list[LintResult]:
- try:
- with open(fname, 'r') as f:
- code = f.read()
- compile(code, fname, 'exec') # USE TRACEBACK BELOW HERE
- return []
- except SyntaxError as err:
- err_lineno = getattr(err, 'end_lineno', err.lineno)
- err_offset = getattr(err, 'end_offset', err.offset)
- if err_offset and err_offset < 0:
- err_offset = err.offset
- return [
- LintResult(
- file=fname, line=err_lineno, column=err_offset or 1, message=err.msg
- )
- ]
- def flake_lint(filepath: str) -> list[LintResult]:
- fatal = 'F821,F822,F831,E112,E113,E999,E902'
- flake8_cmd = f'flake8 --select={fatal} --isolated {filepath}'
- try:
- cmd_outputs = run_cmd(flake8_cmd)
- except FileNotFoundError:
- return []
- results: list[LintResult] = []
- if not cmd_outputs:
- return results
- for line in cmd_outputs.splitlines():
- parts = line.split(':')
- if len(parts) >= 4:
- _msg = parts[3].strip()
- if len(parts) > 4:
- _msg += ': ' + parts[4].strip()
- try:
- line_num = int(parts[1])
- except ValueError as e:
- logger.warning(
- f'Error parsing flake8 output for line: {e}. Parsed parts: {parts}. Skipping...'
- )
- continue
- try:
- column_num = int(parts[2])
- except ValueError as e:
- column_num = 1
- _msg = (
- parts[2].strip() + ' ' + _msg
- ) # add the unparsed message to the original message
- logger.warning(
- f'Error parsing flake8 output for column: {e}. Parsed parts: {parts}. Using default column 1.'
- )
- results.append(
- LintResult(
- file=filepath,
- line=line_num,
- column=column_num,
- message=_msg,
- )
- )
- return results
- class PythonLinter(BaseLinter):
- @property
- def supported_extensions(self) -> List[str]:
- return ['.py']
- def lint(self, file_path: str) -> list[LintResult]:
- error = flake_lint(file_path)
- if not error:
- error = python_compile_lint(file_path)
- return error
- def compile_lint(self, file_path: str, code: str) -> List[LintResult]:
- try:
- compile(code, file_path, 'exec')
- return []
- except SyntaxError as e:
- return [
- LintResult(
- file=file_path,
- line=e.lineno,
- column=e.offset,
- message=str(e),
- rule='SyntaxError',
- )
- ]
|