blob: 21332f04dbc26f27c35ad136b01f1c0a48c06788 [file] [log] [blame]
"""Test for Python 3 string formatting error"""
# pylint: disable=too-few-public-methods, import-error, unused-argument, line-too-long, no-absolute-import,
# pylint: disable=useless-object-inheritance
import os
import sys
import logging
from missing import Missing
class Custom(object):
""" Has a __getattr__ """
def __getattr__(self, _):
return self
class Test(object):
""" test format attribute access """
custom = Custom()
ids = [1, 2, 3, [4, 5, 6]]
class Getitem(object):
""" test custom getitem for lookup access """
def __getitem__(self, index):
return 42
class ReturnYes(object):
""" can't be properly infered """
missing = Missing()
def log(message, message_type="error"):
""" Test """
return message
def print_good():
""" Good format strings """
"{0} {1}".format(1, 2)
"{0!r:20}".format("Hello")
"{!r:20}".format("Hello")
"{a!r:20}".format(a="Hello")
"{pid}".format(pid=os.getpid())
str("{}").format(2)
"{0.missing.length}".format(ReturnYes())
"{1.missing.length}".format(ReturnYes())
"{a.ids[3][1]}".format(a=Test())
"{a[0][0]}".format(a=[[1]])
"{[0][0]}".format({0: {0: 1}})
"{a.test}".format(a=Custom())
"{a.__len__}".format(a=[])
"{a.ids.__len__}".format(a=Test())
"{a[0]}".format(a=Getitem())
"{a[0][0]}".format(a=[Getitem()])
"{[0][0]}".format(["test"])
# these are skipped
"{0} {1}".format(*[1, 2])
"{a} {b}".format(**{'a': 1, 'b': 2})
"{a}".format(a=Missing())
logging.debug("%s", 42)
logging.debug("%s %s", 42, 43)
def pprint_bad():
"""Test string format """
"{{}}".format(1) # [too-many-format-args]
"{} {".format() # [bad-format-string]
"{} }".format() # [bad-format-string]
"{0} {}".format(1, 2) # [format-combined-specification]
# +1: [missing-format-argument-key, unused-format-string-argument]
"{a} {b}".format(a=1, c=2)
"{} {a}".format(1, 2) # [missing-format-argument-key]
"{} {}".format(1) # [too-few-format-args]
"{} {}".format(1, 2, 3) # [too-many-format-args]
# +1: [missing-format-argument-key,missing-format-argument-key,missing-format-argument-key]
"{a} {b} {c}".format()
"{} {}".format(a=1, b=2) # [too-few-format-args]
# +1: [missing-format-argument-key, missing-format-argument-key]
"{a} {b}".format(1, 2)
"{0} {1} {a}".format(1, 2, 3) # [missing-format-argument-key]
# +1: [missing-format-attribute]
"{a.ids.__len__.length}".format(a=Test())
"{a.ids[3][400]}".format(a=Test()) # [invalid-format-index]
"{a.ids[3]['string']}".format(a=Test()) # [invalid-format-index]
"{[0][1]}".format(["a"]) # [invalid-format-index]
"{[0][0]}".format(((1, ))) # [invalid-format-index]
# +1: [missing-format-argument-key, unused-format-string-argument]
"{b[0]}".format(a=23)
"{a[0]}".format(a=object) # [invalid-format-index]
log("{}".format(2, "info")) # [too-many-format-args]
"{0.missing}".format(2) # [missing-format-attribute]
"{0} {1} {2}".format(1, 2) # [too-few-format-args]
"{0} {1}".format(1, 2, 3) # [too-many-format-args]
"{0} {a}".format(a=4) # [too-few-format-args]
"{[0]} {}".format([4]) # [too-few-format-args]
"{[0]} {}".format([4], 5, 6) # [too-many-format-args]
logging.debug("%s %s", 42) # [logging-too-few-args]
logging.debug("%s", 42, 43) # [logging-too-many-args]
def good_issue288(*args, **kwargs):
""" Test that using kwargs does not emit a false
positive.
"""
'Hello John Doe {0[0]}'.format(args)
'Hello {0[name]}'.format(kwargs)
def good_issue287():
""" Test that the string format checker skips
format nodes which don't have a string as a parent
(but a subscript, name etc).
"""
name = 'qwerty'
ret = {'comment': ''}
ret['comment'] = 'MySQL grant {0} is set to be revoked'
ret['comment'] = ret['comment'].format(name)
return ret, name
def nested_issue294():
""" Test nested format fields. """
'{0:>{1}}'.format(42, 24)
'{0:{a[1]}} {a}'.format(1, a=[1, 2])
'{:>{}}'.format(42, 24)
'{0:>{1}}'.format(42) # [too-few-format-args]
'{0:>{1}}'.format(42, 24, 54) # [too-many-format-args]
'{0:{a[1]}}'.format(1) # [missing-format-argument-key]
'{0:{a.x}}'.format(1, a=2) # [missing-format-attribute]
def issue310():
""" Test a regression using duplicate manual position arguments. """
'{0} {1} {0}'.format(1, 2)
'{0} {1} {0}'.format(1) # [too-few-format-args]
def issue322():
""" Test a regression using mixed manual position arguments
and attribute access arguments.
"""
'{0}{1[FOO]}'.format(123, {'FOO': 456})
'{0}{1[FOO]}'.format(123, {'FOO': 456}, 321) # [too-many-format-args]
'{0}{1[FOO]}'.format(123) # [too-few-format-args]
def issue338():
"""
Check that using a namedtuple subclass doesn't crash when
trying to infer EmptyNodes (resulted after mocking the
members of namedtuples).
"""
from collections import namedtuple # pylint: disable=import-outside-toplevel
class Crash(namedtuple("C", "foo bar")):
""" Looking for attributes in __str__ will crash,
because EmptyNodes can't be infered.
"""
def __str__(self):
return "{0.foo}: {0.bar}".format(self)
return Crash
def issue351():
"""
Check that the format method can be assigned to a variable, ie:
"""
fmt = 'test {} {}'.format
fmt('arg1') # [too-few-format-args]
fmt('arg1', 'arg2')
fmt('arg1', 'arg2', 'arg3') # [too-many-format-args]
def issue373():
"""
Ignore any object coming from an argument.
"""
class SomeClass(object):
""" empty docstring. """
def __init__(self, opts=None):
self.opts = opts
def dunc(self, arg):
"""Don't try to analyze this."""
return "A{0}{1}".format(arg, self.opts)
def func(self):
"""Don't try to analyze the following string."""
return 'AAA{0[iface]}BBB{0[port]}'.format(self.opts)
return SomeClass
def issue_463():
"""
Mix positional arguments, `{0}`, with positional
arguments with attribute access, `{0.__x__}`.
"""
data = "{0.__class__.__name__}: {0}".format(42)
data2 = "{0[0]}: {0}".format([1])
return (data, data2)
def avoid_empty_attribute():
"""The following string is invalid, avoid crashing."""
return "There are {.:2f} undiscovered errors.".format(1) # [bad-format-string]
def invalid_format_index_on_inference_ambiguity():
"""Test inference bug for invalid-format-index"""
if len(sys.argv) > 1:
options = [["Woof!"]]
else:
options = [["Barf!"]]
return 'Why is this bad? {options[0][0]}'.format(options=options)