Skip to content
22 changes: 11 additions & 11 deletions Lib/test/test_bytes.py
Original file line number Diff line number Diff line change
Expand Up @@ -792,16 +792,16 @@ def __int__(self):
pi = PseudoFloat(3.1415)

exceptions_params = [
('%x format: an integer is required, not float', b'%x', 3.14),
('%X format: an integer is required, not float', b'%X', 2.11),
('%o format: an integer is required, not float', b'%o', 1.79),
('%x format: an integer is required, not PseudoFloat', b'%x', pi),
('%x format: an integer is required, not complex', b'%x', 3j),
('%X format: an integer is required, not complex', b'%X', 2j),
('%o format: an integer is required, not complex', b'%o', 1j),
('%u format: a real number is required, not complex', b'%u', 3j),
('%i format: a real number is required, not complex', b'%i', 2j),
('%d format: a real number is required, not complex', b'%d', 2j),
('%x requires an integer, not float', b'%x', 3.14),
('%X requires an integer, not float', b'%X', 2.11),
('%o requires an integer, not float', b'%o', 1.79),
(r'%x requires an integer, not .*\.PseudoFloat', b'%x', pi),
('%x requires an integer, not complex', b'%x', 3j),
('%X requires an integer, not complex', b'%X', 2j),
('%o requires an integer, not complex', b'%o', 1j),
('%u requires a real number, not complex', b'%u', 3j),
('%i requires a real number, not complex', b'%i', 2j),
('%d requires a real number, not complex', b'%d', 2j),
(
r'%c requires an integer in range\(256\)'
r' or a single byte, not .*\.PseudoFloat',
Expand All @@ -810,7 +810,7 @@ def __int__(self):
]

for msg, format_bytes, value in exceptions_params:
with self.assertRaisesRegex(TypeError, msg):
with self.assertRaisesRegex(TypeError, 'format argument: ' + msg):
operator.mod(format_bytes, value)

def test_memory_leak_gh_140939(self):
Expand Down
239 changes: 197 additions & 42 deletions Lib/test/test_format.py

Large diffs are not rendered by default.

19 changes: 12 additions & 7 deletions Lib/test/test_peepholer.py
Original file line number Diff line number Diff line change
Expand Up @@ -733,22 +733,27 @@ def test_format_errors(self):
with self.assertRaisesRegex(TypeError,
'not all arguments converted during string formatting'):
eval("'%s' % (x, y)", {'x': 1, 'y': 2})
with self.assertRaisesRegex(ValueError, 'incomplete format'):
with self.assertRaisesRegex(ValueError, 'stray % at position 2'):
eval("'%s%' % (x,)", {'x': 1234})
with self.assertRaisesRegex(ValueError, 'incomplete format'):
with self.assertRaisesRegex(ValueError, 'stray % at position 4'):
eval("'%s%%%' % (x,)", {'x': 1234})
with self.assertRaisesRegex(TypeError,
'not enough arguments for format string'):
eval("'%s%z' % (x,)", {'x': 1234})
with self.assertRaisesRegex(ValueError, 'unsupported format character'):
with self.assertRaisesRegex(ValueError,
'unsupported format %z at position 2'):
eval("'%s%z' % (x, 5)", {'x': 1234})
with self.assertRaisesRegex(TypeError, 'a real number is required, not str'):
with self.assertRaisesRegex(TypeError,
'format argument 1: %d requires a real number, not str'):
eval("'%d' % (x,)", {'x': '1234'})
with self.assertRaisesRegex(TypeError, 'an integer is required, not float'):
with self.assertRaisesRegex(TypeError,
'format argument 1: %x requires an integer, not float'):
eval("'%x' % (x,)", {'x': 1234.56})
with self.assertRaisesRegex(TypeError, 'an integer is required, not str'):
with self.assertRaisesRegex(TypeError,
'format argument 1: %x requires an integer, not str'):
eval("'%x' % (x,)", {'x': '1234'})
with self.assertRaisesRegex(TypeError, 'must be real number, not str'):
with self.assertRaisesRegex(TypeError,
'format argument 1: %f requires a real number, not str'):
eval("'%f' % (x,)", {'x': '1234'})
with self.assertRaisesRegex(TypeError,
'not enough arguments for format string'):
Expand Down
45 changes: 34 additions & 11 deletions Lib/test/test_str.py
Original file line number Diff line number Diff line change
Expand Up @@ -1578,17 +1578,40 @@ def __int__(self):
self.assertEqual('%X' % letter_m, '6D')
self.assertEqual('%o' % letter_m, '155')
self.assertEqual('%c' % letter_m, 'm')
self.assertRaisesRegex(TypeError, '%x format: an integer is required, not float', operator.mod, '%x', 3.14)
self.assertRaisesRegex(TypeError, '%X format: an integer is required, not float', operator.mod, '%X', 2.11)
self.assertRaisesRegex(TypeError, '%o format: an integer is required, not float', operator.mod, '%o', 1.79)
self.assertRaisesRegex(TypeError, '%x format: an integer is required, not PseudoFloat', operator.mod, '%x', pi)
self.assertRaisesRegex(TypeError, '%x format: an integer is required, not complex', operator.mod, '%x', 3j)
self.assertRaisesRegex(TypeError, '%X format: an integer is required, not complex', operator.mod, '%X', 2j)
self.assertRaisesRegex(TypeError, '%o format: an integer is required, not complex', operator.mod, '%o', 1j)
self.assertRaisesRegex(TypeError, '%u format: a real number is required, not complex', operator.mod, '%u', 3j)
self.assertRaisesRegex(TypeError, '%i format: a real number is required, not complex', operator.mod, '%i', 2j)
self.assertRaisesRegex(TypeError, '%d format: a real number is required, not complex', operator.mod, '%d', 1j)
self.assertRaisesRegex(TypeError, r'%c requires an int or a unicode character, not .*\.PseudoFloat', operator.mod, '%c', pi)
with self.assertRaisesRegex(TypeError,
'format argument: %x requires an integer, not float'):
'%x' % 3.14
with self.assertRaisesRegex(TypeError,
'format argument: %X requires an integer, not float'):
'%X' % 2.11
with self.assertRaisesRegex(TypeError,
'format argument: %o requires an integer, not float'):
'%o' % 1.79
with self.assertRaisesRegex(TypeError,
r'format argument: %x requires an integer, not .*\.PseudoFloat'):
'%x' % pi
with self.assertRaisesRegex(TypeError,
'format argument: %x requires an integer, not complex'):
'%x' % 3j
with self.assertRaisesRegex(TypeError,
'format argument: %X requires an integer, not complex'):
'%X' % 2j
with self.assertRaisesRegex(TypeError,
'format argument: %o requires an integer, not complex'):
'%o' % 1j
with self.assertRaisesRegex(TypeError,
'format argument: %u requires a real number, not complex'):
'%u' % 3j
with self.assertRaisesRegex(TypeError,
'format argument: %i requires a real number, not complex'):
'%i' % 2j
with self.assertRaisesRegex(TypeError,
'format argument: %d requires a real number, not complex'):
'%d' % 1j
with self.assertRaisesRegex(TypeError,
r'format argument: %c requires an integer or a unicode character, '
r'not .*\.PseudoFloat'):
'%c' % pi

class RaisingNumber:
def __int__(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Improve error messages for printf-style formatting.
For errors in the format string, always include the position of the
start of the format unit.
For errors related to the formatted arguments, always include the number
or the name of the argument.
Raise more specific errors and include more information (type and number
of arguments, most probable causes of error).
Loading
Loading