diff --git a/setup.cfg b/setup.cfg index 1c542604..3dea164d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -42,6 +42,7 @@ install_requires= pycodestyle >= 2.7.0, < 2.8.0 mccabe >= 0.6.0, < 0.7.0 importlib-metadata; python_version<"3.8" + toml python_requires = >=3.6 diff --git a/src/flake8/options/config.py b/src/flake8/options/config.py index e920e582..56778d5e 100644 --- a/src/flake8/options/config.py +++ b/src/flake8/options/config.py @@ -7,6 +7,8 @@ from typing import Optional from typing import Tuple +import toml + from flake8 import utils LOG = logging.getLogger(__name__) @@ -51,7 +53,12 @@ def __init__( 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", f".{program_name}") + self.project_filenames = ( + "pyproject.toml", + "setup.cfg", + "tox.ini", + f".{program_name}", + ) self.local_directory = os.path.abspath(os.curdir) @@ -77,7 +84,17 @@ def _read_config( found_files = [] for filename in files: try: - found_files.extend(config.read(filename)) + if filename.endswith("pyproject.toml"): + pyproject_config = toml.load(filename) + config.read_dict( + { + "flake8": pyproject_config["tool"]["flake8"], + }, + source=filename, + ) + found_files.append(filename) + else: + found_files.extend(config.read(filename)) except UnicodeDecodeError: LOG.exception( "There was an error decoding a config file." diff --git a/tests/fixtures/config_files/broken-pyproject.toml b/tests/fixtures/config_files/broken-pyproject.toml new file mode 100644 index 00000000..2d7227cf --- /dev/null +++ b/tests/fixtures/config_files/broken-pyproject.toml @@ -0,0 +1,12 @@ +[tool.flake8] +ignore = [ + "E123", + "W234", + E111, +] +exclude = [ + "foo/", + "bar/", + "bogus/", +] +quiet = 1 diff --git a/tests/fixtures/config_files/cli-specified-pyproject.toml b/tests/fixtures/config_files/cli-specified-pyproject.toml new file mode 100644 index 00000000..570a2462 --- /dev/null +++ b/tests/fixtures/config_files/cli-specified-pyproject.toml @@ -0,0 +1,12 @@ +[tool.flake8] +ignore = [ + "E123", + "W234", + "E111", +] +exclude = [ + "foo/", + "bar/", + "bogus/", +] +quiet = 1 diff --git a/tests/fixtures/config_files/no-flake8-section-pyproject.toml b/tests/fixtures/config_files/no-flake8-section-pyproject.toml new file mode 100644 index 00000000..6aa528ae --- /dev/null +++ b/tests/fixtures/config_files/no-flake8-section-pyproject.toml @@ -0,0 +1,12 @@ +[tool.flake9] +ignore = [ + "E123", + "W234", + "E111", +] +exclude = [ + "foo/", + "bar/", + "bogus/", +] +quiet = 1 diff --git a/tests/unit/test_config_file_finder.py b/tests/unit/test_config_file_finder.py index 51167962..919cc4d1 100644 --- a/tests/unit/test_config_file_finder.py +++ b/tests/unit/test_config_file_finder.py @@ -10,10 +10,23 @@ CLI_SPECIFIED_FILEPATH = "tests/fixtures/config_files/cli-specified.ini" BROKEN_CONFIG_PATH = "tests/fixtures/config_files/broken.ini" +CLI_SPECIFIED_PYPROJECT_CONFIG_PATH = ( + "tests/fixtures/config_files/cli-specified-pyproject.toml" # noqa: E501 +) +BROKEN_PYPROJECT_CONFIG_PATH = ( + "tests/fixtures/config_files/broken-pyproject.toml" # noqa: E501 +) -def test_cli_config(): + +@pytest.mark.parametrize( + "cli_filepath", + [ + CLI_SPECIFIED_FILEPATH, + CLI_SPECIFIED_PYPROJECT_CONFIG_PATH, + ], +) +def test_cli_config(cli_filepath): """Verify opening and reading the file specified via the cli.""" - cli_filepath = CLI_SPECIFIED_FILEPATH finder = config.ConfigFileFinder("flake8") parsed_config = finder.cli_config(cli_filepath) @@ -91,13 +104,19 @@ def test_local_configs(): "files", [ [BROKEN_CONFIG_PATH], - [CLI_SPECIFIED_FILEPATH, BROKEN_CONFIG_PATH], + [BROKEN_PYPROJECT_CONFIG_PATH], + [ + CLI_SPECIFIED_FILEPATH, + BROKEN_CONFIG_PATH, + BROKEN_PYPROJECT_CONFIG_PATH, + ], ], ) def test_read_config_catches_broken_config_files(files): """Verify that we do not allow the exception to bubble up.""" _, parsed = config.ConfigFileFinder._read_config(*files) assert BROKEN_CONFIG_PATH not in parsed + assert BROKEN_PYPROJECT_CONFIG_PATH not in parsed def test_read_config_catches_decoding_errors(tmpdir): diff --git a/tests/unit/test_merged_config_parser.py b/tests/unit/test_merged_config_parser.py index b19291c6..c6e00187 100644 --- a/tests/unit/test_merged_config_parser.py +++ b/tests/unit/test_merged_config_parser.py @@ -54,6 +54,10 @@ def test_parse_cli_config(optmanager, config_finder): [ ("tests/fixtures/config_files/cli-specified.ini", True), ("tests/fixtures/config_files/no-flake8-section.ini", False), + ( + "tests/fixtures/config_files/no-flake8-section-pyproject.toml", + False, + ), # noqa: E501 ], ) def test_is_configured_by( @@ -188,6 +192,7 @@ def test_parse_uses_cli_config(optmanager): "tests/fixtures/config_files/cli-specified.ini", "tests/fixtures/config_files/cli-specified-with-inline-comments.ini", "tests/fixtures/config_files/cli-specified-without-inline-comments.ini", # noqa: E501 + "tests/fixtures/config_files/cli-specified-pyproject.toml", ], ) def test_parsed_configs_are_equivalent(