From aab1f14375d7e0d4d059536e0f53b420d6cec470 Mon Sep 17 00:00:00 2001 From: "Eric N. Vander Weele" Date: Mon, 20 Jan 2020 16:42:16 -0500 Subject: [PATCH] config: Determine path to user configuration immediately Preemptively determine the path of the user configuration file during the construction of the `ConfigFileFinder` object. The user configuration path will always be the same, regardless of when it gets obtained by a run of `flake8`. This isolates the logic of determining the user configuration path into a static helper method to be called to set the `.user_config_file` attribute. The helper method leverages `utils.is_windows()`, instead of reimplementing the check, and decomposes clearly the directory name and the base name to construct the path with a single `return` path. Additionally, this avoids reconstructing the path on demand of obtaining the user configuration file path. --- src/flake8/options/config.py | 35 +++++++++++++------------ tests/unit/test_config_file_finder.py | 13 --------- tests/unit/test_merged_config_parser.py | 14 +++++----- 3 files changed, 24 insertions(+), 38 deletions(-) diff --git a/src/flake8/options/config.py b/src/flake8/options/config.py index 0adb957..5884873 100644 --- a/src/flake8/options/config.py +++ b/src/flake8/options/config.py @@ -3,7 +3,6 @@ import collections import configparser import logging import os.path -import sys from typing import List, Optional, Tuple from flake8 import utils @@ -46,21 +45,29 @@ class ConfigFileFinder(object): # The value of --isolated from the CLI. self.ignore_config_files = ignore_config_files - # Platform specific settings - self.is_windows = sys.platform == "win32" - self.xdg_home = os.environ.get( - "XDG_CONFIG_HOME", os.path.expanduser("~/.config") - ) - - # Look for '.' files - self.program_config = "." + program_name + # User configuration file. self.program_name = program_name + self.user_config_file = self._user_config_file(program_name) # List of filenames to find in the local/project directory - self.project_filenames = ("setup.cfg", "tox.ini", self.program_config) + self.project_filenames = ("setup.cfg", "tox.ini", "." + program_name) self.local_directory = os.path.abspath(os.curdir) + @staticmethod + def _user_config_file(program_name): + # type: (str) -> str + if utils.is_windows(): + home_dir = os.path.expanduser("~") + config_file_basename = "." + program_name + else: + home_dir = os.environ.get( + "XDG_CONFIG_HOME", os.path.expanduser("~/.config") + ) + config_file_basename = program_name + + return os.path.join(home_dir, config_file_basename) + @staticmethod def _read_config(*files): # type: (*str) -> Tuple[configparser.RawConfigParser, List[str]] @@ -139,15 +146,9 @@ class ConfigFileFinder(object): """Parse all local config files into one config object.""" return self.local_configs_with_files()[0] - def user_config_file(self): - """Find the user-level config file.""" - if self.is_windows: - return os.path.expanduser("~\\" + self.program_config) - return os.path.join(self.xdg_home, self.program_name) - def user_config(self): """Parse the user config file into a config object.""" - config, found_files = self._read_config(self.user_config_file()) + config, found_files = self._read_config(self.user_config_file) if found_files: LOG.debug("Found user configuration files: %s", found_files) return config diff --git a/tests/unit/test_config_file_finder.py b/tests/unit/test_config_file_finder.py index 29aacd4..d21b03d 100644 --- a/tests/unit/test_config_file_finder.py +++ b/tests/unit/test_config_file_finder.py @@ -2,7 +2,6 @@ """Tests for the ConfigFileFinder.""" import configparser import os -import sys import mock import pytest @@ -13,18 +12,6 @@ CLI_SPECIFIED_FILEPATH = 'tests/fixtures/config_files/cli-specified.ini' BROKEN_CONFIG_PATH = 'tests/fixtures/config_files/broken.ini' -@pytest.mark.parametrize('platform,is_windows', [ - ('win32', True), - ('linux', False), - ('darwin', False), -]) -def test_windows_detection(platform, is_windows): - """Verify we detect Windows to the best of our knowledge.""" - with mock.patch.object(sys, 'platform', platform): - finder = config.ConfigFileFinder('flake8') - assert finder.is_windows is is_windows - - def test_cli_config(): """Verify opening and reading the file specified via the cli.""" cli_filepath = CLI_SPECIFIED_FILEPATH diff --git a/tests/unit/test_merged_config_parser.py b/tests/unit/test_merged_config_parser.py index 2eaa4b3..41885e4 100644 --- a/tests/unit/test_merged_config_parser.py +++ b/tests/unit/test_merged_config_parser.py @@ -69,9 +69,9 @@ def test_parse_user_config(optmanager, config_finder): action='count') parser = config.MergedConfigParser(optmanager, config_finder) - 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() + 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'], @@ -127,11 +127,9 @@ def test_merge_user_and_local_config(optmanager, config_finder): 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() + config_finder.user_config_file = ('tests/fixtures/config_files/' + 'user-config.ini') + parsed_config = parser.merge_user_and_local_config() assert parsed_config == { 'exclude': [