[2.7] bpo-25794: Fix `type.__setattr__()` for non-interned or unicode attribute names. (GH-1652) (#1675)
Based on patch by Eryk Sun.
(cherry picked from commit d896985bb2de49046f9b6879e906d1e4db255e23)
diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py
index e5cdf08..5cd138d 100644
--- a/Lib/test/test_class.py
+++ b/Lib/test/test_class.py
@@ -635,6 +635,49 @@
self.assertRaises(TypeError, type(c).__getattribute__, c, [])
self.assertRaises(TypeError, type(c).__setattr__, c, [], [])
+ def testSetattrWrapperNameIntern(self):
+ # Issue #25794: __setattr__ should intern the attribute name
+ class A(object):
+ pass
+
+ def add(self, other):
+ return 'summa'
+
+ name = ''.join(list('__add__')) # shouldn't be optimized
+ self.assertIsNot(name, '__add__') # not interned
+ type.__setattr__(A, name, add)
+ self.assertEqual(A() + 1, 'summa')
+
+ name2 = ''.join(list('__add__'))
+ self.assertIsNot(name2, '__add__')
+ self.assertIsNot(name2, name)
+ type.__delattr__(A, name2)
+ with self.assertRaises(TypeError):
+ A() + 1
+
+ @test_support.requires_unicode
+ def testSetattrWrapperNameUnicode(self):
+ # Issue #25794: __setattr__ should intern the attribute name
+ class A(object):
+ pass
+
+ def add(self, other):
+ return 'summa'
+
+ type.__setattr__(A, u'__add__', add)
+ self.assertEqual(A() + 1, 'summa')
+
+ type.__delattr__(A, u'__add__')
+ with self.assertRaises(TypeError):
+ A() + 1
+
+ def testSetattrNonStringName(self):
+ class A(object):
+ pass
+
+ with self.assertRaises(TypeError):
+ type.__setattr__(A, bytearray(b'x'), None)
+
def test_main():
with test_support.check_py3k_warnings(
(".+__(get|set|del)slice__ has been removed", DeprecationWarning),