Merge branch 'expensive-debug' into 'master'

Delete an extremely expensive LOG.debug call; optimize keyword_arguments_for

See merge request pycqa/flake8!430
This commit is contained in:
Anders Kaseorg 2021-03-30 07:19:42 +00:00
commit b51127941a
3 changed files with 25 additions and 19 deletions

View file

@ -408,12 +408,11 @@ class FileChecker(object):
self.results.append((error_code, line_number, column, text, line)) self.results.append((error_code, line_number, column, text, line))
return error_code return error_code
def run_check(self, plugin, **arguments): def run_check(self, plugin):
"""Run the check in a single plugin.""" """Run the check in a single plugin."""
LOG.debug("Running %r with %r", plugin, arguments)
try: try:
self.processor.keyword_arguments_for( arguments = self.processor.keyword_arguments_for(
plugin["parameters"], arguments plugin["parameters"]
) )
except AttributeError as ae: except AttributeError as ae:
LOG.error("Plugin requested unknown parameters.") LOG.error("Plugin requested unknown parameters.")
@ -480,8 +479,10 @@ class FileChecker(object):
) )
return return
self.processor.tree = ast
for plugin in self.checks["ast_plugins"]: for plugin in self.checks["ast_plugins"]:
checker = self.run_check(plugin, tree=ast) checker = self.run_check(plugin)
# If the plugin uses a class, call the run method of it, otherwise # If the plugin uses a class, call the run method of it, otherwise
# the call should return something iterable itself # the call should return something iterable itself
try: try:
@ -496,6 +497,8 @@ class FileChecker(object):
text=text, text=text,
) )
del self.processor.tree
def run_logical_checks(self): def run_logical_checks(self):
"""Run all checks expecting a logical line.""" """Run all checks expecting a logical line."""
comments, logical_line, mapping = self.processor.build_logical_line() comments, logical_line, mapping = self.processor.build_logical_line()
@ -507,7 +510,7 @@ class FileChecker(object):
for plugin in self.checks["logical_line_plugins"]: for plugin in self.checks["logical_line_plugins"]:
self.processor.update_checker_state_for(plugin) self.processor.update_checker_state_for(plugin)
results = self.run_check(plugin, logical_line=logical_line) or () results = self.run_check(plugin) or ()
for offset, text in results: for offset, text in results:
line_number, column_offset = find_offset(offset, mapping) line_number, column_offset = find_offset(offset, mapping)
if line_number == column_offset == 0: if line_number == column_offset == 0:
@ -526,9 +529,11 @@ class FileChecker(object):
A single physical check may return multiple errors. A single physical check may return multiple errors.
""" """
self.processor.physical_line = physical_line
for plugin in self.checks["physical_line_plugins"]: for plugin in self.checks["physical_line_plugins"]:
self.processor.update_checker_state_for(plugin) self.processor.update_checker_state_for(plugin)
result = self.run_check(plugin, physical_line=physical_line) result = self.run_check(plugin)
if result is not None: if result is not None:
# This is a single result if first element is an int # This is a single result if first element is an int
@ -551,6 +556,8 @@ class FileChecker(object):
text=text, text=text,
) )
del self.processor.physical_line
def process_tokens(self): def process_tokens(self):
"""Process tokens and trigger checks. """Process tokens and trigger checks.

View file

@ -243,18 +243,15 @@ class FileProcessor(object):
yield line yield line
self.line_number += 1 self.line_number += 1
def keyword_arguments_for(self, parameters, arguments=None): def keyword_arguments_for(self, parameters):
# type: (Dict[str, bool], Optional[Dict[str, Any]]) -> Dict[str, Any] # type: (Dict[str, bool]) -> Dict[str, Any]
"""Generate the keyword arguments for a list of parameters.""" """Generate the keyword arguments for a list of parameters."""
if arguments is None: arguments = {}
arguments = {} for param in parameters:
for param, required in parameters.items():
if param in arguments:
continue
try: try:
arguments[param] = getattr(self, param) arguments[param] = getattr(self, param)
except AttributeError as exc: except AttributeError as exc:
if required: if parameters[param]:
LOG.exception(exc) LOG.exception(exc)
raise raise
else: else:

View file

@ -188,7 +188,7 @@ def test_next_line(default_options):
@pytest.mark.parametrize('params, args, expected_kwargs', [ @pytest.mark.parametrize('params, args, expected_kwargs', [
({'blank_before': True, 'blank_lines': True}, ({'blank_before': True, 'blank_lines': True},
None, {},
{'blank_before': 0, 'blank_lines': 0}), {'blank_before': 0, 'blank_lines': 0}),
({'noqa': True, 'fake': True}, ({'noqa': True, 'fake': True},
{'fake': 'foo'}, {'fake': 'foo'},
@ -196,8 +196,8 @@ def test_next_line(default_options):
({'blank_before': True, 'blank_lines': True, 'noqa': True}, ({'blank_before': True, 'blank_lines': True, 'noqa': True},
{'blank_before': 10, 'blank_lines': 5, 'noqa': True}, {'blank_before': 10, 'blank_lines': 5, 'noqa': True},
{'blank_before': 10, 'blank_lines': 5, 'noqa': True}), {'blank_before': 10, 'blank_lines': 5, 'noqa': True}),
({}, {'fake': 'foo'}, {'fake': 'foo'}), ({'fake': False}, {'fake': 'foo'}, {'fake': 'foo'}),
({'non-existent': False}, {'fake': 'foo'}, {'fake': 'foo'}), ({'fake': False, 'non-existent': False}, {'fake': 'foo'}, {'fake': 'foo'}),
]) ])
def test_keyword_arguments_for(params, args, expected_kwargs, default_options): def test_keyword_arguments_for(params, args, expected_kwargs, default_options):
"""Verify the keyword args are generated properly.""" """Verify the keyword args are generated properly."""
@ -206,7 +206,9 @@ def test_keyword_arguments_for(params, args, expected_kwargs, default_options):
]) ])
kwargs_for = file_processor.keyword_arguments_for kwargs_for = file_processor.keyword_arguments_for
assert kwargs_for(params, args) == expected_kwargs for k, v in args.items():
setattr(file_processor, k, v)
assert kwargs_for(params) == expected_kwargs
def test_keyword_arguments_for_does_not_handle_attribute_errors( def test_keyword_arguments_for_does_not_handle_attribute_errors(