Skip to content

Commit

Permalink
pythongh-55664: Add warning when creating a type using a namespace di…
Browse files Browse the repository at this point in the history
…ctionary with non-string keys. (pythonGH-105338)

Co-authored-by: Daniel Urban <[email protected]>
  • Loading branch information
furkanonder and durban authored Jan 28, 2024
1 parent 3bb6912 commit f7c05d7
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 1 deletion.
17 changes: 16 additions & 1 deletion Lib/test/test_descr.py
Original file line number Diff line number Diff line change
Expand Up @@ -4734,6 +4734,20 @@ class X(object):
with self.assertRaises(AttributeError):
del X.__abstractmethods__

def test_gh55664(self):
# gh-55664: issue a warning when the
# __dict__ of a class contains non-string keys
with self.assertWarnsRegex(RuntimeWarning, 'MyClass'):
MyClass = type('MyClass', (), {1: 2})

class meta(type):
def __new__(mcls, name, bases, ns):
ns[1] = 2
return super().__new__(mcls, name, bases, ns)

with self.assertWarnsRegex(RuntimeWarning, 'MyClass'):
MyClass = meta('MyClass', (), {})

def test_proxy_call(self):
class FakeStr:
__class__ = str
Expand Down Expand Up @@ -5151,7 +5165,8 @@ class Base2(object):
mykey = 'from Base2'
mykey2 = 'from Base2'

X = type('X', (Base,), {MyKey(): 5})
with self.assertWarnsRegex(RuntimeWarning, 'X'):
X = type('X', (Base,), {MyKey(): 5})
# mykey is read from Base
self.assertEqual(X.mykey, 'from Base')
# mykey2 is read from Base2 because MyKey.__eq__ has set __bases__
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add warning when creating :class:`type` using a namespace dictionary with non-string keys. Patched by Daniel Urban and Furkan Onder.
11 changes: 11 additions & 0 deletions Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -3828,6 +3828,17 @@ type_new_impl(type_new_ctx *ctx)
// Put the proper slots in place
fixup_slot_dispatchers(type);

if (!_PyDict_HasOnlyStringKeys(type->tp_dict)) {
if (PyErr_WarnFormat(
PyExc_RuntimeWarning,
1,
"non-string key in the __dict__ of class %.200s",
type->tp_name) == -1)
{
goto error;
}
}

if (type_new_set_names(type) < 0) {
goto error;
}
Expand Down

0 comments on commit f7c05d7

Please sign in to comment.