mirror of
https://github.com/microsoft/autogen.git
synced 2025-07-08 09:31:51 +00:00
99 lines
3.7 KiB
Python
99 lines
3.7 KiB
Python
# Modified from: https://github.com/kai687/sphinxawesome-codelinter
|
|
|
|
import tempfile
|
|
from typing import AbstractSet, Any, Iterable
|
|
|
|
from docutils import nodes
|
|
from sphinx.application import Sphinx
|
|
from sphinx.builders import Builder
|
|
from sphinx.util import logging
|
|
from sphinx.util.console import darkgreen, darkred, red, teal, faint # type: ignore[attr-defined]
|
|
|
|
from pygments import highlight # type: ignore
|
|
from pygments.lexers import PythonLexer
|
|
from pygments.formatters import TerminalFormatter
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
__version__ = "0.1.0"
|
|
|
|
|
|
class CodeLinter(Builder):
|
|
"""Iterate over all ``literal_block`` nodes.
|
|
|
|
pipe them into any command line tool that
|
|
can read from standard input.
|
|
"""
|
|
|
|
name = "code_lint"
|
|
allow_parallel = True
|
|
|
|
def init(self) -> None:
|
|
"""Initialize."""
|
|
self._had_errors = False
|
|
pass
|
|
|
|
def get_outdated_docs(self) -> str | Iterable[str]:
|
|
"""Check for outdated files.
|
|
|
|
Return an iterable of outdated output files, or a string describing what an
|
|
update will build.
|
|
"""
|
|
return self.env.found_docs
|
|
|
|
def get_target_uri(self, docname: str, typ: str | None = None) -> str:
|
|
"""Return Target URI for a document name."""
|
|
return ""
|
|
|
|
def prepare_writing(self, docnames: AbstractSet[str]) -> None:
|
|
"""Run these steps before documents are written."""
|
|
return
|
|
|
|
def write_doc(self, docname: str, doctree: nodes.Node) -> None:
|
|
path_prefix: str = self.app.config.code_lint_path_prefix
|
|
supported_languages = set(["python", "default"])
|
|
|
|
if not docname.startswith(path_prefix):
|
|
return
|
|
|
|
for code in doctree.findall(nodes.literal_block):
|
|
if code["language"] in supported_languages:
|
|
logger.info("Checking a code block in %s...", docname, nonl=True)
|
|
if "ignore" in code["classes"]:
|
|
logger.info(" " + darkgreen("OK[ignored]"))
|
|
continue
|
|
|
|
# Create a temporary file to store the code block
|
|
with tempfile.NamedTemporaryFile(mode="wb", suffix=".py") as temp_file:
|
|
temp_file.write(code.astext().encode())
|
|
temp_file.flush()
|
|
|
|
# Run pyright on the temporary file using subprocess.run
|
|
import subprocess
|
|
|
|
result = subprocess.run(["pyright", temp_file.name], capture_output=True, text=True)
|
|
if result.returncode != 0:
|
|
logger.info(" " + darkred("FAIL"))
|
|
highlighted_code = highlight(code.astext(), PythonLexer(), TerminalFormatter()) # type: ignore
|
|
output = f"{faint('========================================================')}\n{red('Error')}: Pyright found issues in {teal(docname)}:\n{faint('--------------------------------------------------------')}\n{highlighted_code}\n{faint('--------------------------------------------------------')}\n\n{teal('pyright output:')}\n{red(result.stdout)}{faint('========================================================')}\n"
|
|
logger.info(output)
|
|
self._had_errors = True
|
|
else:
|
|
logger.info(" " + darkgreen("OK"))
|
|
|
|
def finish(self) -> None:
|
|
"""Finish the build process."""
|
|
if self._had_errors:
|
|
raise RuntimeError("Code linting failed - see earlier output")
|
|
|
|
|
|
def setup(app: Sphinx) -> dict[str, Any]:
|
|
app.add_builder(CodeLinter)
|
|
app.add_config_value("code_lint_path_prefix", "", "env")
|
|
|
|
return {
|
|
"version": __version__,
|
|
"parallel_read_safe": True,
|
|
"parallel_write_safe": True,
|
|
}
|