| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 |
- # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
- # For details: https://github.com/pylint-dev/astroid/blob/main/LICENSE
- # Copyright (c) https://github.com/pylint-dev/astroid/blob/main/CONTRIBUTORS.txt
- """Astroid hooks for understanding statistics library module.
- Provides inference improvements for statistics module functions that have
- complex runtime behavior difficult to analyze statically.
- """
- from __future__ import annotations
- from collections.abc import Iterator
- from typing import TYPE_CHECKING
- from astroid import nodes
- from astroid.context import InferenceContext
- from astroid.inference_tip import inference_tip
- from astroid.manager import AstroidManager
- from astroid.util import Uninferable
- if TYPE_CHECKING:
- from astroid.typing import InferenceResult
- def _looks_like_statistics_quantiles(node: nodes.Call) -> bool:
- """Check if this is a call to statistics.quantiles."""
- match node.func:
- case nodes.Attribute(expr=nodes.Name(name="statistics"), attrname="quantiles"):
- # Case 1: statistics.quantiles(...)
- return True
- case nodes.Name(name="quantiles"):
- # Case 2: from statistics import quantiles; quantiles(...)
- # Check if quantiles was imported from statistics
- try:
- frame = node.frame()
- if "quantiles" in frame.locals:
- # Look for import from statistics
- for stmt in frame.body:
- if (
- isinstance(stmt, nodes.ImportFrom)
- and stmt.modname == "statistics"
- and any(name[0] == "quantiles" for name in stmt.names or [])
- ):
- return True
- except (AttributeError, TypeError):
- # If we can't determine the import context, be conservative
- pass
- return False
- def infer_statistics_quantiles(
- node: nodes.Call, context: InferenceContext | None = None
- ) -> Iterator[InferenceResult]:
- """Infer the result of statistics.quantiles() calls.
- Returns Uninferable because quantiles() has complex runtime behavior
- that cannot be statically analyzed, preventing false positives in
- pylint's unbalanced-tuple-unpacking checker.
- statistics.quantiles() returns a list with (n-1) elements, but static
- analysis sees only the empty list initializations in the function body.
- """
- yield Uninferable
- def register(manager: AstroidManager) -> None:
- """Register statistics-specific inference improvements."""
- manager.register_transform(
- nodes.Call,
- inference_tip(infer_statistics_quantiles),
- _looks_like_statistics_quantiles,
- )
|