src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Logging/LoggingChecker.py

branch
eric7
changeset 10362
cfa7034cccf6
child 10363
6244c89dbc3f
equal deleted inserted replaced
10361:e6ff9a4f6ee5 10362:cfa7034cccf6
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a checker for logging related issues.
8 """
9
10 import copy
11
12
13 class LoggingChecker:
14 """
15 Class implementing a checker for logging related issues.
16 """
17
18 Codes = [
19 ## Logging format
20 "L101",
21 "L102",
22 "L103",
23 "L104",
24 "L110",
25 ]
26
27 def __init__(self, source, filename, tree, select, ignore, expected, repeat, args):
28 """
29 Constructor
30
31 @param source source code to be checked
32 @type list of str
33 @param filename name of the source file
34 @type str
35 @param tree AST tree of the source code
36 @type ast.Module
37 @param select list of selected codes
38 @type list of str
39 @param ignore list of codes to be ignored
40 @type list of str
41 @param expected list of expected codes
42 @type list of str
43 @param repeat flag indicating to report each occurrence of a code
44 @type bool
45 @param args dictionary of arguments for the various checks
46 @type dict
47 """
48 self.__select = tuple(select)
49 self.__ignore = ("",) if select else tuple(ignore)
50 self.__expected = expected[:]
51 self.__repeat = repeat
52 self.__filename = filename
53 self.__source = source[:]
54 self.__tree = copy.deepcopy(tree)
55 self.__args = args
56
57 # statistics counters
58 self.counters = {}
59
60 # collection of detected errors
61 self.errors = []
62
63 checkersWithCodes = [
64 (self.__checkLoggingFormat, ("L101", "L102", "L103", "L104", "L110")),
65 ]
66
67 self.__checkers = []
68 for checker, codes in checkersWithCodes:
69 if any(not (code and self.__ignoreCode(code)) for code in codes):
70 self.__checkers.append(checker)
71
72 def __ignoreCode(self, code):
73 """
74 Private method to check if the message code should be ignored.
75
76 @param code message code to check for
77 @type str
78 @return flag indicating to ignore the given code
79 @rtype bool
80 """
81 return code.startswith(self.__ignore) and not code.startswith(self.__select)
82
83 def __error(self, lineNumber, offset, code, *args):
84 """
85 Private method to record an issue.
86
87 @param lineNumber line number of the issue
88 @type int
89 @param offset position within line of the issue
90 @type int
91 @param code message code
92 @type str
93 @param args arguments for the message
94 @type list
95 """
96 if self.__ignoreCode(code):
97 return
98
99 if code in self.counters:
100 self.counters[code] += 1
101 else:
102 self.counters[code] = 1
103
104 # Don't care about expected codes
105 if code in self.__expected:
106 return
107
108 if code and (self.counters[code] == 1 or self.__repeat):
109 # record the issue with one based line number
110 self.errors.append(
111 {
112 "file": self.__filename,
113 "line": lineNumber + 1,
114 "offset": offset,
115 "code": code,
116 "args": args,
117 }
118 )
119
120 def run(self):
121 """
122 Public method to check the given source against miscellaneous
123 conditions.
124 """
125 if not self.__filename:
126 # don't do anything, if essential data is missing
127 return
128
129 if not self.__checkers:
130 # don't do anything, if no codes were selected
131 return
132
133 for check in self.__checkers:
134 check()
135
136 def __checkLoggingFormat(self):
137 """
138 Private method to check logging statements.
139 """
140 from .LoggingFormatVisitor import LoggingFormatVisitor
141
142 visitor = LoggingFormatVisitor()
143 visitor.visit(self.__tree)
144 for node, reason in visitor.violations:
145 self.__error(node.lineno - 1, node.col_offset, reason)

eric ide

mercurial