@@ -4120,6 +4120,104 @@ def __dir__(self):
41204120 actual = self .get_suggestion (A (), 'blech' )
41214121 self .assertNotIn ("Did you mean" , actual )
41224122
4123+ def test_delattr_suggestions (self ):
4124+ class Substitution :
4125+ noise = more_noise = a = bc = None
4126+ blech = None
4127+
4128+ class Elimination :
4129+ noise = more_noise = a = bc = None
4130+ blch = None
4131+
4132+ class Addition :
4133+ noise = more_noise = a = bc = None
4134+ bluchin = None
4135+
4136+ class SubstitutionOverElimination :
4137+ blach = None
4138+ bluc = None
4139+
4140+ class SubstitutionOverAddition :
4141+ blach = None
4142+ bluchi = None
4143+
4144+ class EliminationOverAddition :
4145+ blucha = None
4146+ bluc = None
4147+
4148+ class CaseChangeOverSubstitution :
4149+ Luch = None
4150+ fluch = None
4151+ BLuch = None
4152+
4153+ for cls , suggestion in [
4154+ (Addition , "'bluchin'?" ),
4155+ (Substitution , "'blech'?" ),
4156+ (Elimination , "'blch'?" ),
4157+ (Addition , "'bluchin'?" ),
4158+ (SubstitutionOverElimination , "'blach'?" ),
4159+ (SubstitutionOverAddition , "'blach'?" ),
4160+ (EliminationOverAddition , "'bluc'?" ),
4161+ (CaseChangeOverSubstitution , "'BLuch'?" ),
4162+ ]:
4163+ obj = cls ()
4164+ def callable ():
4165+ delattr (obj , 'bluch' )
4166+ actual = self .get_suggestion (callable )
4167+ self .assertIn (suggestion , actual )
4168+
4169+ def test_delattr_suggestions_underscored (self ):
4170+ class A :
4171+ bluch = None
4172+
4173+ obj = A ()
4174+ self .assertIn ("'bluch'" , self .get_suggestion (lambda : delattr (obj , 'blach' )))
4175+ self .assertIn ("'bluch'" , self .get_suggestion (lambda : delattr (obj , '_luch' )))
4176+ self .assertIn ("'bluch'" , self .get_suggestion (lambda : delattr (obj , '_bluch' )))
4177+
4178+ class B :
4179+ _bluch = None
4180+
4181+ obj = B ()
4182+ self .assertIn ("'_bluch'" , self .get_suggestion (lambda : delattr (obj , '_blach' )))
4183+ self .assertIn ("'_bluch'" , self .get_suggestion (lambda : delattr (obj , '_luch' )))
4184+ self .assertNotIn ("'_bluch'" , self .get_suggestion (lambda : delattr (obj , 'bluch' )))
4185+
4186+ def test_delattr_suggestions_do_not_trigger_for_long_attributes (self ):
4187+ class A :
4188+ blech = None
4189+
4190+ obj = A ()
4191+ actual = self .get_suggestion (lambda : delattr (obj , 'somethingverywrong' ))
4192+ self .assertNotIn ("blech" , actual )
4193+
4194+ def test_delattr_error_bad_suggestions_do_not_trigger_for_small_names (self ):
4195+ class MyClass :
4196+ vvv = mom = w = id = pytho = None
4197+
4198+ obj = MyClass ()
4199+ for name in ("b" , "v" , "m" , "py" ):
4200+ with self .subTest (name = name ):
4201+ actual = self .get_suggestion (lambda : delattr (obj , name ))
4202+ self .assertNotIn ("Did you mean" , actual )
4203+ self .assertNotIn ("'vvv" , actual )
4204+ self .assertNotIn ("'mom'" , actual )
4205+ self .assertNotIn ("'id'" , actual )
4206+ self .assertNotIn ("'w'" , actual )
4207+ self .assertNotIn ("'pytho'" , actual )
4208+
4209+ def test_delattr_suggestions_do_not_trigger_for_big_dicts (self ):
4210+ class A :
4211+ blech = None
4212+ # A class with a very big __dict__ will not be considered
4213+ # for suggestions.
4214+ obj = A ()
4215+ for index in range (2000 ):
4216+ setattr (obj , f"index_{ index } " , None )
4217+
4218+ actual = self .get_suggestion (lambda : delattr (obj , 'bluch' ))
4219+ self .assertNotIn ("blech" , actual )
4220+
41234221 def test_attribute_error_with_failing_dict (self ):
41244222 class T :
41254223 bluch = 1
0 commit comments