def test_parse_user_config(optmanager, config_finder): """Verify parsing of user config files.""" optmanager.add_option( "--exclude", parse_from_config=True, comma_separated_list=True, normalize_paths=True, ) optmanager.add_option("--ignore", parse_from_config=True, comma_separated_list=True) optmanager.add_option("--quiet", parse_from_config=True, action="count") parser = config.MergedConfigParser(optmanager, config_finder) config_finder.user_config_file = ("tests/fixtures/config_files/" "cli-specified.ini") parsed_config = parser.parse_user_config() assert parsed_config == { "ignore": ["E123", "W234", "E111"], "exclude": [ os.path.abspath("foo/"), os.path.abspath("bar/"), os.path.abspath("bogus/"), ], "quiet": 1, }
def test_parsed_hyphenated_and_underscored_names(optmanager, config_finder, config_file): """Verify we find hyphenated option names as well as underscored. This tests for options like --max-line-length and --enable-extensions which are able to be specified either as max-line-length or max_line_length in our config files. """ optmanager.add_option("--max-line-length", parse_from_config=True, type=int) optmanager.add_option( "--enable-extensions", parse_from_config=True, comma_separated_list=True, ) parser = config.MergedConfigParser(optmanager, config_finder) with mock.patch.object(config_finder, "local_config_files") as localcfs: localcfs.return_value = [config_file] with mock.patch.object(config_finder, "user_config_file") as usercf: usercf.return_value = "" parsed_config = parser.merge_user_and_local_config() assert parsed_config["max_line_length"] == 110 assert parsed_config["enable_extensions"] == ["H101", "H235"]
def test_parse_local_config(optmanager, config_finder): """Verify parsing of local config files.""" optmanager.add_option( "--exclude", parse_from_config=True, comma_separated_list=True, normalize_paths=True, ) optmanager.add_option("--ignore", parse_from_config=True, comma_separated_list=True) optmanager.add_option("--quiet", parse_from_config=True, action="count") parser = config.MergedConfigParser(optmanager, config_finder) with mock.patch.object(config_finder, "local_config_files") as localcfs: localcfs.return_value = [ "tests/fixtures/config_files/cli-specified.ini" ] parsed_config = parser.parse_local_config() assert parsed_config == { "ignore": ["E123", "W234", "E111"], "exclude": [ os.path.abspath("foo/"), os.path.abspath("bar/"), os.path.abspath("bogus/"), ], "quiet": 1, }
def test_parse_cli_config(optmanager, config_finder): """Parse the specified config file as a cli config file.""" optmanager.add_option( "--exclude", parse_from_config=True, comma_separated_list=True, normalize_paths=True, ) optmanager.add_option("--ignore", parse_from_config=True, comma_separated_list=True) optmanager.add_option("--quiet", parse_from_config=True, action="count") parser = config.MergedConfigParser(optmanager, config_finder) config_file = "tests/fixtures/config_files/cli-specified.ini" parsed_config = parser.parse_cli_config(config_file) config_dir = os.path.dirname(config_file) assert parsed_config == { "ignore": ["E123", "W234", "E111"], "exclude": [ os.path.abspath(os.path.join(config_dir, "foo/")), os.path.abspath(os.path.join(config_dir, "bar/")), os.path.abspath(os.path.join(config_dir, "bogus/")), ], "quiet": 1, }
def test_parse_local_config(optmanager, config_finder): """Verify parsing of local config files.""" optmanager.add_option('--exclude', parse_from_config=True, comma_separated_list=True, normalize_paths=True) optmanager.add_option('--ignore', parse_from_config=True, comma_separated_list=True) optmanager.add_option('--verbose', parse_from_config=True, action='count') optmanager.add_option('--quiet', parse_from_config=True, action='count') parser = config.MergedConfigParser(optmanager, config_finder) with mock.patch.object(config_finder, 'local_config_files') as localcfs: localcfs.return_value = [ 'tests/fixtures/config_files/cli-specified.ini' ] parsed_config = parser.parse_local_config() assert parsed_config == { 'ignore': ['E123', 'W234', 'E111'], 'exclude': [ os.path.abspath('foo/'), os.path.abspath('bar/'), os.path.abspath('bogus/'), ], 'verbose': 2, 'quiet': 1, }
def test_merge_user_and_local_config(optmanager, config_finder): """Verify merging of parsed user and local config files.""" optmanager.add_option( "--exclude", parse_from_config=True, comma_separated_list=True, normalize_paths=True, ) optmanager.add_option("--ignore", parse_from_config=True, comma_separated_list=True) optmanager.add_option("--select", parse_from_config=True, comma_separated_list=True) parser = config.MergedConfigParser(optmanager, config_finder) with mock.patch.object(config_finder, "local_config_files") as localcfs: localcfs.return_value = [ "tests/fixtures/config_files/local-config.ini" ] config_finder.user_config_file = ("tests/fixtures/config_files/" "user-config.ini") parsed_config = parser.merge_user_and_local_config() assert parsed_config == { "exclude": [os.path.abspath("docs/")], "ignore": ["D203"], "select": ["E", "W", "F"], }
def test_parse_cli_config(optmanager, config_finder): """Parse the specified config file as a cli config file.""" optmanager.add_option('--exclude', parse_from_config=True, comma_separated_list=True, normalize_paths=True) optmanager.add_option('--ignore', parse_from_config=True, comma_separated_list=True) optmanager.add_option('--verbose', parse_from_config=True, action='count') optmanager.add_option('--quiet', parse_from_config=True, action='count') parser = config.MergedConfigParser(optmanager, config_finder) parsed_config = parser.parse_cli_config( 'tests/fixtures/config_files/cli-specified.ini') assert parsed_config == { 'ignore': ['E123', 'W234', 'E111'], 'exclude': [ os.path.abspath('foo/'), os.path.abspath('bar/'), os.path.abspath('bogus/'), ], 'verbose': 2, 'quiet': 1, }
def test_is_configured_by(filename, is_configured_by, optmanager, config_finder): """Verify the behaviour of the is_configured_by method.""" parsed_config, _ = config.ConfigFileFinder._read_config(filename) parser = config.MergedConfigParser(optmanager, config_finder) assert parser.is_configured_by(parsed_config) is is_configured_by
def test_parse_uses_cli_config(optmanager): """Verify behaviour of the parse method with a specified config.""" config_finder = mock.MagicMock() parser = config.MergedConfigParser(optmanager, config_finder) parser.parse(cli_config='foo.ini') config_finder.cli_config.assert_called_once_with('foo.ini')
def test_parsed_configs_are_equivalent(optmanager, config_finder, config_fixture_path): """Verify the each file matches the expected parsed output. This is used to ensure our documented behaviour does not regress. """ optmanager.add_option('--exclude', parse_from_config=True, comma_separated_list=True, normalize_paths=True) optmanager.add_option('--ignore', parse_from_config=True, comma_separated_list=True) parser = config.MergedConfigParser(optmanager, config_finder) with mock.patch.object(config_finder, 'local_config_files') as localcfs: localcfs.return_value = [config_fixture_path] with mock.patch.object(config_finder, 'user_config_file') as usercf: usercf.return_value = [] parsed_config = parser.merge_user_and_local_config() assert parsed_config['ignore'] == ['E123', 'W234', 'E111'] assert parsed_config['exclude'] == [ os.path.abspath('foo/'), os.path.abspath('bar/'), os.path.abspath('bogus/'), ]
def test_parse_user_config(optmanager, config_finder): """Verify parsing of user config files.""" optmanager.add_option('--exclude', parse_from_config=True, comma_separated_list=True, normalize_paths=True) optmanager.add_option('--ignore', parse_from_config=True, comma_separated_list=True) optmanager.add_option('--quiet', parse_from_config=True, action='count') parser = config.MergedConfigParser(optmanager, config_finder) config_finder.user_config_file = ('tests/fixtures/config_files/' 'cli-specified.ini') parsed_config = parser.parse_user_config() assert parsed_config == { 'ignore': ['E123', 'W234', 'E111'], 'exclude': [ os.path.abspath('foo/'), os.path.abspath('bar/'), os.path.abspath('bogus/'), ], 'quiet': 1, }
def test_merge_user_and_local_config(optmanager, config_finder): """Verify merging of parsed user and local config files.""" optmanager.add_option('--exclude', parse_from_config=True, comma_separated_list=True, normalize_paths=True) optmanager.add_option('--ignore', parse_from_config=True, comma_separated_list=True) optmanager.add_option('--select', parse_from_config=True, comma_separated_list=True) parser = config.MergedConfigParser(optmanager, config_finder) with mock.patch.object(config_finder, 'local_config_files') as localcfs: localcfs.return_value = [ 'tests/fixtures/config_files/local-config.ini' ] with mock.patch.object(config_finder, 'user_config_file') as usercf: usercf.return_value = ('tests/fixtures/config_files/' 'user-config.ini') parsed_config = parser.merge_user_and_local_config() assert parsed_config == { 'exclude': [os.path.abspath('docs/')], 'ignore': ['D203'], 'select': ['E', 'W', 'F'], }
def test_parsed_configs_are_equivalent(optmanager, config_finder, config_fixture_path): """Verify the each file matches the expected parsed output. This is used to ensure our documented behaviour does not regress. """ optmanager.add_option( "--exclude", parse_from_config=True, comma_separated_list=True, normalize_paths=True, ) optmanager.add_option("--ignore", parse_from_config=True, comma_separated_list=True) parser = config.MergedConfigParser(optmanager, config_finder) with mock.patch.object(config_finder, "local_config_files") as localcfs: localcfs.return_value = [config_fixture_path] with mock.patch.object(config_finder, "user_config_file") as usercf: usercf.return_value = "" parsed_config = parser.merge_user_and_local_config() assert parsed_config["ignore"] == ["E123", "W234", "E111"] assert parsed_config["exclude"] == [ os.path.abspath("foo/"), os.path.abspath("bar/"), os.path.abspath("bogus/"), ]
def test_parse_isolates_config(ConfigFileManager, optmanager): """Verify behaviour of the parse method with isolated=True.""" parser = config.MergedConfigParser(optmanager) assert parser.parse(isolated=True) == {} assert parser.config_finder.local_configs.called is False assert parser.config_finder.user_config.called is False
def aggregate_options(manager, arglist=None, values=None): """Aggregate and merge CLI and config file options. :param flake8.option.manager.OptionManager manager: The instance of the OptionManager that we're presently using. :param list arglist: The list of arguments to pass to ``manager.parse_args``. In most cases this will be None so ``parse_args`` uses ``sys.argv``. This is mostly available to make testing easier. :param optparse.Values values: Previously parsed set of parsed options. :returns: Tuple of the parsed options and extra arguments returned by ``manager.parse_args``. :rtype: tuple(optparse.Values, list) """ # Get defaults from the option parser default_values, _ = manager.parse_args([], values=values) # Get original CLI values so we can find additional config file paths and # see if --config was specified. original_values, original_args = manager.parse_args(arglist) extra_config_files = utils.normalize_paths(original_values.append_config) # Make our new configuration file mergerator config_parser = config.MergedConfigParser( option_manager=manager, extra_config_files=extra_config_files, args=original_args, ) # Get the parsed config parsed_config = config_parser.parse(original_values.config, original_values.isolated) # Extend the default ignore value with the extended default ignore list, # registered by plugins. extended_default_ignore = manager.extended_default_ignore.copy() LOG.debug('Extended default ignore list: %s', list(extended_default_ignore)) extended_default_ignore.update(default_values.ignore) default_values.ignore = list(extended_default_ignore) LOG.debug('Merged default ignore list: %s', default_values.ignore) # Merge values parsed from config onto the default values returned for config_name, value in parsed_config.items(): dest_name = config_name # If the config name is somehow different from the destination name, # fetch the destination name from our Option if not hasattr(default_values, config_name): dest_name = config_parser.config_options[config_name].dest LOG.debug('Overriding default value of (%s) for "%s" with (%s)', getattr(default_values, dest_name, None), dest_name, value) # Override the default values with the config values setattr(default_values, dest_name, value) # Finally parse the command-line options return manager.parse_args(arglist, default_values)
def test_parse_isolates_config(optmanager): """Verify behaviour of the parse method with isolated=True.""" config_finder = mock.MagicMock() config_finder.ignore_config_files = True parser = config.MergedConfigParser(optmanager, config_finder) assert parser.parse() == {} assert config_finder.local_configs.called is False assert config_finder.user_config.called is False
def test_parse_uses_cli_config(optmanager): """Verify behaviour of the parse method with a specified config.""" config_file_value = 'foo.ini' config_finder = mock.MagicMock() config_finder.config_file = config_file_value config_finder.ignore_config_files = False parser = config.MergedConfigParser(optmanager, config_finder) parser.parse() config_finder.cli_config.assert_called_once_with(config_file_value)
def test_parse_toml_no_flake8(optmanager, config_finder, config_file): """Verify that we can parse empty pyproject.toml without no error.""" optmanager.add_option('--exclude', parse_from_config=True, comma_separated_list=True) parser = config.MergedConfigParser(optmanager, config_finder) with mock.patch.object(config_finder, 'local_config_files') as localcfs: localcfs.return_value = [config_file] with mock.patch.object(config_finder, 'user_config') as usercf: usercf.return_value = configparser.RawConfigParser() parsed_config = parser.merge_user_and_local_config() assert parsed_config == {}
def test_creates_its_own_config_file_finder(args, extra_config_files, optmanager): """Verify we create a ConfigFileFinder correctly.""" class_path = 'flake8.options.config.ConfigFileFinder' with mock.patch(class_path) as ConfigFileFinder: parser = config.MergedConfigParser( option_manager=optmanager, extra_config_files=extra_config_files, args=args, ) assert parser.program_name == 'flake8' ConfigFileFinder.assert_called_once_with( 'flake8', args, extra_config_files or [], )
def test_parse_user_config(optmanager): """Verify parsing of user config files.""" optmanager.add_option('--exclude', parse_from_config=True, comma_separated_list=True, normalize_paths=True) optmanager.add_option('--ignore', parse_from_config=True, comma_separated_list=True) parser = config.MergedConfigParser(optmanager) with mock.patch.object(parser.config_finder, 'user_config_file') as usercf: usercf.return_value = 'tests/fixtures/config_files/cli-specified.ini' parsed_config = parser.parse_user_config() assert parsed_config == { 'ignore': ['E123', 'W234', 'E111'], 'exclude': [ os.path.abspath('foo/'), os.path.abspath('bar/'), os.path.abspath('bogus/'), ] }
def test_parsed_hyphenated_and_underscored_names(optmanager, config_file): """Verify we find hyphenated option names as well as underscored. This tests for options like --max-line-length and --enable-extensions which are able to be specified either as max-line-length or max_line_length in our config files. """ optmanager.add_option('--max-line-length', parse_from_config=True, type='int') optmanager.add_option('--enable-extensions', parse_from_config=True, comma_separated_list=True) parser = config.MergedConfigParser(optmanager) config_finder = parser.config_finder with mock.patch.object(config_finder, 'local_config_files') as localcfs: localcfs.return_value = [config_file] with mock.patch.object(config_finder, 'user_config_file') as usercf: usercf.return_value = [] parsed_config = parser.merge_user_and_local_config() assert parsed_config['max_line_length'] == 110 assert parsed_config['enable_extensions'] == ['H101', 'H235']
def aggregate_options( manager, # type: OptionManager config_finder, # type: config.ConfigFileFinder argv, # type: List[str] ): # type: (...) -> Tuple[argparse.Namespace, List[str]] """Aggregate and merge CLI and config file options. :param flake8.options.manager.OptionManager manager: The instance of the OptionManager that we're presently using. :param flake8.options.config.ConfigFileFinder config_finder: The config file finder to use. :param list argv: The list of remaining command-line argumentsthat were unknown during preliminary option parsing to pass to ``manager.parse_args``. :returns: Tuple of the parsed options and extra arguments returned by ``manager.parse_args``. :rtype: tuple(argparse.Namespace, list) """ # Get defaults from the option parser default_values, _ = manager.parse_args([]) # Make our new configuration file mergerator config_parser = config.MergedConfigParser( option_manager=manager, config_finder=config_finder ) # Get the parsed config parsed_config = config_parser.parse() # load from pyproject.toml parsed_config.update(parse_py_project_toml()) # Extend the default ignore value with the extended default ignore list, # registered by plugins. extended_default_ignore = manager.extended_default_ignore.copy() LOG.debug( "Extended default ignore list: %s", list(extended_default_ignore) ) extended_default_ignore.update(default_values.ignore) default_values.ignore = list(extended_default_ignore) LOG.debug("Merged default ignore list: %s", default_values.ignore) extended_default_select = manager.extended_default_select.copy() LOG.debug( "Extended default select list: %s", list(extended_default_select) ) default_values.extended_default_select = extended_default_select # Merge values parsed from config onto the default values returned for config_name, value in parsed_config.items(): dest_name = config_name # If the config name is somehow different from the destination name, # fetch the destination name from our Option if not hasattr(default_values, config_name): dest_name = config_parser.config_options[config_name].dest LOG.debug( 'Overriding default value of (%s) for "%s" with (%s)', getattr(default_values, dest_name, None), dest_name, value, ) # Override the default values with the config values setattr(default_values, dest_name, value) # Finally parse the command-line options return manager.parse_args(argv, default_values)