pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python/cpython/commit/012c498035a9adfe9fd218907db1550ecb057f77

faa60c69660fa.css" /> gh-142037: Improve error messages for printf-style formatting (GH-142… · python/cpython@012c498 · GitHub
Skip to content

Commit 012c498

Browse files
gh-142037: Improve error messages for printf-style formatting (GH-142081)
This affects string formatting as well as bytes and bytearray 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 formatted argument. * Suggest more probable causes of errors in the format string (stray %, unsupported format, unexpected character). * Provide more information when the number of arguments does not match the number of format units. * Raise more specific errors when access of arguments by name is mixed with sequential access and when * is used with a mapping. * Add tests for some uncovered cases.
1 parent 5f736a0 commit 012c498

7 files changed

Lines changed: 591 additions & 207 deletions

File tree

Lib/test/test_bytes.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -792,16 +792,16 @@ def __int__(self):
792792
pi = PseudoFloat(3.1415)
793793

794794
exceptions_params = [
795-
('%x format: an integer is required, not float', b'%x', 3.14),
796-
('%X format: an integer is required, not float', b'%X', 2.11),
797-
('%o format: an integer is required, not float', b'%o', 1.79),
798-
('%x format: an integer is required, not PseudoFloat', b'%x', pi),
799-
('%x format: an integer is required, not complex', b'%x', 3j),
800-
('%X format: an integer is required, not complex', b'%X', 2j),
801-
('%o format: an integer is required, not complex', b'%o', 1j),
802-
('%u format: a real number is required, not complex', b'%u', 3j),
803-
('%i format: a real number is required, not complex', b'%i', 2j),
804-
('%d format: a real number is required, not complex', b'%d', 2j),
795+
('%x requires an integer, not float', b'%x', 3.14),
796+
('%X requires an integer, not float', b'%X', 2.11),
797+
('%o requires an integer, not float', b'%o', 1.79),
798+
(r'%x requires an integer, not .*\.PseudoFloat', b'%x', pi),
799+
('%x requires an integer, not complex', b'%x', 3j),
800+
('%X requires an integer, not complex', b'%X', 2j),
801+
('%o requires an integer, not complex', b'%o', 1j),
802+
('%u requires a real number, not complex', b'%u', 3j),
803+
('%i requires a real number, not complex', b'%i', 2j),
804+
('%d requires a real number, not complex', b'%d', 2j),
805805
(
806806
r'%c requires an integer in range\(256\)'
807807
r' or a single byte, not .*\.PseudoFloat',
@@ -810,7 +810,7 @@ def __int__(self):
810810
]
811811

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

816816
def test_memory_leak_gh_140939(self):

Lib/test/test_format.py

Lines changed: 197 additions & 42 deletions
Large diffs are not rendered by default.

Lib/test/test_peepholer.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -733,22 +733,27 @@ def test_format_errors(self):
733733
with self.assertRaisesRegex(TypeError,
734734
'not all arguments converted during string formatting'):
735735
eval("'%s' % (x, y)", {'x': 1, 'y': 2})
736-
with self.assertRaisesRegex(ValueError, 'incomplete format'):
736+
with self.assertRaisesRegex(ValueError, 'stray % at position 2'):
737737
eval("'%s%' % (x,)", {'x': 1234})
738-
with self.assertRaisesRegex(ValueError, 'incomplete format'):
738+
with self.assertRaisesRegex(ValueError, 'stray % at position 4'):
739739
eval("'%s%%%' % (x,)", {'x': 1234})
740740
with self.assertRaisesRegex(TypeError,
741741
'not enough arguments for format string'):
742742
eval("'%s%z' % (x,)", {'x': 1234})
743-
with self.assertRaisesRegex(ValueError, 'unsupported format character'):
743+
with self.assertRaisesRegex(ValueError,
744+
'unsupported format %z at position 2'):
744745
eval("'%s%z' % (x, 5)", {'x': 1234})
745-
with self.assertRaisesRegex(TypeError, 'a real number is required, not str'):
746+
with self.assertRaisesRegex(TypeError,
747+
'format argument 1: %d requires a real number, not str'):
746748
eval("'%d' % (x,)", {'x': '1234'})
747-
with self.assertRaisesRegex(TypeError, 'an integer is required, not float'):
749+
with self.assertRaisesRegex(TypeError,
750+
'format argument 1: %x requires an integer, not float'):
748751
eval("'%x' % (x,)", {'x': 1234.56})
749-
with self.assertRaisesRegex(TypeError, 'an integer is required, not str'):
752+
with self.assertRaisesRegex(TypeError,
753+
'format argument 1: %x requires an integer, not str'):
750754
eval("'%x' % (x,)", {'x': '1234'})
751-
with self.assertRaisesRegex(TypeError, 'must be real number, not str'):
755+
with self.assertRaisesRegex(TypeError,
756+
'format argument 1: %f requires a real number, not str'):
752757
eval("'%f' % (x,)", {'x': '1234'})
753758
with self.assertRaisesRegex(TypeError,
754759
'not enough arguments for format string'):

Lib/test/test_str.py

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,17 +1578,40 @@ def __int__(self):
15781578
self.assertEqual('%X' % letter_m, '6D')
15791579
self.assertEqual('%o' % letter_m, '155')
15801580
self.assertEqual('%c' % letter_m, 'm')
1581-
self.assertRaisesRegex(TypeError, '%x format: an integer is required, not float', operator.mod, '%x', 3.14)
1582-
self.assertRaisesRegex(TypeError, '%X format: an integer is required, not float', operator.mod, '%X', 2.11)
1583-
self.assertRaisesRegex(TypeError, '%o format: an integer is required, not float', operator.mod, '%o', 1.79)
1584-
self.assertRaisesRegex(TypeError, '%x format: an integer is required, not PseudoFloat', operator.mod, '%x', pi)
1585-
self.assertRaisesRegex(TypeError, '%x format: an integer is required, not complex', operator.mod, '%x', 3j)
1586-
self.assertRaisesRegex(TypeError, '%X format: an integer is required, not complex', operator.mod, '%X', 2j)
1587-
self.assertRaisesRegex(TypeError, '%o format: an integer is required, not complex', operator.mod, '%o', 1j)
1588-
self.assertRaisesRegex(TypeError, '%u format: a real number is required, not complex', operator.mod, '%u', 3j)
1589-
self.assertRaisesRegex(TypeError, '%i format: a real number is required, not complex', operator.mod, '%i', 2j)
1590-
self.assertRaisesRegex(TypeError, '%d format: a real number is required, not complex', operator.mod, '%d', 1j)
1591-
self.assertRaisesRegex(TypeError, r'%c requires an int or a unicode character, not .*\.PseudoFloat', operator.mod, '%c', pi)
1581+
with self.assertRaisesRegex(TypeError,
1582+
'format argument: %x requires an integer, not float'):
1583+
'%x' % 3.14
1584+
with self.assertRaisesRegex(TypeError,
1585+
'format argument: %X requires an integer, not float'):
1586+
'%X' % 2.11
1587+
with self.assertRaisesRegex(TypeError,
1588+
'format argument: %o requires an integer, not float'):
1589+
'%o' % 1.79
1590+
with self.assertRaisesRegex(TypeError,
1591+
r'format argument: %x requires an integer, not .*\.PseudoFloat'):
1592+
'%x' % pi
1593+
with self.assertRaisesRegex(TypeError,
1594+
'format argument: %x requires an integer, not complex'):
1595+
'%x' % 3j
1596+
with self.assertRaisesRegex(TypeError,
1597+
'format argument: %X requires an integer, not complex'):
1598+
'%X' % 2j
1599+
with self.assertRaisesRegex(TypeError,
1600+
'format argument: %o requires an integer, not complex'):
1601+
'%o' % 1j
1602+
with self.assertRaisesRegex(TypeError,
1603+
'format argument: %u requires a real number, not complex'):
1604+
'%u' % 3j
1605+
with self.assertRaisesRegex(TypeError,
1606+
'format argument: %i requires a real number, not complex'):
1607+
'%i' % 2j
1608+
with self.assertRaisesRegex(TypeError,
1609+
'format argument: %d requires a real number, not complex'):
1610+
'%d' % 1j
1611+
with self.assertRaisesRegex(TypeError,
1612+
r'format argument: %c requires an integer or a unicode character, '
1613+
r'not .*\.PseudoFloat'):
1614+
'%c' % pi
15921615

15931616
class RaisingNumber:
15941617
def __int__(self):
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Improve error messages for printf-style formatting.
2+
For errors in the format string, always include the position of the
3+
start of the format unit.
4+
For errors related to the formatted arguments, always include the number
5+
or the name of the argument.
6+
Raise more specific errors and include more information (type and number
7+
of arguments, most probable causes of error).

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy