diff options
46 files changed, 199 insertions, 101 deletions
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f4ace61f4..039f220c6 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 1ca3bdb88..7f910918f 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 ab23b6b59..160bad8af 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 <columns> from <stats> and <old_stats>, - 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 71dabd8ef..cd678b6cb 100644 --- a/pylint/checkers/base.py +++ b/pylint/checkers/base.py @@ -102,8 +102,7 @@ else: 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(".*") @@ -234,6 +233,7 @@ TYPING_TYPE_VAR_QNAME = "typing.TypeVar" 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 @@ -940,7 +940,9 @@ class BasicErrorChecker(_BasicChecker): class BasicChecker(_BasicChecker): - """Checks for : + """Basic checker. + + Checks for : * doc strings * number of arguments, local variables, branches, returns and statements in functions, methods @@ -1360,7 +1362,9 @@ class BasicChecker(_BasicChecker): @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 + """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 @@ -1378,7 +1382,9 @@ class BasicChecker(_BasicChecker): @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 + """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 @@ -1495,6 +1501,7 @@ class BasicChecker(_BasicChecker): 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 +2568,7 @@ class ComparisonChecker(_BasicChecker): 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 10e990f93..376e78545 100644 --- a/pylint/checkers/base_checker.py +++ b/pylint/checkers/base_checker.py @@ -67,8 +67,10 @@ class BaseChecker(OptionsProviderMixIn): 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 dd9a0b31c..63078cf42 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 @@ class ScopeAccessMap: 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 @@ a metaclass class method.", @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 @@ a metaclass class method.", 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 @@ a metaclass class method.", 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 dc0713a89..dd75547b9 100644 --- a/pylint/checkers/deprecated.py +++ b/pylint/checkers/deprecated.py @@ -22,6 +22,7 @@ ACCEPTABLE_NODES = ( class DeprecatedMixin(BaseChecker): """A mixin implementing logic for checking deprecated symbols. + A class implementing mixin must define "deprecated-method" Message. """ @@ -180,8 +181,9 @@ class DeprecatedMixin(BaseChecker): 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 37cd16c57..46bd443a2 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 f29ebed04..1261485b8 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 9960b8d32..58d273ca2 100644 --- a/pylint/checkers/exceptions.py +++ b/pylint/checkers/exceptions.py @@ -58,6 +58,7 @@ def _builtin_exceptions(): 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 799d97cbc..716dce4cb 100644 --- a/pylint/checkers/format.py +++ b/pylint/checkers/format.py @@ -237,7 +237,9 @@ class TokenWrapper: class FormatChecker(BaseTokenChecker): - """Checks for : + """Formatting checker. + + Checks for : * unauthorized constructions * strict indentation * line length @@ -739,7 +741,9 @@ class FormatChecker(BaseTokenChecker): 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 689573b21..f9422f9b3 100644 --- a/pylint/checkers/imports.py +++ b/pylint/checkers/imports.py @@ -300,7 +300,9 @@ DEFAULT_PREFERRED_MODULES = () 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 baec58fbb..6461975ae 100644 --- a/pylint/checkers/misc.py +++ b/pylint/checkers/misc.py @@ -76,7 +76,9 @@ class ByIdManagedMessagesChecker(BaseChecker): 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 00fa0748e..eb8473d09 100644 --- a/pylint/checkers/newstyle.py +++ b/pylint/checkers/newstyle.py @@ -45,7 +45,8 @@ MSGS = { 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 84e6c23c4..dae296ec8 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 b1fa67278..e9482f6b7 100644 --- a/pylint/checkers/refactoring/implicit_booleaness_checker.py +++ b/pylint/checkers/refactoring/implicit_booleaness_checker.py @@ -128,8 +128,7 @@ class ImplicitBooleanessChecker(checkers.BaseChecker): @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 07fcff802..00e234cbd 100644 --- a/pylint/checkers/refactoring/refactoring_checker.py +++ b/pylint/checkers/refactoring/refactoring_checker.py @@ -1531,6 +1531,7 @@ class RefactoringChecker(checkers.BaseTokenChecker): 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 @@ class RefactoringChecker(checkers.BaseTokenChecker): 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 @@ class RefactoringChecker(checkers.BaseTokenChecker): 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 5287e3127..8e6eee92d 100644 --- a/pylint/checkers/similar.py +++ b/pylint/checkers/similar.py @@ -109,9 +109,8 @@ STREAM_TYPES = Union[TextIO, BufferedReader, BytesIO] 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 @@ LinesChunkLimits_T = Tuple["LineSet", LineNumber, LineNumber] 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 stripped_lines( @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 3884fc32e..5b4670803 100644 --- a/pylint/checkers/stdlib.py +++ b/pylint/checkers/stdlib.py @@ -646,9 +646,7 @@ class StdlibChecker(DeprecatedMixin, BaseChecker): ) 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 e89e8db5f..3b2ed5106 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 78e92becb..d3ab8ca8e 100644 --- a/pylint/checkers/typecheck.py +++ b/pylint/checkers/typecheck.py @@ -1289,6 +1289,7 @@ accessed. Python regular expressions are accepted.", 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 @@ accessed. Python regular expressions are accepted.", @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 @@ accessed. Python regular expressions are accepted.", 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 026a78b5e..4cc413e5c 100644 --- a/pylint/checkers/utils.py +++ b/pylint/checkers/utils.py @@ -512,8 +512,9 @@ class UnsupportedFormatCharacter(Exception): 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 b61c5a68a..d4663e37b 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 @@ scope_type : {self._atomic.scope_type} 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 @@ scope_type : {self._atomic.scope_type} 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 @@ scope_type : {self._atomic.scope_type} 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 @@ scope_type : {self._atomic.scope_type} 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 @@ scope_type : {self._atomic.scope_type} 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 @@ scope_type : {self._atomic.scope_type} # 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 @@ class VariablesChecker(BaseChecker): "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 @@ class VariablesChecker(BaseChecker): 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 @@ class VariablesChecker(BaseChecker): 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 70b312539..2e295ca11 100644 --- a/pylint/extensions/_check_docs_utils.py +++ b/pylint/extensions/_check_docs_utils.py @@ -400,7 +400,9 @@ class SphinxDocstring(Docstring): 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 5a3e3ba17..d1bb04928 100644 --- a/pylint/extensions/code_style.py +++ b/pylint/extensions/code_style.py @@ -252,6 +252,7 @@ class CodeStyleChecker(BaseChecker): 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 592e15a5b..0d0865a13 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 35324ac04..d618ea4d4 100644 --- a/pylint/extensions/docparams.py +++ b/pylint/extensions/docparams.py @@ -492,10 +492,8 @@ class DocstringParameterChecker(BaseChecker): 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 ``*<args>`` diff --git a/pylint/extensions/emptystring.py b/pylint/extensions/emptystring.py index 15bdd1e58..096b96ec9 100644 --- a/pylint/extensions/emptystring.py +++ b/pylint/extensions/emptystring.py @@ -26,6 +26,7 @@ if TYPE_CHECKING: 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 b0dd6ce46..aeadac9b3 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 11c79eb04..c3bf9aab2 100644 --- a/pylint/extensions/overlapping_exceptions.py +++ b/pylint/extensions/overlapping_exceptions.py @@ -19,6 +19,7 @@ if TYPE_CHECKING: 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 b2e6d769d..07d18fdc7 100644 --- a/pylint/extensions/typing.py +++ b/pylint/extensions/typing.py @@ -305,8 +305,9 @@ class TypingChecker(BaseChecker): @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 f75ce4e64..c35cf8c5d 100644 --- a/pylint/graph.py +++ b/pylint/graph.py @@ -152,7 +152,8 @@ class DotBackend: def emit_edge(self, name1, name2, **props): """Emit an edge from <name1> to <name2>. - 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 @@ class DotBackend: 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 296e6b577..236e49c99 100644 --- a/pylint/lint/expand_modules.py +++ b/pylint/lint/expand_modules.py @@ -18,7 +18,9 @@ def _modpath_from_file(filename, is_namespace, path=None): 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 f3e2d6cb4..99c371493 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 6cbdc5cc7..b71905184 100644 --- a/pylint/lint/run.py +++ b/pylint/lint/run.py @@ -398,7 +398,9 @@ to search for configuration file. 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 ee19a5b65..fccdcf557 100644 --- a/pylint/pyreverse/dot_printer.py +++ b/pylint/pyreverse/dot_printer.py @@ -67,7 +67,10 @@ class DotPrinter(Printer): 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 61c8d1f7e..808f34266 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 014041993..a725d03f4 100644 --- a/pylint/pyreverse/mermaidjs_printer.py +++ b/pylint/pyreverse/mermaidjs_printer.py @@ -38,7 +38,10 @@ class MermaidJSPrinter(Printer): 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 5693e626f..2e643fe1f 100644 --- a/pylint/pyreverse/plantuml_printer.py +++ b/pylint/pyreverse/plantuml_printer.py @@ -48,7 +48,10 @@ class PlantUmlPrinter(Printer): 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 ca7f9b0a2..6f4d62f36 100644 --- a/pylint/pyreverse/printer.py +++ b/pylint/pyreverse/printer.py @@ -85,7 +85,10 @@ class Printer(ABC): 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 5cb4138e7..52bfb4fbd 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 f7e2a4665..52e99a300 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 @@ class VCGPrinter(Printer): 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 a68c8c423..c2c7382d2 100644 --- a/pylint/reporters/multi_reporter.py +++ b/pylint/reporters/multi_reporter.py @@ -49,9 +49,10 @@ class MultiReporter: @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 e851ccfbe..70dc01f38 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 @@ class OutputLine(NamedTuple): @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 ac72def41..34d66d217 100644 --- a/pylint/testutils/pyreverse.py +++ b/pylint/testutils/pyreverse.py @@ -8,6 +8,7 @@ from typing import List, Optional, Tuple # 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 c3d120458..14f57a16c 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'] |