This file is indexed.

/usr/share/pyshared/pychecker2/FormatStringChecks.py is in pychecker 0.8.19-8.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
from pychecker2.Check import Check
from pychecker2.util import BaseVisitor
from pychecker2.Warning import Warning
from compiler import ast, walk
from types import *
import re

class UnknownError(Exception): pass

def _compute_node(node, recurse):
    if isinstance(node, ast.Add):
        return recurse(node.left) + recurse(node.right)
    elif isinstance(node, ast.Mul):
        return recurse(node.left) * recurse(node.right)
    elif isinstance(node, ast.Sub):
        return recurse(node.left) - recurse(node.right)
    elif isinstance(node, ast.Div):
        return recurse(node.left) / recurse(node.right)
    raise UnknownError

def _compute_constant(node):
    "Compute a simple forms of constant strings from an expression node"
    if isinstance(node, ast.Const):
        return node.value
    return _compute_node(node, _compute_constant)

def _compute_tuple_size(node):
    "Compute the length of simple forms of tuples from an expression node"
    if isinstance(node, ast.Tuple):
        return (None,) * len(node.nodes)
    if isinstance(node, ast.Const):
        return node.value
    if isinstance(node, ast.Backquote):
        return ''
    return _compute_node(node, _compute_tuple_size)

# for details: http://www.python.org/doc/current/lib/typesseq-strings.html
_MOD_AND_TYPE = '([hlL])?([diouxXeEfFgGcrs%])'
_TUP_FORMAT_REGEX = re.compile('%(())?[ #+-]*'
                               '([0-9]*|[*])(|[.](|[*]|[0-9]*))' +
                               _MOD_AND_TYPE)
_DICT_FORMAT_REGEX = re.compile('%([(]([a-zA-Z_]+)[)])?[ #+-]*'
                                '([0-9]*)(|[.](|[0-9]*))' + _MOD_AND_TYPE)

class FormatError(Exception):
    def __init__(self, position):
        Exception.__init__(self)
        self.position = position

def _check_format(s):
    pos = 0
    specs = []
    while 1:
        pos = s.find('%', pos)
        if pos < 0:
            return specs

        match = _TUP_FORMAT_REGEX.search(s, pos)
        if not match or match.start(0) != pos:
            match = _DICT_FORMAT_REGEX.search(s, pos)
            if not match or match.start(0) != pos:
                raise FormatError(pos)

        if match.group(7) != '%':       # ignore "%%"
            specs.append( (match.group(2), match.group(3), match.group(5),
                           match.group(6)) )
        pos = match.end(0)
    return specs

class _GetMod(BaseVisitor):
    def __init__(self):
        self.mods = []
    def visitMod(self, node):
        self.mods.append(node)
        self.visitChildren(node)
    # don't descend into other scopes
    def visitFunction(self, node): pass
    visitClass = visitFunction
    visitLambda = visitFunction

def get_mods(node):
    try:
        return walk(node.code, _GetMod()).mods
    except AttributeError:
        return walk(node.node, _GetMod()).mods

_BAD_FORMAT_MAX = 10
def _bad_format_str(s, pos):
    result = s[pos : pos + _BAD_FORMAT_MAX]
    return result + (len(s) > pos + _BAD_FORMAT_MAX and "..." or "")

class FormatStringCheck(Check):
    "Look for warnings in format strings"

    badFormat = \
              Warning('Report illegal format specifications in format strings',
                      'Bad format specifier at position %d (%s)')
    uselessModifier = \
              Warning('Report unused modifiers for format strings (l, h, L)',
                      'Modifier %s is not necessary')

    mixedFormat = \
              Warning('Report format strings which use both positional '
                      'and named formats',
                      'Cannot mix positional and named formats (%%%s)')
    
    formatCount = \
              Warning('Report positional format string with the wrong '
                      'number of arguments',
                      'Wrong number of arguments supplied for format: '
                      '%d given %d required')
    unknownFormatName = \
              Warning('Report unknown names if locals() or globals() '
                      'are used for format strings',
                      'The name "%s" is not defined in %s')

    badConstant = \
              Warning('Report bad constant expressions for format strings',
                      'Error computing constant: %s')

    def check(self, file, unused_checker):
        if not file.parseTree:
            return

        for scope in file.scopes.values():
            for mod in get_mods(scope.node):
                formats = []
                try:
                    s = _compute_constant(mod.left)
                    formats = _check_format(s)
                except FormatError, detail:
                    file.warning(mod, self.badFormat, detail.position,
                                 _bad_format_str(s, detail.position))
                except TypeError, detail:
                    file.warning(mod, self.badConstant, str(detail))
                except UnknownError:
                    pass
                if not formats:
                    continue

                count = len(formats)
                for name, width, precision, lmodifier in formats:
                    if lmodifier:
                        file.warning(mod, self.uselessModifier, lmodifier)
                    if width == '*':
                        count += 1
                    if precision == '*':
                        count += 1

                names = [f[0] for f in formats if f[0]]
                if len(names) == 0:     # tuple
                    try:
                        t = _compute_tuple_size(mod.right)
                        n = 1
                        if type(t) == TupleType:
                            n = len(t)
                        if n != count:
                            file.warning(mod, self.formatCount, n, count)
                    except UnknownError:
                        pass
                    except TypeError, detail:
                        file.warning(mod, self.badConstant, str(detail))

                elif len(names) == len(formats): # dictionary
                    defines = None
                    if isinstance(mod.right, ast.CallFunc) and \
                       isinstance(mod.right.node, ast.Name):
                        if mod.right.node.name in ['locals', 'vars']:
                            defines = scope.defs
                            uses = scope.uses
                        if mod.right.node.name == 'globals':
                            defines = file.root_scope.defs
                            uses = file.root_scope.uses
                    if defines is not None:
                        for n in names:
                            if not defines.has_key(n):
                                file.warning(mod, self.unknownFormatName,
                                             n, mod.right.node.name)
                            else:
                                uses[n] = uses.get(n, mod)
                else:
                    file.warning(mod, self.mixedFormat, "(%s)" % names[0])