Add OptionManager#parse_known_args

If a user specified `--max-complexity` on the command-line, they
would be told that it did not exist. The same would be true of any
option provided by a plugin. This is because we parse the command-line
arguments twice in Flake8 -- the first time to specify the verbosity
and destination for logging, the second time to actually execute Flake8.
Since plugin options are not registered to start with the first time,
they are not valid options. So when we first parse the options, we should
only attempt to parse the ones which we know about.

Closes #168
This commit is contained in:
Ian Cordasco 2016-07-16 10:07:19 -05:00
parent 43df3ecf74
commit 73be9b0e90
No known key found for this signature in database
GPG key ID: 656D3395E4A9791A
3 changed files with 47 additions and 4 deletions

View file

@ -68,7 +68,7 @@ class Application(object):
except ValueError:
pass
preliminary_opts, _ = self.option_manager.parse_args(args)
preliminary_opts, _ = self.option_manager.parse_known_args(args)
# Set the verbosity of the program
flake8.configure_logging(preliminary_opts.verbose,
preliminary_opts.output_file)

View file

@ -261,15 +261,49 @@ class OptionManager(object):
plugin_version_format
)
def _normalize(self, options):
for option in self.options:
old_value = getattr(options, option.dest)
setattr(options, option.dest, option.normalize(old_value))
def parse_args(self, args=None, values=None):
"""Simple proxy to calling the OptionParser's parse_args method."""
self.generate_epilog()
self.update_version_string()
options, xargs = self.parser.parse_args(args, values)
for option in self.options:
old_value = getattr(options, option.dest)
setattr(options, option.dest, option.normalize(old_value))
self._normalize(options)
return options, xargs
def parse_known_args(self, args=None, values=None):
"""Parse only the known arguments from the argument values.
Replicate a little argparse behaviour while we're still on
optparse.
"""
self.generate_epilog()
self.update_version_string()
# Taken from optparse.OptionParser.parse_args
rargs = self.parser._get_args(args)
if values is None:
values = self.parser.get_default_values()
self.parser.rargs = rargs
self.parser.largs = largs = []
self.parser.values = values
while rargs:
# NOTE(sigmavirus24): If we only care about *known* options, then
# we should just shift the bad option over to the largs list and
# carry on.
# Unfortunately, we need to rely on a private method here.
try:
self.parser._process_args(largs, rargs, values)
except (optparse.BadOptionError, optparse.OptionValueError) as err:
self.parser.largs.append(err.opt_str)
args = largs + rargs
options, xargs = self.parser.check_values(values, args)
self._normalize(options)
return options, xargs
def register_plugin(self, name, version):

View file

@ -2,6 +2,7 @@
import optparse
import os
import mock
import pytest
from flake8 import utils
@ -194,3 +195,11 @@ def test_extend_default_ignore(optmanager):
assert optmanager.extended_default_ignore == set(['T100',
'T101',
'T102'])
def test_parse_known_args(optmanager):
"""Verify we ignore unknown options."""
with mock.patch('sys.exit') as sysexit:
optmanager.parse_known_args(['--max-complexity', '5'])
assert sysexit.called is False