Skip to content

Commit f74b4b2

Browse files
Fix new type names and new tests.
1 parent 09b15a9 commit f74b4b2

32 files changed

Lines changed: 239 additions & 193 deletions

Lib/_pyrepl/fancycompleter.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from _colorize import ANSIColors, get_colors, get_theme
99
import rlcompleter
1010
import keyword
11+
import re
1112
import types
1213

1314
TYPE_CHECKING = False
@@ -43,6 +44,12 @@ def _color_for_obj(name: str, value: Any, theme: Theme) -> str:
4344

4445
def _color_by_type(t, theme):
4546
typename = t.__name__
47+
if t.__module__ == 'types' and typename.endswith('Type'):
48+
# MethodWrapperType -> method_wrapper
49+
# 1. Remove the "Type" suffix.
50+
# 2. Insert "_" before each upper letter in the middle.
51+
# 3. Convert to lower case.
52+
typename = re.sub(r'(?<!\A)(?=[A-Z])', '_', typename[:-4]).lower()
4653
# this is needed e.g. to turn method-wrapper into method_wrapper,
4754
# because if we want _colorize.FancyCompleter to be "dataclassable"
4855
# our keys need to be valid identifiers.

Lib/json/encoder.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@ def replace(match):
7171
encode_basestring_ascii = (
7272
c_encode_basestring_ascii or py_encode_basestring_ascii)
7373

74+
def _T(obj):
75+
cls = type(obj)
76+
module = cls.__module__
77+
if module in (None, 'builtins', '__main__'):
78+
return cls.__qualname__
79+
return f'{module}.{cls.__qualname__}'
80+
81+
7482
class JSONEncoder(object):
7583
"""Extensible JSON <https://json.org> encoder for Python data structures.
7684
@@ -316,7 +324,7 @@ def _iterencode_list(lst, _current_indent_level):
316324
except GeneratorExit:
317325
raise
318326
except BaseException as exc:
319-
exc.add_note(f'when serializing {type(lst).__name__} item {i}')
327+
exc.add_note(f'when serializing {_T(lst)} item {i}')
320328
raise
321329
if newline_indent is not None:
322330
_current_indent_level -= 1
@@ -403,7 +411,7 @@ def _iterencode_dict(dct, _current_indent_level):
403411
except GeneratorExit:
404412
raise
405413
except BaseException as exc:
406-
exc.add_note(f'when serializing {type(dct).__name__} item {key!r}')
414+
exc.add_note(f'when serializing {_T(dct)} item {key!r}')
407415
raise
408416
if not first and newline_indent is not None:
409417
_current_indent_level -= 1
@@ -443,7 +451,7 @@ def _iterencode(o, _current_indent_level):
443451
except GeneratorExit:
444452
raise
445453
except BaseException as exc:
446-
exc.add_note(f'when serializing {type(o).__name__} object')
454+
exc.add_note(f'when serializing {_T(o)} object')
447455
raise
448456
if markers is not None:
449457
del markers[markerid]

Lib/test/pickletester.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,15 +1340,15 @@ def test_find_class(self):
13401340
r"Can't resolve path 'log\.spam' on module 'math'") as cm:
13411341
unpickler4.find_class('math', 'log.spam')
13421342
self.assertEqual(str(cm.exception.__context__),
1343-
"'builtin_function_or_method' object has no attribute 'spam'")
1343+
"'types.BuiltinFunctionType' object has no attribute 'spam'")
13441344
with self.assertRaisesRegex(AttributeError,
13451345
r"module 'math' has no attribute 'log\.<locals>\.spam'"):
13461346
unpickler.find_class('math', 'log.<locals>.spam')
13471347
with self.assertRaisesRegex(AttributeError,
13481348
r"Can't resolve path 'log\.<locals>\.spam' on module 'math'") as cm:
13491349
unpickler4.find_class('math', 'log.<locals>.spam')
13501350
self.assertEqual(str(cm.exception.__context__),
1351-
"'builtin_function_or_method' object has no attribute '<locals>'")
1351+
"'types.BuiltinFunctionType' object has no attribute '<locals>'")
13521352
with self.assertRaisesRegex(AttributeError,
13531353
"module 'math' has no attribute ''"):
13541354
unpickler.find_class('math', '')
@@ -3301,11 +3301,33 @@ def test_builtin_types(self):
33013301
self.assertIs(self.loads(s), t)
33023302

33033303
def test_types_types(self):
3304+
if self.py_version < (3, 8):
3305+
self.skipTest('not supported in Python < 3.8')
3306+
# types with __module__ == 'types' added before 3.16
3307+
old_names = {
3308+
'EllipsisType': (3, 8),
3309+
'GenericAlias': (3, 9),
3310+
'NoneType': (3, 8),
3311+
'NotImplementedType': (3, 8),
3312+
'SimpleNamespace': (3, 8),
3313+
'Union': (3, 8),
3314+
'DynamicClassAttribute': (3, 8),
3315+
'_GeneratorWrapper': (3, 8),
3316+
}
3317+
# new types added after 3.16
3318+
new_names = {
3319+
}
33043320
for t in types.__dict__.values():
33053321
if isinstance(t, type):
3322+
if self.py_version < (3, 16):
3323+
if t.__name__ not in old_names or self.py_version < old_names[t.__name__]:
3324+
continue
3325+
elif t.__name__ in new_names and self.py_version < new_names[t.__name__]:
3326+
continue
33063327
for proto in protocols:
3307-
s = self.dumps(t, proto)
3308-
self.assertIs(self.loads(s), t)
3328+
with self.subTest(name=t.__name__, proto=proto):
3329+
s = self.dumps(t, proto)
3330+
self.assertIs(self.loads(s), t)
33093331

33103332
def test_builtin_exceptions(self):
33113333
new_names = {

Lib/test/test_call.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -227,29 +227,29 @@ def test_object_not_callable(self):
227227
self.assertRaisesRegex(TypeError, msg, object())
228228

229229
def test_module_not_callable_no_suggestion_0(self):
230-
msg = r"^'module' object is not callable$"
230+
msg = r"^'types\.ModuleType' object is not callable$"
231231
self.assertRaisesRegex(TypeError, msg, types.ModuleType("mod"))
232232

233233
def test_module_not_callable_no_suggestion_1(self):
234-
msg = r"^'module' object is not callable$"
234+
msg = r"^'types\.ModuleType' object is not callable$"
235235
mod = types.ModuleType("mod")
236236
mod.mod = 42
237237
self.assertRaisesRegex(TypeError, msg, mod)
238238

239239
def test_module_not_callable_no_suggestion_2(self):
240-
msg = r"^'module' object is not callable$"
240+
msg = r"^'types\.ModuleType' object is not callable$"
241241
mod = types.ModuleType("mod")
242242
del mod.__name__
243243
self.assertRaisesRegex(TypeError, msg, mod)
244244

245245
def test_module_not_callable_no_suggestion_3(self):
246-
msg = r"^'module' object is not callable$"
246+
msg = r"^'types\.ModuleType' object is not callable$"
247247
mod = types.ModuleType("mod")
248248
mod.__name__ = 42
249249
self.assertRaisesRegex(TypeError, msg, mod)
250250

251251
def test_module_not_callable_suggestion(self):
252-
msg = r"^'module' object is not callable\. Did you mean: 'mod\.mod\(\.\.\.\)'\?$"
252+
msg = r"^'types\.ModuleType' object is not callable\. Did you mean: 'mod\.mod\(\.\.\.\)'\?$"
253253
mod = types.ModuleType("mod")
254254
mod.mod = lambda: ...
255255
self.assertRaisesRegex(TypeError, msg, mod)

Lib/test/test_crossinterp.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ def ignore_byteswarning():
6161

6262
METHOD = defs.SpamOkay().okay
6363
BUILTIN_METHOD = [].append
64+
MEMBER_DESCRIPTOR = types.FunctionType.__globals__
6465
METHOD_DESCRIPTOR_WRAPPER = str.join
6566
METHOD_WRAPPER = object().__str__
6667
WRAPPER_DESCRIPTOR = object.__init__
@@ -69,7 +70,7 @@ def ignore_byteswarning():
6970
BUILTIN_METHOD: types.BuiltinMethodType,
7071
dict.__dict__['fromkeys']: types.ClassMethodDescriptorType,
7172
types.FunctionType.__code__: types.GetSetDescriptorType,
72-
types.FunctionType.__globals__: types.MemberDescriptorType,
73+
MEMBER_DESCRIPTOR: types.MemberDescriptorType,
7374
METHOD_DESCRIPTOR_WRAPPER: types.MethodDescriptorType,
7475
METHOD_WRAPPER: types.MethodWrapperType,
7576
WRAPPER_DESCRIPTOR: types.WrapperDescriptorType,
@@ -278,16 +279,11 @@ def ignore_byteswarning():
278279
*defs.TOP_CLASSES,
279280
*USER_TOP_INSTANCES,
280281
*USER_EXCEPTIONS,
281-
# from OTHER_TYPES
282-
types.NoneType,
283-
types.EllipsisType,
284-
types.NotImplementedType,
285-
types.GenericAlias,
286-
types.UnionType,
287-
types.SimpleNamespace,
282+
*OTHER_TYPES,
288283
# from BUILTIN_WRAPPERS
289284
METHOD,
290285
BUILTIN_METHOD,
286+
MEMBER_DESCRIPTOR,
291287
METHOD_DESCRIPTOR_WRAPPER,
292288
METHOD_WRAPPER,
293289
WRAPPER_DESCRIPTOR,

Lib/test/test_exception_group.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ def __repr__(self):
267267
seq = MySeq(None)
268268
with self.assertRaisesRegex(
269269
TypeError,
270-
r".*MySeq\.__repr__\(\) must return a str, not NoneType"
270+
r".*MySeq\.__repr__\(\) must return a str, not types.NoneType"
271271
):
272272
ExceptionGroup("test", seq)
273273

Lib/test/test_frame.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,7 @@ class ObjectSubclass:
579579
def test_constructor(self):
580580
FrameLocalsProxy = type([sys._getframe().f_locals
581581
for x in range(1)][0])
582-
self.assertEqual(FrameLocalsProxy.__name__, 'FrameLocalsProxy')
582+
self.assertEqual(FrameLocalsProxy.__name__, 'FrameLocalsProxyType')
583583

584584
def make_frame():
585585
x = 1

Lib/test/test_gdb/test_backtrace.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def test_bt(self):
2020
self.assertMultilineMatches(bt,
2121
r'''^.*
2222
Traceback \(most recent call first\):
23-
<built-in method id of module object .*>
23+
<built-in method id of types\.ModuleType object .*>
2424
File ".*gdb_sample.py", line 10, in baz
2525
id\(42\)
2626
File ".*gdb_sample.py", line 7, in bar

Lib/test/test_import/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1262,7 +1262,7 @@ class Spec:
12621262
self.assertIs(_imp.create_builtin(spec), sys)
12631263

12641264
spec.name = None
1265-
with self.assertRaisesRegex(TypeError, 'name must be string, not NoneType'):
1265+
with self.assertRaisesRegex(TypeError, 'name must be string, not types.NoneType'):
12661266
_imp.create_builtin(spec)
12671267

12681268
# gh-142029

Lib/test/test_json/test_default.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ def default(obj):
2121
with self.assertRaises(ValueError) as cm:
2222
self.dumps(type, default=default)
2323
self.assertEqual(cm.exception.__notes__,
24-
['when serializing ellipsis object',
24+
['when serializing types.EllipsisType object',
2525
'when serializing list item 0',
26-
'when serializing module object',
26+
'when serializing types.ModuleType object',
2727
'when serializing type object'])
2828

2929
def test_ordereddict(self):

0 commit comments

Comments
 (0)