--- a/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/PathLib/PathlibChecker.py Thu Feb 27 09:22:15 2025 +0100 +++ b/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/PathLib/PathlibChecker.py Thu Feb 27 14:42:39 2025 +0100 @@ -12,32 +12,15 @@ ## adapted from: flake8-use-pathlib v0.3.0 ## ## ## ## Original: Copyright (c) 2021 Rodolphe Pelloux-Prayer ## -## ## -## License: ## -## Permission is hereby granted, free of charge, to any person obtaining a copy ## -## of this software and associated documentation files (the "Software"), to deal ## -## in the Software without restriction, including without limitation the rights ## -## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ## -## copies of the Software, and to permit persons to whom the Software is ## -## furnished to do so, subject to the following conditions: ## -## ## -## The above copyright notice and this permission notice shall be included in all ## -## copies or substantial portions of the Software. ## -## ## -## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ## -## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ## -## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ## -## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ## -## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ## -## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ## ##################################################################################### import ast import contextlib -import copy + +from CodeStyleTopicChecker import CodeStyleTopicChecker -class PathlibChecker: +class PathlibChecker(CodeStyleTopicChecker): """ Class implementing a checker for functions that can be replaced by use of the pathlib module. @@ -78,6 +61,7 @@ ## Replacements for py.path.local "P-401", ] + Category = "P" # map functions to be replaced to error codes Function2Code = { @@ -131,87 +115,62 @@ @param repeat flag indicating to report each occurrence of a code @type bool """ - self.__select = tuple(selected) - self.__ignore = tuple(ignored) - self.__expected = expected[:] - self.__repeat = repeat - self.__filename = filename - self.__source = source[:] - self.__tree = copy.deepcopy(tree) - - # statistics counters - self.counters = {} - - # collection of detected errors - self.errors = [] - - self.__checkCodes = (code for code in self.Codes if not self.__ignoreCode(code)) - - def __ignoreCode(self, code): - """ - Private method to check if the message code should be ignored. - - @param code message code to check for - @type str - @return flag indicating to ignore the given code - @rtype bool - """ - return code in self.__ignore or ( - code.startswith(self.__ignore) and not code.startswith(self.__select) + super().__init__( + PathlibChecker.Category, + source, + filename, + tree, + selected, + ignored, + expected, + repeat, + [], ) - def __error(self, lineNumber, offset, code, *args): - """ - Private method to record an issue. - - @param lineNumber line number of the issue - @type int - @param offset position within line of the issue - @type int - @param code message code - @type str - @param args arguments for the message - @type list - """ - if self.__ignoreCode(code): - return - - if code in self.counters: - self.counters[code] += 1 - else: - self.counters[code] = 1 - - # Don't care about expected codes - if code in self.__expected: - return + checkersWithCodes = [ + ( + self.__checkPathlibReplacement, + ( + "P-101", + "P-102", + "P-103", + "P-104", + "P-105", + "P-106", + "P-107", + "P-108", + "P-109", + "P-110", + "P-111", + "P-112", + "P-113", + "P-114", + "P-201", + "P-202", + "P-203", + "P-204", + "P-205", + "P-206", + "P-207", + "P-208", + "P-209", + "P-210", + "P-211", + "P-212", + "P-213", + "P-301", + "P-401", + ), + ), + ] + self._initializeCheckers(checkersWithCodes) - if code and (self.counters[code] == 1 or self.__repeat): - # record the issue with one based line number - self.errors.append( - { - "file": self.__filename, - "line": lineNumber + 1, - "offset": offset, - "code": code, - "args": args, - } - ) - - def run(self): + def __checkPathlibReplacement(self): """ - Public method to check the given source against functions - to be replaced by 'pathlib' equivalents. + Private method to check for pathlib replacements. """ - if not self.__filename: - # don't do anything, if essential data is missing - return - - if not self.__checkCodes: - # don't do anything, if no codes were selected - return - visitor = PathlibVisitor(self.__checkForReplacement) - visitor.visit(self.__tree) + visitor.visit(self.tree) def __checkForReplacement(self, node, name): """ @@ -225,7 +184,7 @@ """ with contextlib.suppress(KeyError): errorCode = self.Function2Code[name] - self.__error(node.lineno - 1, node.col_offset, errorCode) + self.addErrorFromNode(node, errorCode) class PathlibVisitor(ast.NodeVisitor): @@ -282,6 +241,8 @@ self.__checkCallback(node, nameResolver.name()) + self.generic_visit(node) + class NameResolver(ast.NodeVisitor): """