Example #1
0
    def _set_message_state_in_block(
        self,
        msg: MessageDefinition,
        lines: dict[int, bool],
        node: nodes.NodeNG,
        firstchildlineno: int,
    ) -> None:
        """Set the state of a message in a block of lines."""
        first = node.fromlineno
        last = node.tolineno
        for lineno, state in list(lines.items()):
            original_lineno = lineno
            if first > lineno or last < lineno:
                continue
            # Set state for all lines for this block, if the
            # warning is applied to nodes.
            if msg.scope == WarningScope.NODE:
                if lineno > firstchildlineno:
                    state = True
                first_, last_ = node.block_range(lineno)
                # pylint: disable=useless-suppression
                # For block nodes first_ is their definition line. For example, we
                # set the state of line zero for a module to allow disabling
                # invalid-name for the module. For example:
                # 1. # pylint: disable=invalid-name
                # 2. ...
                # OR
                # 1. """Module docstring"""
                # 2. # pylint: disable=invalid-name
                # 3. ...
                #
                # But if we already visited line 0 we don't need to set its state again
                # 1. # pylint: disable=invalid-name
                # 2. # pylint: enable=invalid-name
                # 3. ...
                # The state should come from line 1, not from line 2
                # Therefore, if the 'fromlineno' is already in the states we just start
                # with the lineno we were originally visiting.
                # pylint: enable=useless-suppression
                if (first_ == node.fromlineno and first_ >= firstchildlineno
                        and node.fromlineno in self._module_msgs_state.get(
                            msg.msgid, ())):
                    first_ = lineno

            else:
                first_ = lineno
                last_ = last
            for line in range(first_, last_ + 1):
                # Do not override existing entries. This is especially important
                # when parsing the states for a scoped node where some line-disables
                # have already been parsed.
                if ((isinstance(node, nodes.Module)
                     and node.fromlineno <= line < lineno) or
                    (not isinstance(node, nodes.Module)
                     and node.fromlineno < line < lineno)
                    ) and line in self._module_msgs_state.get(msg.msgid, ()):
                    continue
                if line in lines:  # state change in the same block
                    state = lines[line]
                    original_lineno = line

                # Update suppression mapping
                if not state:
                    self._suppression_mapping[(msg.msgid,
                                               line)] = original_lineno
                else:
                    self._suppression_mapping.pop((msg.msgid, line), None)

                # Update message state for respective line
                try:
                    self._module_msgs_state[msg.msgid][line] = state
                except KeyError:
                    self._module_msgs_state[msg.msgid] = {line: state}
            del lines[lineno]
Example #2
0
 def _collect_block_lines(
     self,
     msgs_store: "MessageDefinitionStore",
     node: nodes.NodeNG,
     msg_state: MessageStateDict,
 ) -> None:
     """Recursively walk (depth first) AST to collect block level options
     line numbers.
     """
     for child in node.get_children():
         self._collect_block_lines(msgs_store, child, msg_state)
     first = node.fromlineno
     last = node.tolineno
     # first child line number used to distinguish between disable
     # which are the first child of scoped node with those defined later.
     # For instance in the code below:
     #
     # 1.   def meth8(self):
     # 2.        """test late disabling"""
     # 3.        pylint: disable=not-callable, useless-suppression
     # 4.        print(self.blip)
     # 5.        pylint: disable=no-member, useless-suppression
     # 6.        print(self.bla)
     #
     # E1102 should be disabled from line 1 to 6 while E1101 from line 5 to 6
     #
     # this is necessary to disable locally messages applying to class /
     # function using their fromlineno
     if (
         isinstance(node, (nodes.Module, nodes.ClassDef, nodes.FunctionDef))
         and node.body
     ):
         firstchildlineno = node.body[0].fromlineno
     else:
         firstchildlineno = last
     for msgid, lines in msg_state.items():
         for lineno, state in list(lines.items()):
             original_lineno = lineno
             if first > lineno or last < lineno:
                 continue
             # Set state for all lines for this block, if the
             # warning is applied to nodes.
             message_definitions = msgs_store.get_message_definitions(msgid)
             for message_definition in message_definitions:
                 if message_definition.scope == WarningScope.NODE:
                     if lineno > firstchildlineno:
                         state = True
                     first_, last_ = node.block_range(lineno)
                 else:
                     first_ = lineno
                     last_ = last
             for line in range(first_, last_ + 1):
                 # do not override existing entries
                 if line in self._module_msgs_state.get(msgid, ()):
                     continue
                 if line in lines:  # state change in the same block
                     state = lines[line]
                     original_lineno = line
                 if not state:
                     self._suppression_mapping[(msgid, line)] = original_lineno
                 try:
                     self._module_msgs_state[msgid][line] = state
                 except KeyError:
                     self._module_msgs_state[msgid] = {line: state}
             del lines[lineno]