interfaces.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  2. # For details: https://github.com/pylint-dev/pylint/blob/main/LICENSE
  3. # Copyright (c) https://github.com/pylint-dev/pylint/blob/main/CONTRIBUTORS.txt
  4. """Interfaces for Pylint objects."""
  5. from __future__ import annotations
  6. import warnings
  7. from tokenize import TokenInfo
  8. from typing import TYPE_CHECKING, NamedTuple
  9. from astroid import nodes
  10. if TYPE_CHECKING:
  11. from pylint.checkers import BaseChecker
  12. from pylint.message import Message
  13. from pylint.reporters.ureports.nodes import Section
  14. __all__ = (
  15. "IRawChecker",
  16. "IAstroidChecker",
  17. "ITokenChecker",
  18. "IReporter",
  19. "IChecker",
  20. "HIGH",
  21. "CONTROL_FLOW",
  22. "INFERENCE",
  23. "INFERENCE_FAILURE",
  24. "UNDEFINED",
  25. "CONFIDENCE_LEVELS",
  26. "CONFIDENCE_LEVEL_NAMES",
  27. )
  28. class Confidence(NamedTuple):
  29. name: str
  30. description: str
  31. # Warning Certainties
  32. HIGH = Confidence("HIGH", "Warning that is not based on inference result.")
  33. CONTROL_FLOW = Confidence(
  34. "CONTROL_FLOW", "Warning based on assumptions about control flow."
  35. )
  36. INFERENCE = Confidence("INFERENCE", "Warning based on inference result.")
  37. INFERENCE_FAILURE = Confidence(
  38. "INFERENCE_FAILURE", "Warning based on inference with failures."
  39. )
  40. UNDEFINED = Confidence("UNDEFINED", "Warning without any associated confidence level.")
  41. CONFIDENCE_LEVELS = [HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE, UNDEFINED]
  42. CONFIDENCE_LEVEL_NAMES = [i.name for i in CONFIDENCE_LEVELS]
  43. class Interface:
  44. """Base class for interfaces."""
  45. def __init__(self) -> None:
  46. warnings.warn(
  47. "Interface and all of its subclasses have been deprecated "
  48. "and will be removed in pylint 3.0.",
  49. DeprecationWarning,
  50. stacklevel=2,
  51. )
  52. @classmethod
  53. def is_implemented_by(
  54. cls: type[Interface] | tuple[type[Interface], ...], instance: BaseChecker
  55. ) -> bool:
  56. with warnings.catch_warnings():
  57. warnings.filterwarnings("ignore", category=DeprecationWarning)
  58. return implements(instance, cls)
  59. def implements(
  60. obj: BaseChecker,
  61. interface: type[Interface] | tuple[type[Interface], ...],
  62. ) -> bool:
  63. """Does the given object (maybe an instance or class) implement the interface."""
  64. # TODO: 3.0: Remove deprecated function
  65. warnings.warn(
  66. "implements has been deprecated in favour of using basic "
  67. "inheritance patterns without using __implements__.",
  68. DeprecationWarning,
  69. stacklevel=2,
  70. )
  71. implements_ = getattr(obj, "__implements__", ())
  72. if not isinstance(implements_, (list, tuple)):
  73. implements_ = (implements_,)
  74. return any(issubclass(i, interface) for i in implements_)
  75. class IChecker(Interface):
  76. """Base interface, to be used only for sub interfaces definition."""
  77. def open(self) -> None:
  78. """Called before visiting project (i.e. set of modules)."""
  79. def close(self) -> None:
  80. """Called after visiting project (i.e. set of modules)."""
  81. class IRawChecker(IChecker):
  82. """Interface for checker which need to parse the raw file."""
  83. def process_module(self, node: nodes.Module) -> None:
  84. """Process a module.
  85. The module's content is accessible via ``astroid.stream``
  86. """
  87. class ITokenChecker(IChecker):
  88. """Interface for checkers that need access to the token list."""
  89. def process_tokens(self, tokens: list[TokenInfo]) -> None:
  90. """Process a module.
  91. Tokens is a list of all source code tokens in the file.
  92. """
  93. class IAstroidChecker(IChecker):
  94. """Interface for checker which prefers receive events according to
  95. statement type.
  96. """
  97. class IReporter(Interface):
  98. """Reporter collect messages and display results encapsulated in a layout."""
  99. def handle_message(self, msg: Message) -> None:
  100. """Handle the given message object."""
  101. def display_reports(self, layout: Section) -> None:
  102. """Display results encapsulated in the layout tree."""