pylint/checkers/utils.py
def parse_format_string(
    format_string: str
) -> Tuple[Set[str], int, Dict[str, str], List[str]]:
    """Parses a format string, returning a tuple of (keys, num_args), where keys
    is the set of mapping keys in the format string, and num_args is the number
    of arguments required by the format string.  Raises
    IncompleteFormatString or UnsupportedFormatCharacter if a
    parse error occurs."""
    keys = set()
    key_types = dict()
    pos_types = []
    num_args = 0

    def next_char(i):
        i += 1
        if i == len(format_string):
            raise IncompleteFormatString
        return (i, format_string[i])

    i = 0
    while i < len(format_string):
        char = format_string[i]
        if char == "%":
            i, char = next_char(i)
            # Parse the mapping key (optional).
            key = None
            if char == "(":
                depth = 1
                i, char = next_char(i)
                key_start = i
                while depth != 0:
                    if char == "(":
                        depth += 1
                    elif char == ")":
                        depth -= 1
                    i, char = next_char(i)
                key_end = i - 1
                key = format_string[key_start:key_end]

            # Parse the conversion flags (optional).
            while char in "#0- +":
                i, char = next_char(i)
            # Parse the minimum field width (optional).
            if char == "*":
                num_args += 1
                i, char = next_char(i)
            else:
                while char in string.digits:
                    i, char = next_char(i)
            # Parse the precision (optional).
            if char == ".":
                i, char = next_char(i)
                if char == "*":
                    num_args += 1
                    i, char = next_char(i)
                else:
                    while char in string.digits:
                        i, char = next_char(i)
            # Parse the length modifier (optional).
            if char in "hlL":
                i, char = next_char(i)
            # Parse the conversion type (mandatory).
            if PY3K:
                flags = "diouxXeEfFgGcrs%a"
            else:
                flags = "diouxXeEfFgGcrs%"
            if char not in flags:
                raise UnsupportedFormatCharacter(i)
            if key:
                keys.add(key)
                key_types[key] = char
            elif char != "%":
                num_args += 1
                pos_types.append(char)
        i += 1
    return keys, num_args, key_types, pos_types
def parse_format_string(
    format_string: str
) -> Tuple[Set[str], int, Dict[str, str], List[str]]:
    """Parses a format string, returning a tuple of (keys, num_args), where keys
    is the set of mapping keys in the format string, and num_args is the number
    of arguments required by the format string.  Raises
    IncompleteFormatString or UnsupportedFormatCharacter if a
    parse error occurs."""
    keys = set()
    key_types = dict()
    pos_types = []
    num_args = 0

    def next_char(i):
        i += 1
        if i == len(format_string):
            raise IncompleteFormatString
        return (i, format_string[i])

    i = 0
    while i < len(format_string):
        char = format_string[i]
        if char == "%":
            i, char = next_char(i)
            # Parse the mapping key (optional).
            key = None
            if char == "(":
                depth = 1
                i, char = next_char(i)
                key_start = i
                while depth != 0:
                    if char == "(":
                        depth += 1
                    elif char == ")":
                        depth -= 1
                    i, char = next_char(i)
                key_end = i - 1
                key = format_string[key_start:key_end]

            # Parse the conversion flags (optional).
            while char in "#0- +":
                i, char = next_char(i)
            # Parse the minimum field width (optional).
            if char == "*":
                num_args += 1
                i, char = next_char(i)
            else:
                while char in string.digits:
                    i, char = next_char(i)
            # Parse the precision (optional).
            if char == ".":
                i, char = next_char(i)
                if char == "*":
                    num_args += 1
                    i, char = next_char(i)
                else:
                    while char in string.digits:
                        i, char = next_char(i)
            # Parse the length modifier (optional).
            if char in "hlL":
                i, char = next_char(i)
            # Parse the conversion type (mandatory).
            if PY3K:
                flags = "diouxXeEfFgGcrs%a"
            else:
                flags = "diouxXeEfFgGcrs%"
            if char not in flags:
                raise UnsupportedFormatCharacter(i)
            if key:
                keys.add(key)
                key_types[key] = char
            elif char != "%":
                num_args += 1
                pos_types.append(char)
        i += 1
    return keys, num_args, key_types, pos_types
def parse_format_string ( format_string : str ) -> Tuple [ Set [ str ] , int , Dict [ str , str ] , List [ str ] ] : keys = set ( ) key_types = dict ( ) pos_types = [ ] num_args = 0 def next_char ( i ) : i += 1 if i == len ( format_string ) : raise IncompleteFormatString return ( i , format_string [ i ] ) i = 0 while i < len ( format_string ) : char = format_string [ i ] if char == "%" : i , char = next_char ( i ) # Parse the mapping key (optional). key = None if char == "(" : depth = 1 i , char = next_char ( i ) key_start = i while depth != 0 : if char == "(" : depth += 1 elif char == ")" : depth -= 1 i , char = next_char ( i ) key_end = i - 1 key = format_string [ key_start : key_end ] # Parse the conversion flags (optional). while char in "#0- +" : i , char = next_char ( i ) # Parse the minimum field width (optional). if char == "*" : num_args += 1 i , char = next_char ( i ) else : while char in string . digits : i , char = next_char ( i ) # Parse the precision (optional). if char == "." : i , char = next_char ( i ) if char == "*" : num_args += 1 i , char = next_char ( i ) else : while char in string . digits : i , char = next_char ( i ) # Parse the length modifier (optional). if char in "hlL" : i , char = next_char ( i ) # Parse the conversion type (mandatory). if PY3K : flags = "diouxXeEfFgGcrs%a" else : flags = "diouxXeEfFgGcrs%" if char not in flags : raise UnsupportedFormatCharacter ( i ) if key : keys . add ( key ) key_types [ key ] = char elif char != "%" : num_args += 1 pos_types . append ( char ) i += 1 return keys , num_args , key_types , pos_types
Parses a format string, returning a tuple of (keys, num_args), where keys
    is the set of mapping keys in the format string, and num_args is the number
    of arguments required by the format string.  Raises
    IncompleteFormatString or UnsupportedFormatCharacter if a
    parse error occurs.
Parses a format string returning a tuple of ( keys num_args ) where keys is the set of mapping keys in the format string and num_args is the number of arguments required by the format string . Raises IncompleteFormatString or UnsupportedFormatCharacter if a parse error occurs .