From 3e334c122fd1d3abad5c6f72fdbb10eb167bc1b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20Noord?= <13665637+DanielNoord@users.noreply.github.com> Date: Sun, 13 Mar 2022 11:52:05 +0100 Subject: [PATCH 1/2] Upgrade ``pydocstringformatter`` to ``0.5.0`` --- .pre-commit-config.yaml | 4 +- doc/exts/pylint_messages.py | 2 + pylint/checkers/__init__.py | 5 ++- pylint/checkers/base.py | 7 ++++ pylint/checkers/base_checker.py | 6 ++- pylint/checkers/classes/class_checker.py | 19 +++++++--- pylint/checkers/deprecated.py | 6 ++- pylint/checkers/design_analysis.py | 4 +- pylint/checkers/ellipsis_checker.py | 3 +- pylint/checkers/exceptions.py | 1 + pylint/checkers/format.py | 8 +++- pylint/checkers/imports.py | 4 +- pylint/checkers/misc.py | 4 +- pylint/checkers/newstyle.py | 3 +- pylint/checkers/raw_metrics.py | 4 +- .../implicit_booleaness_checker.py | 3 +- .../refactoring/refactoring_checker.py | 7 +++- pylint/checkers/similar.py | 26 ++++++++----- pylint/checkers/stdlib.py | 4 +- pylint/checkers/strings.py | 1 + pylint/checkers/typecheck.py | 5 ++- pylint/checkers/utils.py | 30 +++++++++------ pylint/checkers/variables.py | 37 +++++++++++-------- pylint/extensions/_check_docs_utils.py | 4 +- pylint/extensions/code_style.py | 1 + pylint/extensions/comparetozero.py | 1 + pylint/extensions/docparams.py | 6 +-- pylint/extensions/emptystring.py | 1 + pylint/extensions/eq_without_hash.py | 7 ++-- pylint/extensions/overlapping_exceptions.py | 1 + pylint/extensions/typing.py | 5 ++- pylint/graph.py | 11 +++--- pylint/lint/expand_modules.py | 4 +- pylint/lint/parallel.py | 3 +- pylint/lint/run.py | 4 +- pylint/pyreverse/dot_printer.py | 5 ++- pylint/pyreverse/inspector.py | 1 + pylint/pyreverse/mermaidjs_printer.py | 5 ++- pylint/pyreverse/plantuml_printer.py | 5 ++- pylint/pyreverse/printer.py | 5 ++- pylint/pyreverse/utils.py | 1 + pylint/pyreverse/vcg_printer.py | 6 ++- pylint/reporters/multi_reporter.py | 7 ++-- pylint/testutils/output_line.py | 10 +++-- pylint/testutils/pyreverse.py | 1 + pylint/utils/utils.py | 2 +- 46 files changed, 193 insertions(+), 96 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f4ace61f43..039f220c6c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -95,7 +95,9 @@ repos: args: [--prose-wrap=always, --print-width=88] exclude: tests(/.*)*/data - repo: https://github.com/DanielNoord/pydocstringformatter - rev: a9f94bf13b08fe33f784ed7f0a0fc39e2a8549e2 + rev: v0.5.0 hooks: - id: pydocstringformatter exclude: *fixtures + args: ["--max-summary-lines=2", "--split-summary-body", "-w"] + files: "pylint" diff --git a/doc/exts/pylint_messages.py b/doc/exts/pylint_messages.py index 1ca3bdb88a..7f910918f4 100644 --- a/doc/exts/pylint_messages.py +++ b/doc/exts/pylint_messages.py @@ -52,6 +52,7 @@ def _get_all_messages( ) -> Tuple[MessagesDict, OldMessagesDict]: """Get all messages registered to a linter and return a dictionary indexed by message type. + Also return a dictionary of old message and the new messages they can be mapped to. """ messages_dict: MessagesDict = { @@ -202,6 +203,7 @@ def _write_redirect_pages(old_messages: OldMessagesDict) -> None: # pylint: disable-next=unused-argument def build_messages_pages(app: Optional[Sphinx]) -> None: """Overwrite messages files by printing the documentation to a stream. + Documentation is written in ReST format. """ # Create linter, register all checkers and extensions and get all messages diff --git a/pylint/checkers/__init__.py b/pylint/checkers/__init__.py index ab23b6b592..160bad8af2 100644 --- a/pylint/checkers/__init__.py +++ b/pylint/checkers/__init__.py @@ -77,8 +77,9 @@ def table_lines_from_stats( stat_type: Literal["duplicated_lines", "message_types"], ) -> List[str]: """Get values listed in from and , - and return a formatted list of values, designed to be given to a - ureport.Table object + and return a formatted list of values. + + The return value is designed to be given to a ureport.Table object """ lines: List[str] = [] if stat_type == "duplicated_lines": diff --git a/pylint/checkers/base.py b/pylint/checkers/base.py index 71dabd8efc..6809f213bb 100644 --- a/pylint/checkers/base.py +++ b/pylint/checkers/base.py @@ -103,6 +103,7 @@ class NamingStyle: """It may seem counterintuitive that single naming style has multiple "accepted" forms of regular expressions, but we need to special-case stuff like dunder names + in method names. """ @@ -234,6 +235,7 @@ class AnyStyle(NamingStyle): def _redefines_import(node): """Detect that the given node (AssignName) is inside an exception handler and redefines an import from the tryexcept body. + Returns True if the node redefines an import, False otherwise. """ current = node @@ -942,6 +944,7 @@ def _check_redefinition(self, redeftype, node): class BasicChecker(_BasicChecker): """Checks for : * doc strings + * number of arguments, local variables, branches, returns and statements in functions, methods * required module attributes @@ -1362,6 +1365,7 @@ def is_iterable(internal_node): def visit_return(self, node: nodes.Return) -> None: """1 - check if the node has a right sibling (if so, that's some unreachable code) + 2 - check if the node is inside the 'finally' clause of a 'try...finally' block """ @@ -1380,6 +1384,7 @@ def visit_continue(self, node: nodes.Continue) -> None: def visit_break(self, node: nodes.Break) -> None: """1 - check if the node has a right sibling (if so, that's some unreachable code) + 2 - check if the node is inside the 'finally' clause of a 'try...finally' block """ @@ -1495,6 +1500,7 @@ def _check_unreachable(self, node): def _check_not_in_finally(self, node, node_name, breaker_classes=()): """Check that a node is not inside a 'finally' clause of a 'try...finally' statement. + If we find a parent which type is in breaker_classes before a 'try...finally' block we skip the whole check. """ @@ -2561,6 +2567,7 @@ def _check_literal_comparison(self, literal, node: nodes.Compare): def _check_logical_tautology(self, node: nodes.Compare): """Check if identifier is compared against itself. + :param node: Compare node :Example: val = 786 diff --git a/pylint/checkers/base_checker.py b/pylint/checkers/base_checker.py index 10e990f935..376e785450 100644 --- a/pylint/checkers/base_checker.py +++ b/pylint/checkers/base_checker.py @@ -67,8 +67,10 @@ def __repr__(self): return f"{status} '{self.name}' (responsible for '{msgs}')" def __str__(self): - """This might be incomplete because multiple class inheriting BaseChecker - can have the same name. Cf MessageHandlerMixIn.get_full_documentation() + """This might be incomplete because multiple classes inheriting BaseChecker + can have the same name. + + See: MessageHandlerMixIn.get_full_documentation() """ return self.get_full_documentation( msgs=self.msgs, options=self.options_and_values(), reports=self.reports diff --git a/pylint/checkers/classes/class_checker.py b/pylint/checkers/classes/class_checker.py index dd9a0b31ce..63078cf421 100644 --- a/pylint/checkers/classes/class_checker.py +++ b/pylint/checkers/classes/class_checker.py @@ -362,7 +362,9 @@ def _has_data_descriptor(cls, attr): def _called_in_methods(func, klass, methods): """Check if the func was called in any of the given methods, - belonging to the *klass*. Returns True if so, False otherwise. + belonging to the *klass*. + + Returns True if so, False otherwise. """ if not isinstance(func, nodes.FunctionDef): return False @@ -697,7 +699,9 @@ def accessed(self, scope): class ClassChecker(BaseChecker): - """Checks for : + """Checker for class nodes. + + Checks for : * methods without self as first argument * overridden methods signature * access only to existent members via self @@ -876,7 +880,8 @@ def _check_typing_final(self, node: nodes.ClassDef) -> None: @check_messages("unused-private-member", "attribute-defined-outside-init") def leave_classdef(self, node: nodes.ClassDef) -> None: - """Close a class node: + """Checker for Class nodes. + check that instance attributes are defined in __init__ and check access to existent members """ @@ -1463,7 +1468,9 @@ def leave_functiondef(self, node: nodes.FunctionDef) -> None: def visit_attribute(self, node: nodes.Attribute) -> None: """Check if the getattr is an access to a class member - if so, register it. Also check for access to protected + if so, register it + + Also check for access to protected class member from outside its class (but ignore __special__ methods) """ @@ -1617,7 +1624,9 @@ def _check_classmethod_declaration(self, node): def _check_protected_attribute_access(self, node: nodes.Attribute): """Given an attribute access node (set or get), check if attribute - access is legitimate. Call _check_first_attr with node before calling + access is legitimate. + + Call _check_first_attr with node before calling this method. Valid cases are: * self._attr in a method or cls._attr in a classmethod. Checked by _check_first_attr. diff --git a/pylint/checkers/deprecated.py b/pylint/checkers/deprecated.py index dc0713a89e..dd75547b95 100644 --- a/pylint/checkers/deprecated.py +++ b/pylint/checkers/deprecated.py @@ -22,6 +22,7 @@ class DeprecatedMixin(BaseChecker): """A mixin implementing logic for checking deprecated symbols. + A class implementing mixin must define "deprecated-method" Message. """ @@ -180,8 +181,9 @@ def check_deprecated_module(self, node, mod_path): self.add_message("deprecated-module", node=node, args=mod_path) def check_deprecated_method(self, node, inferred): - """Executes the checker for the given node. This method should - be called from the checker implementing this mixin. + """Executes the checker for the given node. + + This method should be called from the checker implementing this mixin. """ # Reject nodes which aren't of interest to us. diff --git a/pylint/checkers/design_analysis.py b/pylint/checkers/design_analysis.py index 37cd16c571..46bd443a2e 100644 --- a/pylint/checkers/design_analysis.py +++ b/pylint/checkers/design_analysis.py @@ -298,7 +298,9 @@ def _get_parents( class MisdesignChecker(BaseChecker): - """Checks for sign of poor/misdesign: + """Checker of potential misdesigns. + + Checks for sign of poor/misdesign: * number of methods, attributes, local variables... * size, complexity of functions, methods """ diff --git a/pylint/checkers/ellipsis_checker.py b/pylint/checkers/ellipsis_checker.py index f29ebed042..1261485b82 100644 --- a/pylint/checkers/ellipsis_checker.py +++ b/pylint/checkers/ellipsis_checker.py @@ -28,7 +28,8 @@ class EllipsisChecker(BaseChecker): @check_messages("unnecessary-ellipsis") def visit_const(self, node: nodes.Const) -> None: """Check if the ellipsis constant is used unnecessarily. - Emit a warning when: + + Emits a warning when: - A line consisting of an ellipsis is preceded by a docstring. - A statement exists in the same scope as the ellipsis. For example: A function consisting of an ellipsis followed by a diff --git a/pylint/checkers/exceptions.py b/pylint/checkers/exceptions.py index 9960b8d32e..58d273ca2e 100644 --- a/pylint/checkers/exceptions.py +++ b/pylint/checkers/exceptions.py @@ -58,6 +58,7 @@ def predicate(obj): def _annotated_unpack_infer(stmt, context=None): """Recursively generate nodes inferred by the given statement. + If the inferred value is a list or a tuple, recurse on the elements. Returns an iterator which yields tuples in the format ('original node', 'inferred node'). diff --git a/pylint/checkers/format.py b/pylint/checkers/format.py index 799d97cbc5..716dce4cba 100644 --- a/pylint/checkers/format.py +++ b/pylint/checkers/format.py @@ -237,7 +237,9 @@ def line(self, idx): class FormatChecker(BaseTokenChecker): - """Checks for : + """Formatting checker. + + Checks for : * unauthorized constructions * strict indentation * line length @@ -739,7 +741,9 @@ def specific_splitlines(lines: str) -> List[str]: return res def check_lines(self, lines: str, lineno: int) -> None: - """Check lines have : + """Check given lines for potential messages. + + Check lines have : - a final newline - no trailing whitespace - less than a maximum number of characters diff --git a/pylint/checkers/imports.py b/pylint/checkers/imports.py index 689573b211..f9422f9b32 100644 --- a/pylint/checkers/imports.py +++ b/pylint/checkers/imports.py @@ -300,7 +300,9 @@ def _make_graph( class ImportsChecker(DeprecatedMixin, BaseChecker): - """Checks for + """BaseChecker for import statements. + + Checks for * external modules dependencies * relative / wildcard imports * cyclic imports diff --git a/pylint/checkers/misc.py b/pylint/checkers/misc.py index baec58fbbf..6461975ae4 100644 --- a/pylint/checkers/misc.py +++ b/pylint/checkers/misc.py @@ -76,7 +76,9 @@ def process_module(self, node: nodes.Module) -> None: class EncodingChecker(BaseChecker): - """Checks for: + """BaseChecker for encoding issues. + + Checks for: * warning notes in the code like FIXME, XXX * encoding issues. """ diff --git a/pylint/checkers/newstyle.py b/pylint/checkers/newstyle.py index 00fa0748e3..eb8473d09f 100644 --- a/pylint/checkers/newstyle.py +++ b/pylint/checkers/newstyle.py @@ -45,7 +45,8 @@ class NewStyleConflictChecker(BaseChecker): """Checks for usage of new style capabilities on old style classes and - other new/old styles conflicts problems + other new/old styles conflicts problems. + * use of property, __slots__, super * "super" usage """ diff --git a/pylint/checkers/raw_metrics.py b/pylint/checkers/raw_metrics.py index 84e6c23c47..dae296ec84 100644 --- a/pylint/checkers/raw_metrics.py +++ b/pylint/checkers/raw_metrics.py @@ -60,7 +60,9 @@ def report_raw_stats( class RawMetricsChecker(BaseTokenChecker): - """Does not check anything but gives some raw metrics : + """Checker that provides raw metrics instead of checking anything. + + Provides: * total number of lines * total number of code lines * total number of docstring lines diff --git a/pylint/checkers/refactoring/implicit_booleaness_checker.py b/pylint/checkers/refactoring/implicit_booleaness_checker.py index b1fa672788..e9482f6b71 100644 --- a/pylint/checkers/refactoring/implicit_booleaness_checker.py +++ b/pylint/checkers/refactoring/implicit_booleaness_checker.py @@ -128,8 +128,7 @@ def instance_has_bool(class_def: nodes.ClassDef) -> bool: @utils.check_messages("use-implicit-booleaness-not-len") def visit_unaryop(self, node: nodes.UnaryOp) -> None: """`not len(S)` must become `not S` regardless if the parent block - is a test condition or something else (boolean expression) - e.g. `if not len(S):` + is a test condition or something else (boolean expression) e.g. `if not len(S):` """ if ( isinstance(node, nodes.UnaryOp) diff --git a/pylint/checkers/refactoring/refactoring_checker.py b/pylint/checkers/refactoring/refactoring_checker.py index 07fcff802c..00e234cbd6 100644 --- a/pylint/checkers/refactoring/refactoring_checker.py +++ b/pylint/checkers/refactoring/refactoring_checker.py @@ -1531,6 +1531,7 @@ def _check_use_list_or_dict_literal(self, node: nodes.Call) -> None: def _check_consider_using_join(self, aug_assign): """We start with the augmented assignment and work our way upwards. + Names of variables for nodes if match successful: result = '' # assign for number in ['1', '2', '3'] # for_loop @@ -1824,7 +1825,7 @@ def _has_return_in_siblings(node: nodes.NodeNG) -> bool: return False def _is_function_def_never_returning(self, node: nodes.FunctionDef) -> bool: - """Return True if the function never returns. False otherwise. + """Return True if the function never returns, False otherwise. Args: node (nodes.FunctionDef): function definition node to be analyzed. @@ -1846,7 +1847,9 @@ def _is_function_def_never_returning(self, node: nodes.FunctionDef) -> bool: def _check_return_at_the_end(self, node): """Check for presence of a *single* return statement at the end of a - function. "return" or "return None" are useless because None is the + function. + + "return" or "return None" are useless because None is the default return type if they are missing. NOTE: produces a message only if there is a single return statement diff --git a/pylint/checkers/similar.py b/pylint/checkers/similar.py index 5287e31279..8e6eee92d5 100644 --- a/pylint/checkers/similar.py +++ b/pylint/checkers/similar.py @@ -109,9 +109,8 @@ class LineSpecifs(NamedTuple): class CplSuccessiveLinesLimits: - """This class holds a couple of SuccessiveLinesLimits objects, one for each file compared, - and a counter on the number of common lines between both stripped lines collections extracted - from both files + """Holds a SuccessiveLinesLimits object for each file compared and a + counter on the number of common lines between both stripped lines collections extracted from both files """ __slots__ = ("first_file", "second_file", "effective_cmn_lines_nb") @@ -230,7 +229,9 @@ def increment(self, value: Index) -> "LineSetStartCouple": def hash_lineset( lineset: "LineSet", min_common_lines: int = DEFAULT_MIN_SIMILARITY_LINE ) -> Tuple[HashToIndex_T, IndexToLines_T]: - """Return two dicts. The first associates the hash of successive stripped lines of a lineset + """Return two dicts. + + The first associates the hash of successive stripped lines of a lineset to the indices of the starting lines. The second dict, associates the index of the starting line in the lineset's stripped lines to the couple [start, end] lines number in the corresponding file. @@ -318,9 +319,12 @@ def filter_noncode_lines( stindex_2: Index, common_lines_nb: int, ) -> int: - """Return the effective number of common lines between lineset1 and lineset2 filtered from non code lines, that is to say the number of - common successive stripped lines except those that do not contain code (for example a ligne with only an - ending parathensis) + """Return the effective number of common lines between lineset1 + and lineset2 filtered from non code lines. + + That is to say the number of common successive stripped + lines except those that do not contain code (for example + a line with only an ending parathensis) :param ls_1: first lineset :param stindex_1: first lineset starting index @@ -665,6 +669,7 @@ def _get_functions( @functools.total_ordering class LineSet: """Holds and indexes all the lines of a single source file. + Allows for correspondence between real lines of the source file and stripped ones, which are the real ones from which undesired patterns have been removed. """ @@ -737,9 +742,10 @@ def report_similarities( # wrapper to get a pylint checker from the similar class class SimilarChecker(BaseChecker, Similar, MapReduceMixin): - """Checks for similarities and duplicated code. This computation may be - memory / CPU intensive, so you should disable it if you experiment some - problems. + """Checks for similarities and duplicated code. + + This computation may be memory / CPU intensive, so you + should disable it if you experiment some problems. """ __implements__ = (IRawChecker,) diff --git a/pylint/checkers/stdlib.py b/pylint/checkers/stdlib.py index 3884fc32e4..5b4670803e 100644 --- a/pylint/checkers/stdlib.py +++ b/pylint/checkers/stdlib.py @@ -646,9 +646,7 @@ def _check_redundant_assert(self, node, infer): ) def _check_datetime(self, node): - """Check that a datetime was inferred. - If so, emit boolean-datetime warning. - """ + """Check that a datetime was inferred, if so, emit boolean-datetime warning.""" try: inferred = next(node.infer()) except astroid.InferenceError: diff --git a/pylint/checkers/strings.py b/pylint/checkers/strings.py index e89e8db5f3..3b2ed51068 100644 --- a/pylint/checkers/strings.py +++ b/pylint/checkers/strings.py @@ -933,6 +933,7 @@ def register(linter: "PyLinter") -> None: def str_eval(token): """Mostly replicate `ast.literal_eval(token)` manually to avoid any performance hit. + This supports f-strings, contrary to `ast.literal_eval`. We have to support all string literal notations: https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals diff --git a/pylint/checkers/typecheck.py b/pylint/checkers/typecheck.py index 78e92becb8..d3ab8ca8e4 100644 --- a/pylint/checkers/typecheck.py +++ b/pylint/checkers/typecheck.py @@ -1289,6 +1289,7 @@ def _check_uninferable_call(self, node): def _check_argument_order(self, node, call_site, called, called_param_names): """Match the supplied argument names against the function parameters. + Warn if some argument names are not in the same order as they are in the function signature. """ @@ -1339,8 +1340,7 @@ def _check_isinstance_args(self, node): @check_messages(*(list(MSGS.keys()))) def visit_call(self, node: nodes.Call) -> None: """Check that called functions/methods are inferred to callable objects, - and that the arguments passed to the function match the parameters in - the inferred function's definition + and that passed arguments match the parameters in the inferred function. """ called = safe_infer(node.func) @@ -2001,6 +2001,7 @@ def visit_for(self, node: nodes.For) -> None: class IterableChecker(BaseChecker): """Checks for non-iterables used in an iterable context. + Contexts include: - for-statement - starargs in function call diff --git a/pylint/checkers/utils.py b/pylint/checkers/utils.py index 026a78b5e7..4cc413e5c3 100644 --- a/pylint/checkers/utils.py +++ b/pylint/checkers/utils.py @@ -512,8 +512,9 @@ def __init__(self, index): def parse_format_string( format_string: str, ) -> Tuple[Set[str], int, Dict[str, str], List[str]]: - """Parses a format string, returning a tuple of (keys, num_args), where 'keys' - is the set of mapping keys in the format string, and 'num_args' is the number + """Parses a format string, returning a tuple (keys, num_args). + + Where 'keys' is the set of mapping keys in the format string, and 'num_args' is the number of arguments required by the format string. Raises IncompleteFormatString or UnsupportedFormatCharacter if a parse error occurs. """ @@ -593,8 +594,9 @@ def split_format_field_names(format_string) -> Tuple[str, Iterable[Tuple[bool, s def collect_string_fields(format_string) -> Iterable[Optional[str]]: """Given a format string, return an iterator - of all the valid format fields. It handles nested fields - as well. + of all the valid format fields. + + It handles nested fields as well. """ formatter = string.Formatter() try: @@ -627,8 +629,9 @@ def parse_format_method_string( format_string: str, ) -> Tuple[List[Tuple[str, List[Tuple[bool, str]]]], int, int]: """Parses a PEP 3101 format string, returning a tuple of - (keyword_arguments, implicit_pos_args_cnt, explicit_pos_args), - where keyword_arguments is the set of mapping keys in the format string, implicit_pos_args_cnt + (keyword_arguments, implicit_pos_args_cnt, explicit_pos_args). + + keyword_arguments is the set of mapping keys in the format string, implicit_pos_args_cnt is the number of arguments required by the format string and explicit_pos_args is the number of arguments passed with the position. """ @@ -1045,8 +1048,8 @@ def get_exception_handlers( def is_node_inside_try_except(node: nodes.Raise) -> bool: - """Check if the node is directly under a Try/Except statement. - (but not under an ExceptHandler!) + """Check if the node is directly under a Try/Except statement + (but not under an ExceptHandler!). Args: node (nodes.Raise): the node raising the exception. @@ -1366,7 +1369,9 @@ def is_registered_in_singledispatch_function(node: nodes.FunctionDef) -> bool: def get_node_last_lineno(node: nodes.NodeNG) -> int: - """Get the last lineno of the given node. For a simple statement this will just be node.lineno, + """Get the last lineno of the given node. + + For a simple statement this will just be node.lineno, but for a node that has child statements (e.g. a method) this will be the lineno of the last child statement recursively. """ @@ -1438,6 +1443,7 @@ def is_node_in_type_annotation_context(node: nodes.NodeNG) -> bool: def is_subclass_of(child: nodes.ClassDef, parent: nodes.ClassDef) -> bool: """Check if first node is a subclass of second node. + :param child: Node to check for subclass. :param parent: Node to check for superclass. :returns: True if child is derived from parent. False otherwise. @@ -1658,6 +1664,7 @@ def is_typing_guard(node: nodes.If) -> bool: def is_node_in_guarded_import_block(node: nodes.NodeNG) -> bool: """Return True if node is part for guarded if block. + I.e. `sys.version_info` or `typing.TYPE_CHECKING` """ return isinstance(node.parent, nodes.If) and ( @@ -1731,8 +1738,9 @@ def get_node_first_ancestor_of_type_and_its_child( node: nodes.NodeNG, ancestor_type: Union[Type[T_Node], Tuple[Type[T_Node], ...]] ) -> Union[Tuple[None, None], Tuple[T_Node, nodes.NodeNG]]: """Modified version of get_node_first_ancestor_of_type to also return the - descendant visited directly before reaching the sought ancestor. Useful - for extracting whether a statement is guarded by a try, except, or finally + descendant visited directly before reaching the sought ancestor + + Useful for extracting whether a statement is guarded by a try, except, or finally when searching for a TryFinally ancestor. """ child = node diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py index b61c5a68ae..d4663e37ba 100644 --- a/pylint/checkers/variables.py +++ b/pylint/checkers/variables.py @@ -310,7 +310,9 @@ def _infer_name_module(node, name): def _fix_dot_imports(not_consumed): """Try to fix imports with multiple dots, by returning a dictionary - with the import names expanded. The function unflattens root imports, + with the import names expanded. + + The function unflattens root imports, like 'xml' (when we have both 'xml.etree' and 'xml.sax'), to 'xml.etree' and 'xml.sax' respectively. """ @@ -351,8 +353,9 @@ def _fix_dot_imports(not_consumed): def _find_frame_imports(name, frame): - """Detect imports in the frame, with the required - *name*. Such imports can be considered assignments. + """Detect imports in the frame, with the required *name*. + + Such imports can be considered assignments. Returns True if an import for the given name was found. """ imports = frame.nodes_of_class((nodes.Import, nodes.ImportFrom)) @@ -603,6 +606,7 @@ def consumed(self): def consumed_uncertain(self) -> DefaultDict[str, List[nodes.NodeNG]]: """Retrieves nodes filtered out by get_next_to_consume() that may not have executed, such as statements in except blocks, or statements + in try blocks (when evaluating their corresponding except and finally blocks). Checkers that want to treat the statements as executed (e.g. for unused-variable) may need to add them back. @@ -615,6 +619,7 @@ def scope_type(self): def mark_as_consumed(self, name, consumed_nodes): """Mark the given nodes as consumed for the name. + If all of the nodes for the name were consumed, delete the name from the to_consume dictionary """ @@ -627,8 +632,9 @@ def mark_as_consumed(self, name, consumed_nodes): del self.to_consume[name] def get_next_to_consume(self, node: nodes.Name) -> Optional[List[nodes.NodeNG]]: - """Return a list of the nodes that define `node` from this scope. If it is - uncertain whether a node will be consumed, such as for statements in + """Return a list of the nodes that define `node` from this scope. + + If it is uncertain whether a node will be consumed, such as for statements in except blocks, add it to self.consumed_uncertain instead of returning it. Return None to indicate a special case that needs to be handled by the caller. """ @@ -804,6 +810,7 @@ def _check_loop_finishes_via_except( node: nodes.NodeNG, other_node_try_except: nodes.TryExcept ) -> bool: """Check for a case described in https://github.com/PyCQA/pylint/issues/5683. + It consists of a specific control flow scenario where the only non-break exit from a loop consists of the very except handler we are examining, such that code in the `else` branch of the loop can depend on it @@ -895,9 +902,8 @@ def _recursive_search_for_continue_before_break( def _uncertain_nodes_in_try_blocks_when_evaluating_except_blocks( found_nodes: List[nodes.NodeNG], node_statement: nodes.Statement ) -> List[nodes.NodeNG]: - """Return any nodes in ``found_nodes`` that should be treated as uncertain - because they are in a try block and the ``node_statement`` being evaluated - is in one of its except handlers. + """Return any nodes in ``found_nodes`` that should be treated as uncertain because they + are in a try block and the ``node_statement`` being evaluated is in one of its except handlers. """ uncertain_nodes: List[nodes.NodeNG] = [] closest_except_handler = utils.get_node_first_ancestor_of_type( @@ -994,7 +1000,9 @@ def _uncertain_nodes_in_try_blocks_when_evaluating_finally_blocks( # pylint: disable=too-many-public-methods class VariablesChecker(BaseChecker): - """Checks for + """BaseChecker for variables. + + Checks for * unused variables / imports * undefined variables * redefinition of variable from builtins or from an outer scope @@ -1781,9 +1789,8 @@ def visit_importfrom(self, node: nodes.ImportFrom) -> None: "unbalanced-tuple-unpacking", "unpacking-non-sequence", "self-cls-assignment" ) def visit_assign(self, node: nodes.Assign) -> None: - """Check unbalanced tuple unpacking for assignments - and unpacking non-sequences as well as in case self/cls - get assigned. + """Check unbalanced tuple unpacking for assignments and unpacking + non-sequences as well as in case self/cls get assigned. """ self._check_self_cls_assign(node) if not isinstance(node.targets[0], (nodes.Tuple, nodes.List)): @@ -2485,8 +2492,7 @@ def _has_homonym_in_upper_function_scope( self, node: nodes.Name, index: int ) -> bool: """Return whether there is a node with the same name in the - to_consume dict of an upper scope and if that scope is a - function + to_consume dict of an upper scope and if that scope is a function :param node: node to check for :param index: index of the current consumer inside self._to_consume @@ -2615,8 +2621,7 @@ def _nodes_to_unpack(node: nodes.NodeNG) -> Optional[List[nodes.NodeNG]]: def _check_module_attrs(self, node, module, module_names): """Check that module_names (list of string) are accessible through the - given module - if the latest access name corresponds to a module, return it + given module, if the latest access name corresponds to a module, return it """ while module_names: name = module_names.pop(0) diff --git a/pylint/extensions/_check_docs_utils.py b/pylint/extensions/_check_docs_utils.py index 70b312539e..2e295ca110 100644 --- a/pylint/extensions/_check_docs_utils.py +++ b/pylint/extensions/_check_docs_utils.py @@ -400,7 +400,9 @@ def match_param_docs(self): class EpytextDocstring(SphinxDocstring): - """Epytext is similar to Sphinx. See the docs: + """Epytext is similar to Sphinx. + + See the docs: http://epydoc.sourceforge.net/epytext.html http://epydoc.sourceforge.net/fields.html#fields diff --git a/pylint/extensions/code_style.py b/pylint/extensions/code_style.py index 5a3e3ba17d..d1bb04928a 100644 --- a/pylint/extensions/code_style.py +++ b/pylint/extensions/code_style.py @@ -252,6 +252,7 @@ def _check_prev_sibling_to_if_stmt( prev_sibling: Optional[nodes.NodeNG], name: Optional[str] ) -> TypeGuard[Union[nodes.Assign, nodes.AnnAssign]]: """Check if previous sibling is an assignment with the same name. + Ignore statements which span multiple lines. """ if prev_sibling is None or prev_sibling.tolineno - prev_sibling.fromlineno != 0: diff --git a/pylint/extensions/comparetozero.py b/pylint/extensions/comparetozero.py index 592e15a5b9..0d0865a133 100644 --- a/pylint/extensions/comparetozero.py +++ b/pylint/extensions/comparetozero.py @@ -31,6 +31,7 @@ def _is_constant_zero(node): class CompareToZeroChecker(checkers.BaseChecker): """Checks for comparisons to zero. + Most of the time you should use the fact that integers with a value of 0 are false. An exception to this rule is when 0 is allowed in the program and has a different meaning than None! diff --git a/pylint/extensions/docparams.py b/pylint/extensions/docparams.py index 35324ac041..d618ea4d4d 100644 --- a/pylint/extensions/docparams.py +++ b/pylint/extensions/docparams.py @@ -492,10 +492,8 @@ def check_arguments_in_docstring( warning_node: astroid.NodeNG, accept_no_param_doc: Optional[bool] = None, ): - """Check that all parameters in a function, method or class constructor - on the one hand and the parameters mentioned in the parameter - documentation (e.g. the Sphinx tags 'param' and 'type') on the other - hand are consistent with each other. + """Check that all parameters are consistent with the parameters mentioned + in the parameter documentation (e.g. the Sphinx tags 'param' and 'type'). * Undocumented parameters except 'self' are noticed. * Undocumented parameter types except for 'self' and the ``*`` diff --git a/pylint/extensions/emptystring.py b/pylint/extensions/emptystring.py index 15bdd1e584..096b96ec90 100644 --- a/pylint/extensions/emptystring.py +++ b/pylint/extensions/emptystring.py @@ -26,6 +26,7 @@ class CompareToEmptyStringChecker(checkers.BaseChecker): """Checks for comparisons to empty string. + Most of the time you should use the fact that empty strings are false. An exception to this rule is when an empty string value is allowed in the program and has a different meaning than None! diff --git a/pylint/extensions/eq_without_hash.py b/pylint/extensions/eq_without_hash.py index b0dd6ce46f..aeadac9b33 100644 --- a/pylint/extensions/eq_without_hash.py +++ b/pylint/extensions/eq_without_hash.py @@ -1,9 +1,10 @@ # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/main/LICENSE -"""This is the remnant of the python3 checker. It was removed because -the transition from python 2 to python3 is behind us, but some checks -are still useful in python3 after all. +"""This is the remnant of the python3 checker. + +It was removed because the transition from python 2 to python3 is +behind us, but some checks are still useful in python3 after all. See https://github.com/PyCQA/pylint/issues/5025 """ diff --git a/pylint/extensions/overlapping_exceptions.py b/pylint/extensions/overlapping_exceptions.py index 11c79eb04e..c3bf9aab2e 100644 --- a/pylint/extensions/overlapping_exceptions.py +++ b/pylint/extensions/overlapping_exceptions.py @@ -19,6 +19,7 @@ class OverlappingExceptionsChecker(checkers.BaseChecker): """Checks for two or more exceptions in the same exception handler clause that are identical or parts of the same inheritance hierarchy + (i.e. overlapping). """ diff --git a/pylint/extensions/typing.py b/pylint/extensions/typing.py index b2e6d769d0..07d18fdc7f 100644 --- a/pylint/extensions/typing.py +++ b/pylint/extensions/typing.py @@ -305,8 +305,9 @@ def _check_for_typing_alias( @check_messages("consider-using-alias") def leave_module(self, node: nodes.Module) -> None: """After parsing of module is complete, add messages for - 'consider-using-alias' check. Make sure results are safe - to recommend / collision free. + 'consider-using-alias' check. + + Make sure results are safe to recommend / collision free. """ if self._py39_plus: for msg in self._deprecated_typing_alias_msgs: diff --git a/pylint/graph.py b/pylint/graph.py index f75ce4e641..c35cf8c5da 100644 --- a/pylint/graph.py +++ b/pylint/graph.py @@ -152,7 +152,8 @@ def emit(self, line): def emit_edge(self, name1, name2, **props): """Emit an edge from to . - edge properties: see https://www.graphviz.org/doc/info/attrs.html + + For edge properties: see https://www.graphviz.org/doc/info/attrs.html """ attrs = [f'{prop}="{value}"' for prop, value in props.items()] n_from, n_to = normalize_node_id(name1), normalize_node_id(name2) @@ -160,7 +161,8 @@ def emit_edge(self, name1, name2, **props): def emit_node(self, name, **props): """Emit a node with given properties. - node properties: see https://www.graphviz.org/doc/info/attrs.html + + For node properties: see https://www.graphviz.org/doc/info/attrs.html """ attrs = [f'{prop}="{value}"' for prop, value in props.items()] self.emit(f"{normalize_node_id(name)} [{', '.join(sorted(attrs))}];") @@ -172,9 +174,8 @@ def normalize_node_id(nid): def get_cycles(graph_dict, vertices=None): - """Given a dictionary representing an ordered graph (i.e. key are vertices - and values is a list of destination vertices representing edges), return a - list of detected cycles + """Return a list of detected cycles in a dictionary representing an ordered graph + (i.e. key are vertices and values is a list of destination vertices representing edges) """ if not graph_dict: return () diff --git a/pylint/lint/expand_modules.py b/pylint/lint/expand_modules.py index 296e6b5778..236e49c992 100644 --- a/pylint/lint/expand_modules.py +++ b/pylint/lint/expand_modules.py @@ -18,7 +18,9 @@ def _is_package_cb(inner_path, parts): def get_python_path(filepath: str) -> str: """TODO This get the python path with the (bad) assumption that there is always - an __init__.py. This is not true since python 3.3 and is causing problem. + an __init__.py + + This is not true since python 3.3 and is causing problem. """ dirname = os.path.realpath(os.path.expanduser(filepath)) if not os.path.isdir(dirname): diff --git a/pylint/lint/parallel.py b/pylint/lint/parallel.py index f3e2d6cb45..99c3714931 100644 --- a/pylint/lint/parallel.py +++ b/pylint/lint/parallel.py @@ -133,7 +133,8 @@ def check_parallel( files: Iterable[FileItem], arguments: Union[None, str, Sequence[str]] = None, ) -> None: - """Use the given linter to lint the files with given amount of workers (jobs) + """Use the given linter to lint the files with given amount of workers (jobs). + This splits the work filestream-by-filestream. If you need to do work across multiple files, as in the similarity-checker, then inherit from MapReduceMixin and implement the map/reduce mixin functionality. diff --git a/pylint/lint/run.py b/pylint/lint/run.py index 6cbdc5cc71..b719051844 100644 --- a/pylint/lint/run.py +++ b/pylint/lint/run.py @@ -398,7 +398,9 @@ def cb_add_plugins(self, name, value): self._plugins.extend(utils._splitstrip(value)) def cb_error_mode(self, *args, **kwargs): - """Error mode: + """Callback for --errors-only. + + Error mode: * disable all but error messages * disable the 'miscellaneous' checker which can be safely deactivated in debug diff --git a/pylint/pyreverse/dot_printer.py b/pylint/pyreverse/dot_printer.py index ee19a5b659..fccdcf5579 100644 --- a/pylint/pyreverse/dot_printer.py +++ b/pylint/pyreverse/dot_printer.py @@ -67,7 +67,10 @@ def emit_node( type_: NodeType, properties: Optional[NodeProperties] = None, ) -> None: - """Create a new node. Nodes can be classes, packages, participants etc.""" + """Create a new node. + + Nodes can be classes, packages, participants etc. + """ if properties is None: properties = NodeProperties(label=name) shape = SHAPES[type_] diff --git a/pylint/pyreverse/inspector.py b/pylint/pyreverse/inspector.py index 61c8d1f7ea..808f34266c 100644 --- a/pylint/pyreverse/inspector.py +++ b/pylint/pyreverse/inspector.py @@ -15,6 +15,7 @@ # For details: https://github.com/PyCQA/pylint/blob/main/LICENSE """Visitor doing some postprocessing on the astroid tree. + Try to resolve definitions (namespace) dictionary, relationship... """ import collections diff --git a/pylint/pyreverse/mermaidjs_printer.py b/pylint/pyreverse/mermaidjs_printer.py index 0140419931..a725d03f4c 100644 --- a/pylint/pyreverse/mermaidjs_printer.py +++ b/pylint/pyreverse/mermaidjs_printer.py @@ -38,7 +38,10 @@ def emit_node( type_: NodeType, properties: Optional[NodeProperties] = None, ) -> None: - """Create a new node. Nodes can be classes, packages, participants etc.""" + """Create a new node. + + Nodes can be classes, packages, participants etc. + """ if properties is None: properties = NodeProperties(label=name) stereotype = "~~Interface~~" if type_ is NodeType.INTERFACE else "" diff --git a/pylint/pyreverse/plantuml_printer.py b/pylint/pyreverse/plantuml_printer.py index 5693e626ff..2e643fe1fe 100644 --- a/pylint/pyreverse/plantuml_printer.py +++ b/pylint/pyreverse/plantuml_printer.py @@ -48,7 +48,10 @@ def emit_node( type_: NodeType, properties: Optional[NodeProperties] = None, ) -> None: - """Create a new node. Nodes can be classes, packages, participants etc.""" + """Create a new node. + + Nodes can be classes, packages, participants etc. + """ if properties is None: properties = NodeProperties(label=name) stereotype = " << interface >>" if type_ is NodeType.INTERFACE else "" diff --git a/pylint/pyreverse/printer.py b/pylint/pyreverse/printer.py index ca7f9b0a2a..6f4d62f364 100644 --- a/pylint/pyreverse/printer.py +++ b/pylint/pyreverse/printer.py @@ -85,7 +85,10 @@ def emit_node( type_: NodeType, properties: Optional[NodeProperties] = None, ) -> None: - """Create a new node. Nodes can be classes, packages, participants etc.""" + """Create a new node. + + Nodes can be classes, packages, participants etc. + """ @abstractmethod def emit_edge( diff --git a/pylint/pyreverse/utils.py b/pylint/pyreverse/utils.py index 5cb4138e74..52bfb4fbdd 100644 --- a/pylint/pyreverse/utils.py +++ b/pylint/pyreverse/utils.py @@ -286,6 +286,7 @@ def infer_node(node: Union[nodes.AssignAttr, nodes.AssignName]) -> set: def check_graphviz_availability(): """Check if the ``dot`` command is available on the machine. + This is needed if image output is desired and ``dot`` is used to convert from *.dot or *.gv into the final output format. """ diff --git a/pylint/pyreverse/vcg_printer.py b/pylint/pyreverse/vcg_printer.py index f7e2a46652..52e99a300a 100644 --- a/pylint/pyreverse/vcg_printer.py +++ b/pylint/pyreverse/vcg_printer.py @@ -15,6 +15,7 @@ """Functions to generate files readable with Georg Sander's vcg (Visualization of Compiler Graphs). + You can download vcg at https://rw4.cs.uni-sb.de/~sander/html/gshome.html Note that vcg exists as a debian package. See vcg's documentation for explanation about the different values that @@ -212,7 +213,10 @@ def emit_node( type_: NodeType, properties: Optional[NodeProperties] = None, ) -> None: - """Create a new node. Nodes can be classes, packages, participants etc.""" + """Create a new node. + + Nodes can be classes, packages, participants etc. + """ if properties is None: properties = NodeProperties(label=name) elif properties.label is None: diff --git a/pylint/reporters/multi_reporter.py b/pylint/reporters/multi_reporter.py index a68c8c423d..c2c7382d29 100644 --- a/pylint/reporters/multi_reporter.py +++ b/pylint/reporters/multi_reporter.py @@ -49,9 +49,10 @@ def out(self): @out.setter def out(self, output: Optional[AnyFile] = None): - """MultiReporter doesn't have its own output. This method is only - provided for API parity with BaseReporter and should not be called - with non-None values for 'output'. + """MultiReporter doesn't have its own output. + + This method is only provided for API parity with BaseReporter + and should not be called with non-None values for 'output'. """ self.__out = None if output is not None: diff --git a/pylint/testutils/output_line.py b/pylint/testutils/output_line.py index e851ccfbe9..70dc01f383 100644 --- a/pylint/testutils/output_line.py +++ b/pylint/testutils/output_line.py @@ -23,7 +23,10 @@ class MessageTest(NamedTuple): col_offset: Optional[int] = None end_line: Optional[int] = None end_col_offset: Optional[int] = None - """Used to test messages produced by pylint. Class name cannot start with Test as pytest doesn't allow constructors in test classes.""" + """Used to test messages produced by pylint. + + Class name cannot start with Test as pytest doesn't allow constructors in test classes. + """ class MalformedOutputLineException(Exception): @@ -93,8 +96,9 @@ def from_msg(cls, msg: Message, check_endline: bool = True) -> "OutputLine": @staticmethod def _get_column(column: str) -> int: - """Handle column numbers except for python < 3.8. The ast parser in those versions doesn't - return them. + """Handle column numbers except for python < 3.8. + + The ast parser in those versions doesn't return them. """ if not PY38_PLUS: # We check the column only for the new better ast parser introduced in python 3.8 diff --git a/pylint/testutils/pyreverse.py b/pylint/testutils/pyreverse.py index ac72def41c..34d66d2177 100644 --- a/pylint/testutils/pyreverse.py +++ b/pylint/testutils/pyreverse.py @@ -8,6 +8,7 @@ # A NamedTuple is not possible as some tests need to modify attributes during the test. class PyreverseConfig: # pylint: disable=too-many-instance-attributes, too-many-arguments """Holds the configuration options for Pyreverse. + The default values correspond to the defaults of the options' parser. """ diff --git a/pylint/utils/utils.py b/pylint/utils/utils.py index c3d120458e..14f57a16c1 100644 --- a/pylint/utils/utils.py +++ b/pylint/utils/utils.py @@ -277,7 +277,7 @@ def get_global_option( def _splitstrip(string, sep=","): """Return a list of stripped string by splitting the string given as - argument on `sep` (',' by default). Empty string are discarded. + argument on `sep` (',' by default), empty strings are discarded. >>> _splitstrip('a, b, c , 4,,') ['a', 'b', 'c', '4'] From 6396673d84f00f72b5d0b4cee6260568cbb5c17a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20Noord?= <13665637+DanielNoord@users.noreply.github.com> Date: Sun, 13 Mar 2022 11:56:18 +0100 Subject: [PATCH 2/2] Update --- pylint/checkers/base.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/pylint/checkers/base.py b/pylint/checkers/base.py index 6809f213bb..cd678b6cb7 100644 --- a/pylint/checkers/base.py +++ b/pylint/checkers/base.py @@ -102,9 +102,7 @@ class NamingStyle: """It may seem counterintuitive that single naming style has multiple "accepted" - forms of regular expressions, but we need to special-case stuff like dunder names - - in method names. + forms of regular expressions, but we need to special-case stuff like dunder names in method names. """ ANY: Pattern[str] = re.compile(".*") @@ -942,9 +940,10 @@ def _check_redefinition(self, redeftype, node): class BasicChecker(_BasicChecker): - """Checks for : - * doc strings + """Basic checker. + Checks for : + * doc strings * number of arguments, local variables, branches, returns and statements in functions, methods * required module attributes @@ -1363,9 +1362,10 @@ def is_iterable(internal_node): @utils.check_messages("unreachable", "lost-exception") def visit_return(self, node: nodes.Return) -> None: - """1 - check if the node has a right sibling (if so, that's some - unreachable code) + """Return node visitor. + 1 - check if the node has a right sibling (if so, that's some + unreachable code) 2 - check if the node is inside the 'finally' clause of a 'try...finally' block """ @@ -1382,9 +1382,10 @@ def visit_continue(self, node: nodes.Continue) -> None: @utils.check_messages("unreachable", "lost-exception") def visit_break(self, node: nodes.Break) -> None: - """1 - check if the node has a right sibling (if so, that's some - unreachable code) + """Break node visitor. + 1 - check if the node has a right sibling (if so, that's some + unreachable code) 2 - check if the node is inside the 'finally' clause of a 'try...finally' block """