-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
linting.py
85 lines (67 loc) · 3.08 KB
/
linting.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# SPDX-FileCopyrightText: 2023-present deepset <[email protected]>
#
# SPDX-License-Identifier: Apache-2.0
#
# https://pylint.pycqa.org/en/latest/development_guide/how_tos/custom_checkers.html
from typing import TYPE_CHECKING, Optional, List, Any
from astroid import nodes
from pylint.checkers import BaseChecker
if TYPE_CHECKING:
from pylint.lint import PyLinter
class DirectLoggingChecker(BaseChecker):
name = "no-direct-logging"
msgs = {
"W9001": (
"Use a logger object instead of a direct logging function like 'logging.%s()'",
"no-direct-logging",
"Do not use direct calls to logging functions like logging.info(), "
"rather create a logger object with getLogger and use it instead. "
"See https://github.com/deepset-ai/haystack/issues/4202.",
)
}
def __init__(self, linter: Optional["PyLinter"] = None) -> None:
super().__init__(linter)
self._function_stack: List[Any] = []
def visit_functiondef(self, node: nodes.FunctionDef) -> None:
self._function_stack.append([])
def leave_functiondef(self, node: nodes.FunctionDef) -> None:
self._function_stack.pop()
def visit_call(self, node: nodes.Call) -> None:
if (
isinstance(node.func, nodes.Attribute)
and isinstance(node.func.expr, nodes.Name)
and node.func.expr.name == "logging"
and node.func.attrname in ["debug", "info", "warning", "error", "critical", "exception"]
):
self.add_message("no-direct-logging", args=node.func.attrname, node=node)
class NoLoggingConfigurationChecker(BaseChecker):
name = "no-logging-basicconfig"
msgs = {
"W9002": (
"Do not use 'logging.basicConfig' in Haystack code: Haystack should not configure any loggers.",
"no-logging-basicconfig",
"Do not configure the logger explicitly, because this would be problematic for users. "
"Always configure the loggers only in scripts that use Haystack, like tutorials, rather than Haystack itself.",
)
}
def __init__(self, linter: Optional["PyLinter"] = None) -> None:
super().__init__(linter)
self._function_stack: List[Any] = []
def visit_functiondef(self, node: nodes.FunctionDef) -> None:
self._function_stack.append([])
def leave_functiondef(self, node: nodes.FunctionDef) -> None:
self._function_stack.pop()
def visit_call(self, node: nodes.Call) -> None:
if (
isinstance(node.func, nodes.Attribute)
and isinstance(node.func.expr, nodes.Name)
and node.func.expr.name == "logging"
and node.func.attrname in ["basicConfig"]
):
self.add_message("no-logging-basicconfig", node=node)
def register(linter: "PyLinter") -> None:
"""This required method auto registers the checker during initialization.
:param linter: The linter to register the checker to.
"""
linter.register_checker(DirectLoggingChecker(linter))
linter.register_checker(NoLoggingConfigurationChecker(linter))