7 | 7 |
from flake8_polyfill import options
|
8 | 8 |
|
9 | 9 |
|
10 | |
@pytest.mark.parametrize("value,expected", [
|
11 | |
("E123,\n\tW234,\n E206", ["E123", "W234", "E206"]),
|
12 | |
("E123,W234,E206", ["E123", "W234", "E206"]),
|
13 | |
(["E123", "W234", "E206"], ["E123", "W234", "E206"]),
|
14 | |
(["E123", "\n\tW234", "\n E206"], ["E123", "W234", "E206"]),
|
|
10 |
@pytest.mark.parametrize('value,expected', [
|
|
11 |
('E123,\n\tW234,\n E206', ['E123', 'W234', 'E206']),
|
|
12 |
('E123,W234,E206', ['E123', 'W234', 'E206']),
|
|
13 |
(['E123', 'W234', 'E206'], ['E123', 'W234', 'E206']),
|
|
14 |
(['E123', '\n\tW234', '\n E206'], ['E123', 'W234', 'E206']),
|
15 | 15 |
])
|
16 | 16 |
def test_parse_comma_separated_list(value, expected):
|
17 | 17 |
"""Verify that similar inputs produce identical outputs."""
|
18 | 18 |
assert options.parse_comma_separated_list(value) == expected
|
19 | 19 |
|
20 | 20 |
|
21 | |
@pytest.mark.parametrize("value,expected", [
|
22 | |
("flake8", "flake8"),
|
23 | |
("../flake8", os.path.abspath("../flake8")),
|
24 | |
("flake8/", os.path.abspath("flake8")),
|
|
21 |
@pytest.mark.parametrize('value,expected', [
|
|
22 |
('flake8', 'flake8'),
|
|
23 |
('../flake8', os.path.abspath('../flake8')),
|
|
24 |
('flake8/', os.path.abspath('flake8')),
|
25 | 25 |
])
|
26 | 26 |
def test_normalize_path(value, expected):
|
27 | 27 |
"""Verify that we normalize paths provided to the tool."""
|
28 | 28 |
assert options.normalize_path(value) == expected
|
29 | 29 |
|
30 | 30 |
|
31 | |
def test_generate_callback_from_nothing():
|
32 | |
"""Assert that do not create a new callback for nothing."""
|
33 | |
callback = options.generate_callback_from(comma_separated_list=False,
|
34 | |
normalize_paths=False,
|
35 | |
preexisting_callback=None)
|
36 | |
assert callback is None
|
|
31 |
@pytest.mark.parametrize('value,expected', [
|
|
32 |
('file.py', 'file.py'),
|
|
33 |
('path/file.py', os.path.abspath('path/file.py')),
|
|
34 |
(['file.py', 'path/file.py'],
|
|
35 |
['file.py', os.path.abspath('path/file.py')]),
|
|
36 |
])
|
|
37 |
def test_parse_normalized_paths(value, expected):
|
|
38 |
"""Verify that we handle strings and lists when normalizing paths."""
|
|
39 |
assert options.parse_normalized_paths(value) == expected
|
37 | 40 |
|
38 | 41 |
|
39 | |
def test_generate_callback_from_returns_preexisting():
|
40 | |
"""Assert we return the original callback.
|
41 | |
|
42 | |
If the value isn't comma separated or a path but we have a callback,
|
43 | |
show that we return it unadulterated.
|
44 | |
"""
|
45 | |
def preexisting_callback():
|
46 | |
pass
|
47 | |
callback = options.generate_callback_from(
|
48 | |
comma_separated_list=False,
|
49 | |
normalize_paths=False,
|
50 | |
preexisting_callback=preexisting_callback,
|
51 | |
)
|
52 | |
assert callback is preexisting_callback
|
53 | |
|
54 | |
|
55 | |
def test_generate_callback_from_comma_separated_list():
|
56 | |
"""Assert we just return the comma-separated callback."""
|
57 | |
callback = options.generate_callback_from(comma_separated_list=True,
|
58 | |
normalize_paths=False,
|
59 | |
preexisting_callback=None)
|
60 | |
assert callback is options.comma_separated_callback
|
61 | |
|
62 | |
|
63 | |
def test_generate_callback_from_normalize_paths():
|
64 | |
"""Assert we just return the noramlize_paths callback."""
|
65 | |
callback = options.generate_callback_from(comma_separated_list=False,
|
66 | |
normalize_paths=True,
|
67 | |
preexisting_callback=None)
|
68 | |
assert callback is options.normalize_paths_callback
|
69 | |
|
70 | |
|
71 | |
filename = 'file.py'
|
72 | |
partial_path = 'path/file.py'
|
73 | |
abspath = os.path.abspath('path/file.py')
|
74 | |
multiple_paths = '{},{}'.format(filename, partial_path)
|
75 | |
parsed_multiple_paths = [filename, abspath]
|
76 | |
|
77 | |
|
78 | |
@pytest.mark.parametrize('values, parsed_value, expected_value', [
|
79 | |
({}, filename, filename),
|
80 | |
({}, partial_path, abspath),
|
81 | |
({'exclude': filename}, filename, filename),
|
82 | |
({'exclude': filename}, partial_path, filename),
|
83 | |
({'exclude': partial_path}, partial_path, abspath),
|
84 | |
({'exclude': partial_path}, filename, abspath),
|
85 | |
({'exclude': [filename, partial_path]}, multiple_paths,
|
86 | |
parsed_multiple_paths),
|
87 | |
])
|
88 | |
def test_normalize_paths_callback(values, parsed_value, expected_value):
|
89 | |
"""Assert our normalize_paths_callback behaves the right way."""
|
90 | |
dest = 'exclude'
|
91 | |
opt_str = '--exclude'
|
92 | |
option = optparse.Option(opt_str, dest=dest)
|
93 | |
parser = mock.Mock(values=optparse.Values(values))
|
94 | |
options.normalize_paths_callback(option, opt_str, parsed_value, parser)
|
95 | |
assert getattr(parser.values, dest) == expected_value
|
96 | |
|
97 | |
|
98 | |
single_code = 'E123'
|
99 | |
parsed_single_code = ['E123']
|
100 | |
multi_code = 'E123,E234,W504'
|
101 | |
parsed_multi_code = ['E123', 'E234', 'W504']
|
102 | |
|
103 | |
|
104 | |
@pytest.mark.parametrize('values, parsed_value, expected_value', [
|
105 | |
({}, single_code, parsed_single_code),
|
106 | |
({}, multi_code, parsed_multi_code),
|
107 | |
({'select': single_code}, single_code, parsed_single_code),
|
108 | |
({'select': single_code}, multi_code, parsed_single_code),
|
109 | |
({'select': multi_code}, multi_code, parsed_multi_code),
|
110 | |
({'select': multi_code}, single_code, parsed_multi_code),
|
111 | |
])
|
112 | |
def test_comma_separated_callback(values, parsed_value, expected_value):
|
113 | |
"""Assert our comma_separated_callback behaves the right way."""
|
114 | |
dest = 'select'
|
115 | |
opt_str = '--{}'.format(dest)
|
116 | |
option = optparse.Option(opt_str, dest=dest)
|
117 | |
parser = mock.Mock(values=optparse.Values(values))
|
118 | |
options.comma_separated_callback(option, opt_str, parsed_value, parser)
|
119 | |
assert getattr(parser.values, dest) == expected_value
|
120 | |
|
121 | |
|
122 | |
# NOTE(sigmavirus24): Now for the tricky bits
|
123 | |
# We can only really effectively test the composition with real integration
|
124 | |
# tests.
|
125 | |
# Testing generate_callback_from's composition separately means we don't need
|
126 | |
# to test it when we test the register function. We can just assert it has a
|
127 | |
# callback.
|
128 | 42 |
@pytest.mark.parametrize(
|
129 | |
'comma_separated_list, normalize_paths, preexisting_callback, values, '
|
130 | |
'parsed_value, expected_value', [
|
131 | |
(True, True, None, {}, multiple_paths, parsed_multiple_paths),
|
132 | |
(True, True, None, {'foo': multiple_paths}, multiple_paths,
|
133 | |
parsed_multiple_paths),
|
134 | |
(True, True, None, {'foo': parsed_multiple_paths}, multiple_paths,
|
135 | |
parsed_multiple_paths),
|
136 | |
(True, True,
|
137 | |
lambda opt, opt_str, v, p: p.values.foo.append('A.py'),
|
138 | |
{}, multiple_paths, parsed_multiple_paths + ['A.py']),
|
139 | |
(True, False,
|
140 | |
lambda opt, opt_str, v, p: p.values.foo.append('A.py'),
|
141 | |
{}, multiple_paths, [filename, partial_path, 'A.py']),
|
142 | |
(False, True,
|
143 | |
lambda opt, opt_str, v, p: setattr(p.values, 'foo',
|
144 | |
p.values.foo + '.j2'),
|
145 | |
{}, filename, filename + '.j2'),
|
146 | |
(False, True,
|
147 | |
lambda opt, opt_str, v, p: setattr(p.values, 'foo',
|
148 | |
p.values.foo + '.j2'),
|
149 | |
{}, partial_path, abspath + '.j2'),
|
|
43 |
# NOTE: `defaults` has NO impact, since the callback being called implies
|
|
44 |
# that a `value` was specified.
|
|
45 |
'comma_separated_list, normalize_paths, defaults, value, expected_value', [
|
|
46 |
(True, True, {}, 'val', 'N(C(val))'),
|
|
47 |
(True, True, {'foo': 'defaultval'}, 'val', 'N(C(val))'),
|
|
48 |
(True, False, {}, 'val', 'C(val)'),
|
|
49 |
(True, False, {'foo': 'defaultval'}, 'val', 'C(val)'),
|
|
50 |
(False, False, {}, 'val', 'val'),
|
|
51 |
(False, False, {'foo': 'defaultval'}, 'val', 'val'),
|
150 | 52 |
]
|
151 | 53 |
)
|
152 | 54 |
def test_generate_callback_from_composition(
|
153 | |
comma_separated_list, normalize_paths, preexisting_callback, values,
|
154 | |
parsed_value, expected_value,
|
|
55 |
comma_separated_list, normalize_paths, defaults,
|
|
56 |
value, expected_value,
|
155 | 57 |
):
|
156 | |
"""Verify our generate_callback_from composition."""
|
|
58 |
"""Verify our generate_callback_from composition.
|
|
59 |
|
|
60 |
We mock out parse_comma_separated_list and parse_normalized_paths with
|
|
61 |
simple string transformations for better readability.
|
|
62 |
"""
|
157 | 63 |
dest = 'foo'
|
158 | |
opt_str = '--{}'.format(dest)
|
|
64 |
opt_str = '--foo'
|
159 | 65 |
option = optparse.Option(opt_str, dest=dest)
|
160 | |
parser = mock.Mock(values=optparse.Values(values))
|
|
66 |
parser = mock.Mock(values=optparse.Values(defaults))
|
161 | 67 |
|
|
68 |
base_callback = mock.Mock()
|
162 | 69 |
callback = options.generate_callback_from(
|
163 | 70 |
comma_separated_list=comma_separated_list,
|
164 | 71 |
normalize_paths=normalize_paths,
|
165 | |
preexisting_callback=preexisting_callback,
|
|
72 |
base_callback=base_callback,
|
166 | 73 |
)
|
167 | 74 |
|
168 | |
callback(option, opt_str, parsed_value, parser)
|
169 | |
assert getattr(parser.values, dest) == expected_value
|
|
75 |
with mock.patch('flake8_polyfill.options.parse_comma_separated_list') as \
|
|
76 |
parse_comma_separated_list, \
|
|
77 |
mock.patch('flake8_polyfill.options.parse_normalized_paths') as \
|
|
78 |
parse_normalized_paths:
|
|
79 |
|
|
80 |
parse_comma_separated_list.side_effect = lambda v: 'C({})'.format(v)
|
|
81 |
parse_normalized_paths.side_effect = lambda v: 'N({})'.format(v)
|
|
82 |
callback(option, opt_str, value, parser)
|
|
83 |
|
|
84 |
base_callback.assert_called_with(option, opt_str, expected_value, parser)
|
|
85 |
|
|
86 |
|
|
87 |
def test_store_callback():
|
|
88 |
"""Verify the default callback behaves like option with action='store'."""
|
|
89 |
dest = 'foo'
|
|
90 |
opt_str = '--foo'
|
|
91 |
option = optparse.Option(opt_str, dest=dest)
|
|
92 |
parser = mock.Mock(values=optparse.Values({'foo': 'defaultval'}))
|
|
93 |
options.store_callback(option, opt_str, 'val', parser)
|
|
94 |
assert parser.values.foo == 'val'
|
170 | 95 |
|
171 | 96 |
|
172 | 97 |
@pytest.fixture
|
|
177 | 102 |
return parser
|
178 | 103 |
|
179 | 104 |
|
|
105 |
def test_register_with_store_callback(parser):
|
|
106 |
"""Verify we handle typical no-custom-callback case (integration test)."""
|
|
107 |
options.register(parser, '--foo', default=['path/file.py'], type='string',
|
|
108 |
comma_separated_list=True, normalize_paths=True)
|
|
109 |
values, _ = parser.parse_args([])
|
|
110 |
assert values.foo == ['path/file.py'] # default is used in its entirety
|
|
111 |
values, _ = parser.parse_args(['--foo=file.py,path/file.py'])
|
|
112 |
assert values.foo == ['file.py', os.path.abspath('path/file.py')]
|
|
113 |
|
|
114 |
|
|
115 |
def test_register_with_custom_callback(parser):
|
|
116 |
"""Verify we handle custom callback (integration test)."""
|
|
117 |
def custom_callback(option, opt_str, value, parser, *args, **kwargs):
|
|
118 |
parser.values.count = len(value)
|
|
119 |
|
|
120 |
options.register(parser, '--foo', type='string', callback=custom_callback,
|
|
121 |
comma_separated_list=True, normalize_paths=True)
|
|
122 |
values, _ = parser.parse_args(['--foo=file.py,path/file.py'])
|
|
123 |
assert values.count == 2
|
|
124 |
|
|
125 |
|
180 | 126 |
def test_register_parse_from_config(parser):
|
181 | 127 |
"""Verify we append to config_options on registration."""
|
182 | 128 |
options.register(parser, '--select', default='E123,W504',
|
183 | 129 |
parse_from_config=True)
|
184 | 130 |
assert 'select' in parser.config_options
|
185 | |
|
186 | |
|
187 | |
def test_register_comma_separated_list(parser):
|
188 | |
"""Verify we register the comma_separated_callback."""
|
189 | |
options.register(parser, '--select', default='E123,W504',
|
190 | |
comma_separated_list=True)
|
191 | |
option = parser.get_option('--select')
|
192 | |
assert option.callback is options.comma_separated_callback
|
193 | |
|
194 | |
|
195 | |
def test_register_normalize_paths(parser):
|
196 | |
"""Verify we register the normalize_paths_callback."""
|
197 | |
options.register(parser, '--exclude', default='file.py',
|
198 | |
normalize_paths=True)
|
199 | |
option = parser.get_option('--exclude')
|
200 | |
assert option.callback is options.normalize_paths_callback
|
201 | |
|
202 | |
|
203 | |
def test_register_comma_separated_paths(parser):
|
204 | |
"""Verify we register a composed hook."""
|
205 | |
options.register(parser, '--exclude', default='file.py',
|
206 | |
normalize_paths=True, comma_separated_list=True)
|
207 | |
option = parser.get_option('--exclude')
|
208 | |
assert option.callback is not options.normalize_paths_callback
|
209 | |
assert option.callback is not options.comma_separated_callback
|
210 | |
assert option.callback is not None
|