Implementation:Mlflow Mlflow Clint Linter Engine
| Knowledge Sources | |
|---|---|
| Domains | CodeQuality, Linting |
| Last Updated | 2026-02-13 20:00 GMT |
Overview
Core linting engine for the Clint custom linter that applies MLflow-specific rules to Python files, Jupyter notebooks, RST, and Markdown documents via AST-based analysis.
Description
The Linter class extends ast.NodeVisitor to walk the syntax tree of Python source code, checking imports, function definitions, class definitions, calls, assignments, and type annotations against the full set of configured Clint rules. The linter supports:
- Inline disable comments: Users can suppress specific rules with
# clint: disable=rule-namecomments, parsed by parse_disable_comments. - Per-file ignores: Configured in pyproject.toml to skip certain rules for specific file patterns.
- Notebook cell linting: The _lint_cell function handles Jupyter notebook cells, including checking for forbidden trace UI iframe content in cell outputs.
- Docstring code block validation: The _iter_code_blocks and _iter_md_code_blocks functions extract Python code examples from RST and Markdown docstrings, then lint them with visit_example.
- Type annotation checking: The TypeAnnotationVisitor validates type annotations for correctness and parameterization.
- Example code validation: The ExampleVisitor checks MLflow API calls in code examples against a symbol index for unknown functions and arguments.
Key supporting classes include Position and Range for source code location tracking, Violation for representing rule violations with ruff-compatible formatting, and CodeBlock for extracted code examples.
The entry point lint_file dispatches based on file extension: .ipynb files are linted cell-by-cell, .rst/.md/.mdx files have their code blocks extracted and linted, and regular Python files go through full AST analysis.
Usage
This module is the heart of the Clint linter and is invoked when running uv run clint . on the MLflow codebase. It is not typically imported directly but is used internally by the Clint CLI.
Code Reference
Source Location
- Repository: Mlflow_Mlflow
- File: dev/clint/src/clint/linter.py
- Lines: 1-1049
Signature
class Linter(ast.NodeVisitor):
def __init__(
self,
*,
path: Path,
config: Config,
disable_comments: list[DisableComment],
index: SymbolIndex,
cell: int | None = None,
offset: Position | None = None,
) -> None: ...
def _check(self, range: Range, rule: rules.Rule) -> None: ...
def visit_FunctionDef(self, node: ast.FunctionDef) -> None: ...
def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None: ...
def visit_ClassDef(self, node: ast.ClassDef) -> None: ...
def visit_Import(self, node: ast.Import) -> None: ...
def visit_ImportFrom(self, node: ast.ImportFrom) -> None: ...
def visit_Call(self, node: ast.Call) -> None: ...
def post_visit(self) -> None: ...
@classmethod
def visit_example(
cls, path: Path, config: Config, example: CodeBlock, index: SymbolIndex
) -> list[Violation]: ...
def lint_file(path: Path, code: str, config: Config, index_path: Path) -> list[Violation]: ...
def parse_disable_comments(code: str) -> list[DisableComment]: ...
Import
from clint.linter import Linter, lint_file, Violation
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| path | Path | Yes | Relative path to the file being linted |
| code | str | Yes | Source code content of the file |
| config | Config | Yes | Linter configuration from pyproject.toml |
| index_path | Path | Yes | Path to the symbol index file for resolving function signatures |
Outputs
| Name | Type | Description |
|---|---|---|
| violations | list[Violation] | List of rule violations found in the file, each containing the rule, path, range, and optional cell index |
Usage Examples
Basic Usage
# Run the Clint linter on the entire codebase
uv run clint .
# Run on specific files
uv run clint mlflow/tracking/client.py
Programmatic Usage
from pathlib import Path
from clint.linter import lint_file
from clint.config import Config
config = Config.load()
violations = lint_file(
path=Path("mlflow/tracking/client.py"),
code=Path("mlflow/tracking/client.py").read_text(),
config=config,
index_path=Path("dev/clint/index.json"),
)
for v in violations:
print(v)