@@ -167,9 +167,14 @@ def test_lookup_on_object(self):
167167 self .assertEqual (get_attr_safe (b , "a" ), "a" )
168168 self .assertEqual (get_attr_safe (b , "b" ), "b" )
169169
170+ self .assertEqual (has_attr_safe (b , "y" ), True )
171+ self .assertEqual (has_attr_safe (b , "b" ), True )
172+
173+
170174 def test_avoid_running_properties (self ):
171175 p = Property ()
172176 self .assertEqual (get_attr_safe (p , "prop" ), Property .prop )
177+ self .assertEqual (has_attr_safe (p , "prop" ), True )
173178
174179 def test_lookup_with_slots (self ):
175180 s = Slots ()
@@ -178,6 +183,8 @@ def test_lookup_with_slots(self):
178183 with self .assertRaises (AttributeError ):
179184 get_attr_safe (s , "s2" )
180185
186+ self .assertEqual (has_attr_safe (s , "s2" ), False )
187+
181188 def test_lookup_on_slots_classes (self ):
182189 sga = get_attr_safe
183190 s = SlotsSubclass ()
@@ -186,6 +193,9 @@ def test_lookup_on_slots_classes(self):
186193 self .assertIsInstance (sga (SlotsSubclass , "s4" ), property )
187194 self .assertIsInstance (sga (s , "s4" ), property )
188195
196+ self .assertEqual (has_attr_safe (s , "s1" ), True )
197+ self .assertEqual (has_attr_safe (s , "s4" ), True )
198+
189199 @unittest .skipIf (py3 , "Py 3 doesn't allow slots and prop in same class" )
190200 def test_lookup_with_property_and_slots (self ):
191201 sga = get_attr_safe
@@ -206,6 +216,12 @@ def test_lookup_on_overridden_methods(self):
206216 with self .assertRaises (AttributeError ):
207217 sga (OverriddenMRO (), "b" )
208218
219+ self .assertEqual (has_attr_safe (OverriddenGetattr (), "b" ), False )
220+ self .assertEqual (has_attr_safe (OverriddenGetattribute (), "b" ), False )
221+ self .assertEqual (has_attr_safe (OverriddenMRO (), "b" ), False )
222+
223+
224+
209225
210226if __name__ == "__main__" :
211227 unittest .main ()
0 commit comments