@@ -272,7 +272,7 @@ def new_line(self, tokens: TokenWrapper, line_end: int, line_start: int) -> None
272272    def  process_module (self , node : nodes .Module ) ->  None :
273273        pass 
274274
275-     # pylint: disable-next = too-many-return-statements, too-many-branches  
275+     # pylint: disable-next = too-many-return-statements 
276276    def  _check_keyword_parentheses (
277277        self , tokens : list [tokenize .TokenInfo ], start : int 
278278    ) ->  None :
@@ -351,30 +351,31 @@ def _check_keyword_parentheses(
351351                    )
352352                return 
353353            elif  depth  ==  1 :
354-                 # This is a tuple, which is always acceptable. 
355-                 if  token [1 ] ==  "," :
356-                     return 
357-                 # 'and' and 'or' are the only boolean operators with lower precedence 
358-                 # than 'not', so parens are only required when they are found. 
359-                 if  token [1 ] in  {"and" , "or" }:
360-                     found_and_or  =  True 
361-                 # A yield inside an expression must always be in parentheses, 
362-                 # quit early without error. 
363-                 elif  token [1 ] ==  "yield" :
364-                     return 
365-                 # A generator expression always has a 'for' token in it, and 
366-                 # the 'for' token is only legal inside parens when it is in a 
367-                 # generator expression.  The parens are necessary here, so bail 
368-                 # without an error. 
369-                 elif  token [1 ] ==  "for" :
370-                     return 
371-                 # A generator expression can have an 'else' token in it. 
372-                 # We check the rest of the tokens to see if any problems occur after 
373-                 # the 'else'. 
374-                 elif  token [1 ] ==  "else" :
375-                     if  "("  in  (i .string  for  i  in  tokens [i :]):
376-                         self ._check_keyword_parentheses (tokens [i :], 0 )
377-                     return 
354+                 match  token [1 ]:
355+                     case  "," :
356+                         # This is a tuple, which is always acceptable. 
357+                         return 
358+                     case  "and"  |  "or" :
359+                         # 'and' and 'or' are the only boolean operators with lower precedence 
360+                         # than 'not', so parens are only required when they are found. 
361+                         found_and_or  =  True 
362+                     case  "yield" :
363+                         # A yield inside an expression must always be in parentheses, 
364+                         # quit early without error. 
365+                         return 
366+                     case  "for" :
367+                         # A generator expression always has a 'for' token in it, and 
368+                         # the 'for' token is only legal inside parens when it is in a 
369+                         # generator expression.  The parens are necessary here, so bail 
370+                         # without an error. 
371+                         return 
372+                     case  "else" :
373+                         # A generator expression can have an 'else' token in it. 
374+                         # We check the rest of the tokens to see if any problems occur after 
375+                         # the 'else'. 
376+                         if  "("  in  (i .string  for  i  in  tokens [i :]):
377+                             self ._check_keyword_parentheses (tokens [i :], 0 )
378+                         return 
378379
379380    def  process_tokens (self , tokens : list [tokenize .TokenInfo ]) ->  None :
380381        """Process tokens and search for: 
@@ -401,39 +402,42 @@ def process_tokens(self, tokens: list[tokenize.TokenInfo]) -> None:
401402                else :
402403                    self .new_line (TokenWrapper (tokens ), idx  -  1 , idx )
403404
404-             if  tok_type  ==  tokenize .NEWLINE :
405-                 # a program statement, or ENDMARKER, will eventually follow, 
406-                 # after some (possibly empty) run of tokens of the form 
407-                 #     (NL | COMMENT)* (INDENT | DEDENT+)? 
408-                 # If an INDENT appears, setting check_equal is wrong, and will 
409-                 # be undone when we see the INDENT. 
410-                 check_equal  =  True 
411-                 self ._check_line_ending (string , line_num )
412-             elif  tok_type  ==  tokenize .INDENT :
413-                 check_equal  =  False 
414-                 self .check_indent_level (string , indents [- 1 ] +  1 , line_num )
415-                 indents .append (indents [- 1 ] +  1 )
416-             elif  tok_type  ==  tokenize .DEDENT :
417-                 # there's nothing we need to check here!  what's important is 
418-                 # that when the run of DEDENTs ends, the indentation of the 
419-                 # program statement (or ENDMARKER) that triggered the run is 
420-                 # equal to what's left at the top of the indents stack 
421-                 check_equal  =  True 
422-                 if  len (indents ) >  1 :
423-                     del  indents [- 1 ]
424-             elif  tok_type  ==  tokenize .NL :
425-                 if  not  line .strip ("\r \n " ):
426-                     last_blank_line_num  =  line_num 
427-             elif  tok_type  not  in tokenize .COMMENT , tokenize .ENCODING ):
428-                 # This is the first concrete token following a NEWLINE, so it 
429-                 # must be the first token of the next program statement, or an 
430-                 # ENDMARKER; the "line" argument exposes the leading white-space 
431-                 # for this statement; in the case of ENDMARKER, line is an empty 
432-                 # string, so will properly match the empty string with which the 
433-                 # "indents" stack was seeded 
434-                 if  check_equal :
405+             match  tok_type :
406+                 case  tokenize .NEWLINE :
407+                     # a program statement, or ENDMARKER, will eventually follow, 
408+                     # after some (possibly empty) run of tokens of the form 
409+                     #     (NL | COMMENT)* (INDENT | DEDENT+)? 
410+                     # If an INDENT appears, setting check_equal is wrong, and will 
411+                     # be undone when we see the INDENT. 
412+                     check_equal  =  True 
413+                     self ._check_line_ending (string , line_num )
414+                 case  tokenize .INDENT :
435415                    check_equal  =  False 
436-                     self .check_indent_level (line , indents [- 1 ], line_num )
416+                     self .check_indent_level (string , indents [- 1 ] +  1 , line_num )
417+                     indents .append (indents [- 1 ] +  1 )
418+                 case  tokenize .DEDENT :
419+                     # there's nothing we need to check here!  what's important is 
420+                     # that when the run of DEDENTs ends, the indentation of the 
421+                     # program statement (or ENDMARKER) that triggered the run is 
422+                     # equal to what's left at the top of the indents stack 
423+                     check_equal  =  True 
424+                     if  len (indents ) >  1 :
425+                         del  indents [- 1 ]
426+                 case  tokenize .NL :
427+                     if  not  line .strip ("\r \n " ):
428+                         last_blank_line_num  =  line_num 
429+                 case  tokenize .COMMENT  |  tokenize .ENCODING :
430+                     pass 
431+                 case  _:
432+                     # This is the first concrete token following a NEWLINE, so it 
433+                     # must be the first token of the next program statement, or an 
434+                     # ENDMARKER; the "line" argument exposes the leading white-space 
435+                     # for this statement; in the case of ENDMARKER, line is an empty 
436+                     # string, so will properly match the empty string with which the 
437+                     # "indents" stack was seeded 
438+                     if  check_equal :
439+                         check_equal  =  False 
440+                         self .check_indent_level (line , indents [- 1 ], line_num )
437441
438442            if  tok_type  ==  tokenize .NUMBER  and  string .endswith ("l" ):
439443                self .add_message ("lowercase-l-suffix" , line = line_num )
@@ -550,30 +554,26 @@ def _infer_else_finally_line_number(
550554
551555    def  _check_multi_statement_line (self , node : nodes .NodeNG , line : int ) ->  None :
552556        """Check for lines containing multiple statements.""" 
553-         if  isinstance (node , nodes .With ):
554-             # Do not warn about multiple nested context managers in with statements. 
555-             return 
556-         if  (
557-             isinstance (node .parent , nodes .If )
558-             and  not  node .parent .orelse 
559-             and  self .linter .config .single_line_if_stmt 
560-         ):
561-             return 
562-         if  (
563-             isinstance (node .parent , nodes .ClassDef )
564-             and  len (node .parent .body ) ==  1 
565-             and  self .linter .config .single_line_class_stmt 
566-         ):
567-             return 
568- 
569-         # Functions stubs and class with ``Ellipsis`` as body are exempted. 
570-         if  (
571-             isinstance (node , nodes .Expr )
572-             and  isinstance (node .parent , (nodes .FunctionDef , nodes .ClassDef ))
573-             and  isinstance (node .value , nodes .Const )
574-             and  node .value .value  is  Ellipsis 
575-         ):
576-             return 
557+         match  node :
558+             case  nodes .With ():
559+                 # Do not warn about multiple nested context managers in with statements. 
560+                 return 
561+             case  nodes .NodeNG (
562+                 parent = nodes .If (orelse = [])
563+             ) if  self .linter .config .single_line_if_stmt :
564+                 return 
565+             case  nodes .NodeNG (
566+                 parent = nodes .ClassDef (body = [_])
567+             ) if  self .linter .config .single_line_class_stmt :
568+                 return 
569+             case  nodes .Expr (
570+                 parent = nodes .FunctionDef () |  nodes .ClassDef (),
571+                 value = nodes .Const (value = value ),
572+             ) if  (
573+                 value  is  Ellipsis 
574+             ):
575+                 # Functions stubs and class with ``Ellipsis`` as body are exempted. 
576+                 return 
577577
578578        self .add_message ("multiple-statements" , node = node , confidence = HIGH )
579579        self ._visited_lines [line ] =  2 
0 commit comments