@@ -4178,6 +4178,104 @@ def __dir__(self):
41784178 actual = self .get_suggestion (A (), 'blech' )
41794179 self .assertNotIn ("Did you mean" , actual )
41804180
4181+ def test_delattr_suggestions (self ):
4182+ class Substitution :
4183+ noise = more_noise = a = bc = None
4184+ blech = None
4185+
4186+ class Elimination :
4187+ noise = more_noise = a = bc = None
4188+ blch = None
4189+
4190+ class Addition :
4191+ noise = more_noise = a = bc = None
4192+ bluchin = None
4193+
4194+ class SubstitutionOverElimination :
4195+ blach = None
4196+ bluc = None
4197+
4198+ class SubstitutionOverAddition :
4199+ blach = None
4200+ bluchi = None
4201+
4202+ class EliminationOverAddition :
4203+ blucha = None
4204+ bluc = None
4205+
4206+ class CaseChangeOverSubstitution :
4207+ Luch = None
4208+ fluch = None
4209+ BLuch = None
4210+
4211+ for cls , suggestion in [
4212+ (Addition , "'bluchin'?" ),
4213+ (Substitution , "'blech'?" ),
4214+ (Elimination , "'blch'?" ),
4215+ (Addition , "'bluchin'?" ),
4216+ (SubstitutionOverElimination , "'blach'?" ),
4217+ (SubstitutionOverAddition , "'blach'?" ),
4218+ (EliminationOverAddition , "'bluc'?" ),
4219+ (CaseChangeOverSubstitution , "'BLuch'?" ),
4220+ ]:
4221+ obj = cls ()
4222+ def callable ():
4223+ delattr (obj , 'bluch' )
4224+ actual = self .get_suggestion (callable )
4225+ self .assertIn (suggestion , actual )
4226+
4227+ def test_delattr_suggestions_underscored (self ):
4228+ class A :
4229+ bluch = None
4230+
4231+ obj = A ()
4232+ self .assertIn ("'bluch'" , self .get_suggestion (lambda : delattr (obj , 'blach' )))
4233+ self .assertIn ("'bluch'" , self .get_suggestion (lambda : delattr (obj , '_luch' )))
4234+ self .assertIn ("'bluch'" , self .get_suggestion (lambda : delattr (obj , '_bluch' )))
4235+
4236+ class B :
4237+ _bluch = None
4238+
4239+ obj = B ()
4240+ self .assertIn ("'_bluch'" , self .get_suggestion (lambda : delattr (obj , '_blach' )))
4241+ self .assertIn ("'_bluch'" , self .get_suggestion (lambda : delattr (obj , '_luch' )))
4242+ self .assertNotIn ("'_bluch'" , self .get_suggestion (lambda : delattr (obj , 'bluch' )))
4243+
4244+ def test_delattr_suggestions_do_not_trigger_for_long_attributes (self ):
4245+ class A :
4246+ blech = None
4247+
4248+ obj = A ()
4249+ actual = self .get_suggestion (lambda : delattr (obj , 'somethingverywrong' ))
4250+ self .assertNotIn ("blech" , actual )
4251+
4252+ def test_delattr_error_bad_suggestions_do_not_trigger_for_small_names (self ):
4253+ class MyClass :
4254+ vvv = mom = w = id = pytho = None
4255+
4256+ obj = MyClass ()
4257+ for name in ("b" , "v" , "m" , "py" ):
4258+ with self .subTest (name = name ):
4259+ actual = self .get_suggestion (lambda : delattr (obj , name ))
4260+ self .assertNotIn ("Did you mean" , actual )
4261+ self .assertNotIn ("'vvv" , actual )
4262+ self .assertNotIn ("'mom'" , actual )
4263+ self .assertNotIn ("'id'" , actual )
4264+ self .assertNotIn ("'w'" , actual )
4265+ self .assertNotIn ("'pytho'" , actual )
4266+
4267+ def test_delattr_suggestions_do_not_trigger_for_big_dicts (self ):
4268+ class A :
4269+ blech = None
4270+ # A class with a very big __dict__ will not be considered
4271+ # for suggestions.
4272+ obj = A ()
4273+ for index in range (2000 ):
4274+ setattr (obj , f"index_{ index } " , None )
4275+
4276+ actual = self .get_suggestion (lambda : delattr (obj , 'bluch' ))
4277+ self .assertNotIn ("blech" , actual )
4278+
41814279 def test_attribute_error_with_failing_dict (self ):
41824280 class T :
41834281 bluch = 1
0 commit comments