Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: flake8-eyeo/flake8_eyeo.py

Issue 29565854: Noissue - Improved accuracy of evaluated expressions for A103 and A207 (Closed)
Patch Set: Changed behavior of A207 Created Oct. 11, 2017, 6:25 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | flake8-eyeo/tests/A103.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # This file is part of Adblock Plus <https://adblockplus.org/>, 1 # This file is part of Adblock Plus <https://adblockplus.org/>,
2 # Copyright (C) 2006-present eyeo GmbH 2 # Copyright (C) 2006-present eyeo GmbH
3 # 3 #
4 # Adblock Plus is free software: you can redistribute it and/or modify 4 # Adblock Plus is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License version 3 as 5 # it under the terms of the GNU General Public License version 3 as
6 # published by the Free Software Foundation. 6 # published by the Free Software Foundation.
7 # 7 #
8 # Adblock Plus is distributed in the hope that it will be useful, 8 # Adblock Plus is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
(...skipping 27 matching lines...) Expand all
38 'codecs.open': 'io.open', 38 'codecs.open': 'io.open',
39 } 39 }
40 40
41 ESSENTIAL_BUILTINS = set(dir(builtins)) - {'apply', 'buffer', 'coerce', 41 ESSENTIAL_BUILTINS = set(dir(builtins)) - {'apply', 'buffer', 'coerce',
42 'intern', 'file'} 42 'intern', 'file'}
43 43
44 LEAVE_BLOCK = (ast.Return, ast.Raise, ast.Continue, ast.Break) 44 LEAVE_BLOCK = (ast.Return, ast.Raise, ast.Continue, ast.Break)
45 VOLATILE = object() 45 VOLATILE = object()
46 46
47 47
48 def evaluate(node): 48 def evaluate(node, namespace):
49 try: 49 try:
50 return eval(compile(ast.Expression(node), '', 'eval'), {}) 50 return eval(compile(ast.Expression(node), '', 'eval'), namespace)
51 except Exception: 51 except Exception:
52 return VOLATILE 52 return VOLATILE
53 53
54 54
55 def is_const(node): 55 def is_const(node):
56 return evaluate(node) is not VOLATILE 56 namespace = {'__builtins__': {'True': True, 'False': False, 'None': None}}
57 return evaluate(node, namespace) is not VOLATILE
57 58
58 59
59 def get_identifier(node): 60 def get_identifier(node):
60 if isinstance(node, ast.Name): 61 if isinstance(node, ast.Name):
61 return node.id 62 return node.id
62 if isinstance(node, ast.Attribute) and isinstance(node.value, ast.Name): 63 if isinstance(node, ast.Attribute) and isinstance(node.value, ast.Name):
63 return '{}.{}'.format(node.value.id, node.attr) 64 return '{}.{}'.format(node.value.id, node.attr)
64 65
65 66
66 def get_statement(node): 67 def get_statement(node):
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 left_is_target = (isinstance(target, ast.Name) and 329 left_is_target = (isinstance(target, ast.Name) and
329 isinstance(node.value.left, ast.Name) and 330 isinstance(node.value.left, ast.Name) and
330 target.id == node.value.left.id) 331 target.id == node.value.left.id)
331 if left_is_target: 332 if left_is_target:
332 self.errors.append((node, 'A106 use augment assignment, ' 333 self.errors.append((node, 'A106 use augment assignment, '
333 'e.g. x += y instead x = x + y')) 334 'e.g. x += y instead x = x + y'))
334 self.generic_visit(node) 335 self.generic_visit(node)
335 336
336 def _visit_hash_keys(self, nodes, what): 337 def _visit_hash_keys(self, nodes, what):
337 keys = [] 338 keys = []
339 namespace = collections.defaultdict(object, vars(builtins))
Vasily Kuznetsov 2017/10/11 19:29:02 This is clever!
338 for node in nodes: 340 for node in nodes:
339 key = evaluate(node) 341 key = evaluate(node, namespace)
340 if key is VOLATILE: 342 if key is VOLATILE:
341 continue 343 continue
342 344
343 if key in keys: 345 if key in keys:
344 self.errors.append((node, 'A207 duplicate ' + what)) 346 self.errors.append((node, 'A207 duplicate ' + what))
345 continue 347 continue
346 348
347 keys.append(key) 349 keys.append(key)
348 350
349 def visit_Dict(self, node): 351 def visit_Dict(self, node):
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 return [(pos, 'A111 redundant parenthesis for {} ' 466 return [(pos, 'A111 redundant parenthesis for {} '
465 'statement'.format(statement))] 467 'statement'.format(statement))]
466 468
467 return [] 469 return []
468 470
469 471
470 for checker in [check_ast, check_non_default_encoding, 472 for checker in [check_ast, check_non_default_encoding,
471 check_quotes, check_redundant_parenthesis]: 473 check_quotes, check_redundant_parenthesis]:
472 checker.name = 'eyeo' 474 checker.name = 'eyeo'
473 checker.version = __version__ 475 checker.version = __version__
OLDNEW
« no previous file with comments | « no previous file | flake8-eyeo/tests/A103.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld