@@ -538,35 +538,58 @@ def _check_superfluous_else_continue(self, node):
538
538
node , msg_id = "no-else-continue" , returning_node_class = astroid .Continue
539
539
)
540
540
541
- def _check_consider_get (self , node ):
542
- def type_and_name_are_equal (node_a , node_b ):
543
- for _type in [astroid .Name , astroid .AssignName ]:
544
- if all (isinstance (_node , _type ) for _node in [node_a , node_b ]):
545
- return node_a .name == node_b .name
546
- if all (isinstance (_node , astroid .Const ) for _node in [node_a , node_b ]):
547
- return node_a .value == node_b .value
541
+ @staticmethod
542
+ def _type_and_name_are_equal (node_a , node_b ):
543
+ for _type in [astroid .Name , astroid .AssignName ]:
544
+ if all (isinstance (_node , _type ) for _node in [node_a , node_b ]):
545
+ return node_a .name == node_b .name
546
+ if all (isinstance (_node , astroid .Const ) for _node in [node_a , node_b ]):
547
+ return node_a .value == node_b .value
548
+ return False
549
+
550
+ def _is_dict_get_block (self , node ):
551
+
552
+ # "if <compare node>"
553
+ if not isinstance (node .test , astroid .Compare ):
554
+ return False
555
+
556
+ # Does not have a single statement in the guard's body
557
+ if len (node .body ) != 1 :
548
558
return False
549
559
550
- if_block_ok = (
551
- isinstance (node .test , astroid .Compare )
552
- and len (node .body ) == 1
553
- and isinstance (node .body [0 ], astroid .Assign )
554
- and isinstance (node .body [0 ].value , astroid .Subscript )
555
- and type_and_name_are_equal (node .body [0 ].value .value , node .test .ops [0 ][1 ])
556
- and isinstance (node .body [0 ].value .slice , astroid .Index )
557
- and type_and_name_are_equal (node .body [0 ].value .slice .value , node .test .left )
560
+ # Look for a single variable assignment on the LHS and a subscript on RHS
561
+ stmt = node .body [0 ]
562
+ if not (
563
+ isinstance (stmt , astroid .Assign )
558
564
and len (node .body [0 ].targets ) == 1
559
565
and isinstance (node .body [0 ].targets [0 ], astroid .AssignName )
560
- and isinstance (utils .safe_infer (node .test .ops [0 ][1 ]), astroid .Dict )
561
- )
566
+ and isinstance (stmt .value , astroid .Subscript )
567
+ ):
568
+ return False
562
569
570
+ # The subscript's slice needs to be the same as the test variable.
571
+ # Python 3.9 we no longer have the `Index` node.
572
+ slice_value = stmt .value .slice
573
+ if isinstance (slice_value , astroid .Index ):
574
+ slice_value = slice_value .value
575
+ if not (
576
+ self ._type_and_name_are_equal (stmt .value .value , node .test .ops [0 ][1 ])
577
+ and self ._type_and_name_are_equal (slice_value , node .test .left )
578
+ ):
579
+ return False
580
+
581
+ # The object needs to be a dictionary instance
582
+ return isinstance (utils .safe_infer (node .test .ops [0 ][1 ]), astroid .Dict )
583
+
584
+ def _check_consider_get (self , node ):
585
+ if_block_ok = self ._is_dict_get_block (node )
563
586
if if_block_ok and not node .orelse :
564
587
self .add_message ("consider-using-get" , node = node )
565
588
elif (
566
589
if_block_ok
567
590
and len (node .orelse ) == 1
568
591
and isinstance (node .orelse [0 ], astroid .Assign )
569
- and type_and_name_are_equal (
592
+ and self . _type_and_name_are_equal (
570
593
node .orelse [0 ].targets [0 ], node .body [0 ].targets [0 ]
571
594
)
572
595
and len (node .orelse [0 ].targets ) == 1
0 commit comments