SCR112: format-string-mismatch
String formatting that fails at run time
| Code | SCR112 |
| Name | format-string-mismatch |
| Category | Scripts (SCR) |
| Default severity | error |
| Enabled by default | yes |
| Fix available | no |
| ign-lint equivalent | none |
What it does
Section titled “What it does”Checks string literals formatted with % or .format(...) against their
arguments, with Jython 2.7's rules (verified on Jython):
-
%: unsupported conversion characters (%q, Python 3's%a), a trailing%, a tuple with too many or too few values for the placeholders (*widths count),%(name)swith a tuple or a single value instead of a dict,%(name)skeys missing from a dict literal,%cwith a string literal that is not one character ('%c' % 'ab') or an integer that is negative or beyond Unicode, a numeric conversion (%d %i %o %u %x %X %e %E %f %F %g %G) or a*width with a string, complex number, container orNoneliteral ('%d' % 'ab'). A single non-tuple literal counts as one value. -
str.format: a single{or}, mixing{}and{0}, conversions other than!rand!s, positional fields beyond the arguments given, and keyword fields that are not passed. A numeric field too large for a Javaint({2147483648}) is a keyword field, which only**kwargscan pass. A negative index ({-1}) always fails (ArrayIndexOutOfBoundsException;{-0}is index 0). A format spec whose width or precision is too large for a Javaint({0:2147483648}) fails for a literal argument and with!ror!s(other objects may have their own__format__), and so does one that Jython's parser rejects whatever the value: characters after the type ('{:dd}'.format(1),'{:%Y}'.format(1),'{:.2.2}'.format(1.5)) or a.without digits ('{:5.}'.format(1)). A format spec that the literal argument does not support (checked against Jython on more than five million generated specs and literals): an unknown presentation type ('{:z}'.format(1),'{:d}'.format('a'),'{:s}'.format(1),'{:d}'.format(1.5), any type butsafter!ror!s); for strings (and containers andNone, formatted as theirstr) a sign,#,=alignment (also implied by a0before the width) or,('{:+s}'.format('ab')); for integers a precision with an integer type ('{:.2}'.format(1)), a sign or#withc,,with a type other thand; for floats#,,withn; for complex numbers#, zero padding,=alignment,,withn. -
Unicode (verified on Jython on about 17,000 generated cases): a unicode format string whose format spec holds a character beyond U+00FF (
u'{0:\U0001f980^4}'.format(1), also through a nested field whose literal value has one:ValueError: Cannot create PyString with non-byte value, whatever the argument); a unicode literal with non-ASCII characters made a byte string, by a byte string format ('{}'.format(u'\xe9')) or by!s(UnicodeEncodeError); a byte string with non-ASCII bytes inserted with%sinto a unicode result, because the format string is unicode or a unicode value was inserted with%sor%cbefore it (u'%s' % '\xff','%s %s' % (u'a', '\xff'):UnicodeDecodeError);%cof a number from 256 on into a byte string result ('%c' % 300:OverflowError). Jython formats a byte string with non-ASCII bytes into a unicode format with.format, and inserts it before any unicode value with%; those are not reported.
Only literal format strings (also concatenated with +: ('%s' + '%s') % (1,)) with literal arguments (or literal argument lists) are
checked; anything computed is left alone. *args and
**kwargs count when they are literals (*(1,), **{'a': 1}). Extra
arguments to .format are allowed (Python ignores them).
Why is this bad?
Section titled “Why is this bad?”The expression raises TypeError, ValueError, KeyError,
IndexError, OverflowError or a Unicode error when it runs, typically while building a log message or an
alarm text, where the failure hides the original problem.
Example
Section titled “Example”logger.info("Line %s stopped at %s" % (line,))label = "{} of {}".format(done)Use instead:
logger.info("Line %s stopped at %s" % (line, stopTime))label = "{} of {}".format(done, total)pylint
Section titled “pylint”Corresponds to E1300-E1306 and E1310-E1311/W1303-W1307
(format errors and argument mismatches). In Jython a dict on the right
of % satisfies any number of positional placeholders, so iglint does
not report "%s %s" % {...} as pylint does.
Generated from the rule metadata by iglint generate-docs; iglint rule SCR112 prints the same page in the terminal. Source: docs/rules/SCR112.md.