This file is indexed.

/usr/share/pyshared/pychecker2/VariableChecks.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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
from pychecker2.Check import Check
from pychecker2.Options import Opt, BoolOpt
from pychecker2.Warning import Warning
from pychecker2.util import *
from pychecker2 import symbols

from compiler import ast, walk

def _is_method(scope):
    return scope.__class__ is symbols.FunctionScope and \
           scope.parent.__class__ is symbols.ClassScope

def _is_self(scope, name):
    return _is_method(scope) and name in scope.node.argnames[:1]

def is_arg_and_defaulted_to_same_name(name, scope):
    if isinstance(scope, symbols.FunctionScope):
        if name in scope.node.argnames and scope.node.defaults:
            # compute default args
            args = scope.node.argnames[:]
            # knock off kwargs
            if scope.node.kwargs:
                args = args[:-1]
            # knock off varags 
            if scope.node.varargs:
                args = args[:-1]
            # take the last args as the defaults
            args = args[-len(scope.node.defaults):]
            try:
                # get the corresponding default arg value
                default = scope.node.defaults[args.index(name)]
                # must be a Name node of the same name
                if isinstance(default, ast.Name) and \
                   default.name == name:
                    return 1
            except ValueError:
                pass
    return None


class ShadowCheck(Check):
    """Use symbol information to check that no scope defines a name
    already known to a parent scope"""

    defineNone = Warning('Report any redefinition of None',
                         'Do not redefine None')
    shadowBuiltins = Warning('Report names that shadow builtins',
                            'Identifier (%s) shadows builtin', 0)
    shadowIdentifier = Warning('Report names already defined in outer scopes',
                               'Identifier (%s) shadows definition in scope %s')
    def check(self, file, unused_checker):
        # warn if any name defined in a scope is defined in a parent scope
        # or even the builtins
        for node, scope in file.not_class_scopes():
            for name in scope.defs:
                if name == 'None':
                    file.warning(scope.defs[name], self.defineNone)
                    continue
                if name in scope.globals:
                    continue
                if is_arg_and_defaulted_to_same_name(name, scope):
                    continue
                if _is_self(scope, name):
                    continue
                if __builtins__.has_key(name):
                    file.warning(scope.defs[name], self.shadowBuiltins, name)
                for p in parents(scope):
                    if p.defs.has_key(name) and \
                       not isinstance(p, symbols.ClassScope):
                        file.warning(scope.defs[name], \
                                     self.shadowIdentifier, name, `p`)

def _str_value(s):
    if type(s) == type(''):
        return eval(s)
    return s


def _empty_function(stmts):
    if not stmts:
        return 1
    stmt = stmts[0]
    # functions which only raise exceptions 
    if isinstance(stmt, ast.Raise):
        return 1
    # functions which do nothing 
    if len(stmts) == 1 and isinstance(stmt, ast.Pass):
        return 1
    # functions which just return a constant 
    if len(stmts) == 1 and \
       isinstance(stmt, ast.Return) and isinstance(stmt.value, ast.Const):
        return 1
    # functions which only assert falsehood 
    if isinstance(stmt, ast.Assert):
        if (isinstance(stmt.test, ast.Const) and not stmt.test.value) or \
            (isinstance(stmt.test, ast.Name) and stmt.test.name == 'None'):
            return 1
    return 0

class UnusedCheck(Check):
    """Use symbol information to check that no scope defines a name
    not used in this or any child scope"""

    unused = Warning('Report names not used', 'Identifier (%s) not used')

    def __init__(self):
        self.reportUnusedSelf = None
        self.unusedPrefixes = None

    def get_options(self, options):
        desc = 'Ignore unused identifiers that start with these values'
        default = ['unused', 'empty', 'dummy',
                   '__pychecker__', '__all__', '__version__', 'ignored']
        options.add(Opt(self, 'unusedPrefixes', desc, default))
        
        desc = 'Ignore unused method "self" parameter'
        options.add(BoolOpt(self, 'reportUnusedSelf', desc))

    def check(self, file, unused_checker):
        self.unusedPrefixes = _str_value(self.unusedPrefixes)

        def used(name, parent_scope):
            if parent_scope.uses.has_key(name):
                return 1
            for c in parent_scope.get_children():
                if used(name, c):
                    return 1
            return 0

        for nodes, scope in file.not_class_scopes():
            if isinstance(nodes, ast.Function):
                if _empty_function(nodes.code.nodes):
                    continue
            
            # ensure that every defined variable is used in some scope
            for var in scope.defs:
                # ignore '_'... just because
                if var == '_':
                    continue

                # check for method self
                if not self.reportUnusedSelf and _is_self(scope, var):
                    continue

                # ignore names in the root scope which are not imported:
                # class defs, function defs, variables, etc, unless
                # they start with '_'
                if scope == file.root_scope:
                    if not scope.imports.has_key(var):
                        if not var.startswith('_'):
                            continue

                for prefix in self.unusedPrefixes:
                    if var.startswith(prefix):
                        break
                else:
                    if not used(var, scope) and not scope.globals.has_key(var):
                        file.warning(scope.defs[var], self.unused, var)

def _importedName(scope, name):
    if scope.imports.has_key(name):
        return 1
    if scope.parent:
        return _importedName(scope.parent, name)
    return None

class UnknownCheck(Check):
    """Use symbol information to check that no scope uses a name
    not defined in a parent scope"""

    unknown = Warning('Report names that are not defined',
                      'Unknown identifier: %s')

    builtins = {}
    builtins.update(__builtins__)
    builtins['__builtins__'] = __builtins__
    builtins['WindowsError'] = getattr(__builtins__, 'WindowsError', None)

    def check(self, file, unused_checker):

        # if a name used is not found in the defined variables, complain
        for scope in file.scopes.values():
            unknown = dict_minus(scope.uses, scope.defs)
            unknown = dict_minus(unknown, self.builtins)
            for var in unknown:
                for p in parents(scope):
                    if p.defs.has_key(var):
                        break
                else:
                    if not _importedName(scope, var):
                        file.warning(scope.uses[var], self.unknown, var)

def _first_arg_defaulted(function_node):
    count = len(function_node.argnames)
    if function_node.varargs:
        count -= 1
    if function_node.kwargs:
        count -= 1
    if count > 0 and len(function_node.defaults) == count:
        return 1
    return None

class SelfCheck(Check):
    'Check for simple self parameter'
    
    selfName = Warning('Report any methods whose first argument is not self',
                       'First argument to method %s (%s) is not in %s')
    selfDefault = Warning('Report a self parameter with a default value',
                          'First argument to method %s (%s) has a default value')
    
    functionSelf = Warning('Report functions (not methods) with '
                           'arguments named "self"',
                           'Argument to function (%s) is "%s"')
    
    missingSelf = Warning('Report methods without "self"',
                          'Method %s is missing self parameter')
    
    def get_options(self, options):
        desc = 'Name of self parameter'
        default = ["self", "this", "s"]
        options.add(Opt(self, 'selfNames', desc, default))

        desc = 'Suspicious self parameters'
        self.selfSuspicious = ["self"]
        options.add(Opt(self, 'selfSuspicious', desc, self.selfSuspicious))

    def check(self, file, unused_checker):
        self.selfNames      = _str_value(self.selfNames)
        self.selfSuspicious = _str_value(self.selfSuspicious)

        for node, scope in file.function_scopes():
            args = node.argnames
            name = getattr(scope.node, 'name', 'lambda')
            if _is_method(scope):
                if not args:
                    file.warning(scope.node, self.missingSelf, name)
                else:
                    if args[0] not in self.selfNames:
                        file.warning(scope.node, self.selfName,
                                     name, args[0], `self.selfNames`)
                    if _first_arg_defaulted(scope.node):
                        file.warning(scope.node, self.selfDefault,
                                     name, args[0])
            else:
                for arg in args:
                    if arg in self.selfSuspicious:
                        file.warning(scope.defs[arg], self.functionSelf,
                                     name, arg)

                

class UnpackCheck(Check):
    'Mark all unpacked variables as used'

    def __init__(self):
        self.unpackedUsed = None

    def get_options(self, options):
        desc = 'Do not treat variables used in tuple assignment as used'
        options.add(BoolOpt(self, 'unpackedUsed', desc, 1))

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

        class Visitor:
            def visitAssTuple(self, node):
                for c in node.getChildNodes():
                    for n in parents(c):
                        try:
                            file.scopes[n].uses[c.name] = node
                            break
                        except (KeyError, AttributeError):
                            pass
            visitAssList = visitAssTuple

        # local args unpacked on the `def' line are used, too
        for scope_node, scope in file.function_scopes():
            for arg in type_filter(scope_node.argnames, tuple):
                for unpacked in ast.flatten(arg):
                    scope.uses[unpacked] = scope.uses.get(unpacked, scope_node)

        if file.root_scope:
            walk(file.root_scope.node, Visitor())

def intersect2(a, b):
    return [i for i in a if i in b]

def intersect(items):
    result = items[0]
    for item in items[1:]:
        result = intersect2(result, item)
    return result

class UsedBeforeSetCheck(Check):

    usedBeforeDefined = \
          Warning('Report variables that may be used before they are defined',
                  'The local %s may be used before defined')

    def check(self, file, unused_checker):
        class Visitor(BaseVisitor):
            def __init__(self, defines = None, uses = None):
                # list of vars defined
                self.defines = []
                # name->node vars used before defined                    
                self.uses = {}
                if defines is not None:
                    self.defines = defines[:]
                if uses is not None:
                    self.uses = uses.copy()
            def visitFunction(self, n):
                self.defines.append(n.name)
                
            visitClass = visitFunction
            visitAssName = visitFunction

            def visitGlobal(self, node):
                for name in node.names:
                    self.defines.append(name)
            
            def visitListComp(self, n):
                # visit qualifiers before expression
                children = ast.flatten_nodes(n.quals) + [n.expr]
                for c in children:
                    self.visit(c)
            
            def visitName(self, n):
                if n.name not in self.defines:
                    self.uses[n.name] = self.uses.get(n.name, n)

            def visitIf(self, n):
                if not n.else_:
                    return
                visits = []
                for test, code in n.tests:
                    visits.append(walk(code, Visitor(self.defines, self.uses)))
                visits.append(walk(n.else_, Visitor(self.defines, self.uses)))
                # compute the intersection of defines
                self.defines = intersect([v.defines for v in visits])
                # compute the union of uses, perserving first occurances
                union = {}
                visits.reverse()
                for v in visits:
                    union.update(v.uses)
                union.update(self.uses)
                self.uses = union
                        
        for node, scope in file.function_scopes():
            predefined = ast.flatten(scope.params) + scope.imports.keys()
            visitor = walk(node.code, Visitor(predefined))
            usedBefore = dict_intersect(visitor.uses, scope.defs)
            for name, use_node in usedBefore.items():
                file.warning(use_node, self.usedBeforeDefined, name)