Anthony Sottile | 8f61529 | 2022-01-15 19:24:05 -0500 | [diff] [blame] | 1 | from __future__ import annotations |
| 2 | |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 3 | import ast |
| 4 | |
| 5 | import pytest |
| 6 | |
Anthony Sottile | 4575652 | 2019-02-11 19:56:15 -0800 | [diff] [blame] | 7 | from pre_commit_hooks.check_builtin_literals import Call |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 8 | from pre_commit_hooks.check_builtin_literals import main |
Anthony Sottile | 4575652 | 2019-02-11 19:56:15 -0800 | [diff] [blame] | 9 | from pre_commit_hooks.check_builtin_literals import Visitor |
Anthony Sottile | 030bfac | 2019-01-31 19:19:10 -0800 | [diff] [blame] | 10 | |
| 11 | BUILTIN_CONSTRUCTORS = '''\ |
Anthony Sottile | f5c42a0 | 2020-02-05 11:10:42 -0800 | [diff] [blame] | 12 | import builtins |
Anthony Sottile | 030bfac | 2019-01-31 19:19:10 -0800 | [diff] [blame] | 13 | |
| 14 | c1 = complex() |
| 15 | d1 = dict() |
| 16 | f1 = float() |
| 17 | i1 = int() |
| 18 | l1 = list() |
| 19 | s1 = str() |
| 20 | t1 = tuple() |
| 21 | |
| 22 | c2 = builtins.complex() |
| 23 | d2 = builtins.dict() |
| 24 | f2 = builtins.float() |
| 25 | i2 = builtins.int() |
| 26 | l2 = builtins.list() |
| 27 | s2 = builtins.str() |
| 28 | t2 = builtins.tuple() |
| 29 | ''' |
| 30 | BUILTIN_LITERALS = '''\ |
| 31 | c1 = 0j |
| 32 | d1 = {} |
| 33 | f1 = 0.0 |
| 34 | i1 = 0 |
| 35 | l1 = [] |
| 36 | s1 = '' |
| 37 | t1 = () |
| 38 | ''' |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 39 | |
| 40 | |
| 41 | @pytest.fixture |
| 42 | def visitor(): |
Anthony Sottile | 4575652 | 2019-02-11 19:56:15 -0800 | [diff] [blame] | 43 | return Visitor() |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 44 | |
| 45 | |
| 46 | @pytest.mark.parametrize( |
| 47 | ('expression', 'calls'), |
| 48 | [ |
Anthony Sottile | df93509 | 2018-05-17 17:14:25 -0700 | [diff] [blame] | 49 | # see #285 |
| 50 | ('x[0]()', []), |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 51 | # complex |
Anthony Sottile | 8626e26 | 2019-02-11 19:57:37 -0800 | [diff] [blame] | 52 | ('0j', []), |
| 53 | ('complex()', [Call('complex', 1, 0)]), |
| 54 | ('complex(0, 0)', []), |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 55 | ("complex('0+0j')", []), |
Ben Webber | 7758676 | 2017-11-30 18:27:16 +0000 | [diff] [blame] | 56 | ('builtins.complex()', []), |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 57 | # float |
Anthony Sottile | 8626e26 | 2019-02-11 19:57:37 -0800 | [diff] [blame] | 58 | ('0.0', []), |
| 59 | ('float()', [Call('float', 1, 0)]), |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 60 | ("float('0.0')", []), |
Ben Webber | 7758676 | 2017-11-30 18:27:16 +0000 | [diff] [blame] | 61 | ('builtins.float()', []), |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 62 | # int |
Anthony Sottile | 8626e26 | 2019-02-11 19:57:37 -0800 | [diff] [blame] | 63 | ('0', []), |
| 64 | ('int()', [Call('int', 1, 0)]), |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 65 | ("int('0')", []), |
Ben Webber | 7758676 | 2017-11-30 18:27:16 +0000 | [diff] [blame] | 66 | ('builtins.int()', []), |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 67 | # list |
Anthony Sottile | 8626e26 | 2019-02-11 19:57:37 -0800 | [diff] [blame] | 68 | ('[]', []), |
| 69 | ('list()', [Call('list', 1, 0)]), |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 70 | ("list('abc')", []), |
| 71 | ("list([c for c in 'abc'])", []), |
| 72 | ("list(c for c in 'abc')", []), |
Ben Webber | 7758676 | 2017-11-30 18:27:16 +0000 | [diff] [blame] | 73 | ('builtins.list()', []), |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 74 | # str |
| 75 | ("''", []), |
Anthony Sottile | 8626e26 | 2019-02-11 19:57:37 -0800 | [diff] [blame] | 76 | ('str()', [Call('str', 1, 0)]), |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 77 | ("str('0')", []), |
Ben Webber | 7758676 | 2017-11-30 18:27:16 +0000 | [diff] [blame] | 78 | ('builtins.str()', []), |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 79 | # tuple |
Anthony Sottile | 8626e26 | 2019-02-11 19:57:37 -0800 | [diff] [blame] | 80 | ('()', []), |
| 81 | ('tuple()', [Call('tuple', 1, 0)]), |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 82 | ("tuple('abc')", []), |
| 83 | ("tuple([c for c in 'abc'])", []), |
| 84 | ("tuple(c for c in 'abc')", []), |
Ben Webber | 7758676 | 2017-11-30 18:27:16 +0000 | [diff] [blame] | 85 | ('builtins.tuple()', []), |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 86 | ], |
| 87 | ) |
| 88 | def test_non_dict_exprs(visitor, expression, calls): |
| 89 | visitor.visit(ast.parse(expression)) |
| 90 | assert visitor.builtin_type_calls == calls |
| 91 | |
| 92 | |
| 93 | @pytest.mark.parametrize( |
| 94 | ('expression', 'calls'), |
| 95 | [ |
Anthony Sottile | 8626e26 | 2019-02-11 19:57:37 -0800 | [diff] [blame] | 96 | ('{}', []), |
| 97 | ('dict()', [Call('dict', 1, 0)]), |
| 98 | ('dict(a=1, b=2, c=3)', []), |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 99 | ("dict(**{'a': 1, 'b': 2, 'c': 3})", []), |
| 100 | ("dict([(k, v) for k, v in [('a', 1), ('b', 2), ('c', 3)]])", []), |
| 101 | ("dict((k, v) for k, v in [('a', 1), ('b', 2), ('c', 3)])", []), |
Ben Webber | 7758676 | 2017-11-30 18:27:16 +0000 | [diff] [blame] | 102 | ('builtins.dict()', []), |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 103 | ], |
| 104 | ) |
| 105 | def test_dict_allow_kwargs_exprs(visitor, expression, calls): |
| 106 | visitor.visit(ast.parse(expression)) |
| 107 | assert visitor.builtin_type_calls == calls |
| 108 | |
| 109 | |
| 110 | @pytest.mark.parametrize( |
| 111 | ('expression', 'calls'), |
| 112 | [ |
Anthony Sottile | 8626e26 | 2019-02-11 19:57:37 -0800 | [diff] [blame] | 113 | ('dict()', [Call('dict', 1, 0)]), |
| 114 | ('dict(a=1, b=2, c=3)', [Call('dict', 1, 0)]), |
Anthony Sottile | 4575652 | 2019-02-11 19:56:15 -0800 | [diff] [blame] | 115 | ("dict(**{'a': 1, 'b': 2, 'c': 3})", [Call('dict', 1, 0)]), |
Ben Webber | 7758676 | 2017-11-30 18:27:16 +0000 | [diff] [blame] | 116 | ('builtins.dict()', []), |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 117 | ], |
| 118 | ) |
| 119 | def test_dict_no_allow_kwargs_exprs(expression, calls): |
Anthony Sottile | 4575652 | 2019-02-11 19:56:15 -0800 | [diff] [blame] | 120 | visitor = Visitor(allow_dict_kwargs=False) |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 121 | visitor.visit(ast.parse(expression)) |
| 122 | assert visitor.builtin_type_calls == calls |
| 123 | |
| 124 | |
| 125 | def test_ignore_constructors(): |
Anthony Sottile | fea76b9 | 2020-02-03 08:41:48 -0800 | [diff] [blame] | 126 | visitor = Visitor( |
| 127 | ignore=('complex', 'dict', 'float', 'int', 'list', 'str', 'tuple'), |
| 128 | ) |
Anthony Sottile | 030bfac | 2019-01-31 19:19:10 -0800 | [diff] [blame] | 129 | visitor.visit(ast.parse(BUILTIN_CONSTRUCTORS)) |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 130 | assert visitor.builtin_type_calls == [] |
| 131 | |
| 132 | |
Anthony Sottile | 030bfac | 2019-01-31 19:19:10 -0800 | [diff] [blame] | 133 | def test_failing_file(tmpdir): |
| 134 | f = tmpdir.join('f.py') |
| 135 | f.write(BUILTIN_CONSTRUCTORS) |
Max Rozentsveyg | f35bfed | 2020-05-20 12:07:45 -0400 | [diff] [blame] | 136 | rc = main([str(f)]) |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 137 | assert rc == 1 |
| 138 | |
| 139 | |
Anthony Sottile | 030bfac | 2019-01-31 19:19:10 -0800 | [diff] [blame] | 140 | def test_passing_file(tmpdir): |
| 141 | f = tmpdir.join('f.py') |
| 142 | f.write(BUILTIN_LITERALS) |
Max Rozentsveyg | f35bfed | 2020-05-20 12:07:45 -0400 | [diff] [blame] | 143 | rc = main([str(f)]) |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 144 | assert rc == 0 |
| 145 | |
| 146 | |
Anthony Sottile | 030bfac | 2019-01-31 19:19:10 -0800 | [diff] [blame] | 147 | def test_failing_file_ignore_all(tmpdir): |
| 148 | f = tmpdir.join('f.py') |
| 149 | f.write(BUILTIN_CONSTRUCTORS) |
Max Rozentsveyg | f35bfed | 2020-05-20 12:07:45 -0400 | [diff] [blame] | 150 | rc = main(['--ignore=complex,dict,float,int,list,str,tuple', str(f)]) |
Ben Webber | 35996b7 | 2017-11-26 00:17:47 +0000 | [diff] [blame] | 151 | assert rc == 0 |