Repository: akaihola/darker

Issue:
darkgraylib.config.ConfigurationError: Invalid [tool.darker] keys in pyproject.toml: flynt
<!-- 

    NOTE:

    To ask for help using Darker, please use Discussions (see the top of this page).
    This form is only for reporting bugs.

-->

**Describe the bug**
Like the title says, `[tool.darker]` configuration does not pass validation if it includes `flynt = true`. I verified this problem all the way to 1.7 which is odd since I've had that configuration option in my pyproject.toml for ages and I don't remember having problems with it until recently. Here's the whole stacktrace:
```bash
oula-custobar-mbp in ☸ production-fi in darker-bug-repros.git/main on  flynt-not-working-in-pyproject (871e84d) [!] is 📦 v0.1.0 via 🐍 v3.12.1 (main)
🐠 ❯ rye show
project: darker-bug-repro
path: /Users/oula/gits/darker-bug-repros.git/main
venv: /Users/oula/gits/darker-bug-repros.git/main/.venv
target python: 3.8
venv python: cpython@3.12.1
virtual: false
configured sources:
  default (index: https://pypi.org/simple/)
oula-custobar-mbp in ☸ production-fi in darker-bug-repros.git/main on  flynt-not-working-in-pyproject (871e84d) [!] is 📦 v0.1.0 via 🐍 v3.12.1 (main)
🐠 ❯ rye list
astor==0.8.1
black==24.8.0
click==8.1.7
darker==2.1.1
-e file:///Users/oula/gits/darker-bug-repros.git/main
darkgraylib==1.2.1
flynt==1.0.1
graylint==1.1.1
isort==5.13.2
mypy-extensions==1.0.0
packaging==24.1
pathspec==0.12.1
platformdirs==4.3.6
toml==0.10.2
oula-custobar-mbp in ☸ production-fi in darker-bug-repros.git/main on  flynt-not-working-in-pyproject (871e84d) [!] is 📦 v0.1.0 via 🐍 v3.12.1 (main)
🐠 ❯ rye run darker src/
Traceback (most recent call last):
  File "/Users/oula/gits/darker-bug-repros.git/main/.venv/bin/darker", line 8, in <module>
    sys.exit(main_with_error_handling())
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/oula/gits/darker-bug-repros.git/main/.venv/lib/python3.12/site-packages/darker/__main__.py", line 633, in main_with_error_handling
    return main()
           ^^^^^^
  File "/Users/oula/gits/darker-bug-repros.git/main/.venv/lib/python3.12/site-packages/darker/__main__.py", line 482, in main
    args, config, config_nondefault = parse_command_line(argv)
                                      ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/oula/gits/darker-bug-repros.git/main/.venv/lib/python3.12/site-packages/darker/command_line.py", line 110, in parse_command_line
    args, effective_cfg, modified_cfg = darkgraylib.command_line.parse_command_line(
                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/oula/gits/darker-bug-repros.git/main/.venv/lib/python3.12/site-packages/darkgraylib/command_line.py", line 159, in parse_command_line
    pyproject_config = load_config(args.config, args.src, section_name, config_type)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/oula/gits/darker-bug-repros.git/main/.venv/lib/python3.12/site-packages/darkgraylib/config.py", line 178, in load_config
    validate_config_keys(pyproject_tool_config, section_name, config_type)
  File "/Users/oula/gits/darker-bug-repros.git/main/.venv/lib/python3.12/site-packages/darkgraylib/config.py", line 93, in validate_config_keys
    raise ConfigurationError(
darkgraylib.config.ConfigurationError: Invalid [tool.darker] keys in pyproject.toml: flynt
```

**To Reproduce**
Steps to reproduce the behavior:
1. Clone this repository: https://github.com/okuuva/darker-bug-repros/tree/flynt-not-working-in-pyproject
2. Follow instructions in repo README.md

**Expected behavior**
`darker` should use `flynt` when `flynt = true` is included under `[tool.darker]` in `pyproject.toml`.

**Environment (please complete the following information):**
 - OS: macOS
 - Python version 3.12.1
 - Git version 2.46.0
 - Darker version 2.1.1
 - Black version 24.8.0
 - `rye list` output:
 ```
 astor==0.8.1
black==24.8.0
click==8.1.7
darker==2.1.1
-e file:///Users/oula/gits/darker-bug-repros.git/main
darkgraylib==1.2.1
flynt==1.0.1
graylint==1.1.1
isort==5.13.2
mypy-extensions==1.0.0
packaging==24.1
pathspec==0.12.1
platformdirs==4.3.6
toml==0.10.2
```


Discussion:
akaihola: Thanks @okuuva! Strange indeed that this surfaces only now even though you've previously used the `flynt =` configuration option successfully.

If you have time, could you add a change log note about this fix? Also, could you check whether this is covered by unit tests?

No prob if you can't afford the time, I'll come back to this myself too.
okuuva: > If you have time, could you add a change log note about this fix? Also, could you check whether this is covered by unit tests?
> 
> No prob if you can't afford the time, I'll come back to this myself too.

Sure, I'll try to get around it later this week.
okuuva: > > If you have time, could you add a change log note about this fix? Also, could you check whether this is covered by unit tests?
> > No prob if you can't afford the time, I'll come back to this myself too.
> 
> Sure, I'll try to get around it later this week.

**One eternity later**

I finally got around updating this. Added tests for checking that `flynt` can be activated with both cli flags and as a config option.

Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index 9f03adf..e650639 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -20,7 +20,7 @@ Added
 - Invoking Black is now implemented as a plugin. This allows for easier integration of
   other formatters in the future. There's also a dummy ``none`` formatter plugin.
 - ``--formatter=none`` now skips running Black. This is useful when you only want to run
-  Isort or Flynt.
+  Isort or Flynt_.
 
 Removed
 -------
@@ -42,6 +42,7 @@ Fixed
 - Pass full environment to Git to avoid the "dubious ownership" error.
 - Work around a `pathlib.Path.resolve` bug in Python 3.8 and 3.9 on Windows.
   The work-around should be removed when Python 3.8 and 3.9 are no longer supported.
+- Add missing configuration flag for Flynt_.
 
 
 2.1.1_ - 2024-04-16
@@ -79,7 +80,7 @@ Added
 - Update to ``ioggstream/bandit-report-artifacts@v1.7.4`` in CI.
 - Support for Python 3.12 in the package metadata and the CI build.
 - Update to Black 24.2.x and isort 5.13.x in pre-commit configuration.
-- Test against Flynt ``master`` branch in the CI build.
+- Test against Flynt_ ``master`` branch in the CI build.
 - Update to Darkgraylib 1.1.1 to get fixes for README formatting.
 - Improved "How does it work?" section in the README.
 - README section on limitations and work-arounds.
@@ -189,7 +190,7 @@ Fixed
 -----
 - Use ``git worktree`` to create a repository checkout for baseline linting. This avoids
   issues with the previous ``git clone`` and ``git checkout`` based approach.
-- Disallow Flynt version 0.78 and newer to avoid an internal API incompatibility.
+- Disallow Flynt_ version 0.78 and newer to avoid an internal API incompatibility.
 - In CI builds, run the ``commit-range`` action from the current checkout instead of
   pointing to a release tag. This fixes workflows when in a release branch.
 - Linting fixes: Use ``stacklevel=2`` in ``warnings.warn()`` calls as suggested by
@@ -678,6 +679,7 @@ Added
 .. _pygments: https://pypi.org/project/Pygments/
 .. _Darkgraylib: https://pypi.org/project/darkgraylib/
 .. _Flake8: https://flake8.pycqa.org/
+.. _Flynt: https://pypi.org/project/flynt/
 .. _Graylint: https://pypi.org/project/graylint/
 .. _Mypy: https://www.mypy-lang.org/
 .. _pydocstyle: http://www.pydocstyle.org/
diff --git a/src/darker/config.py b/src/darker/config.py
index 6b4f908..7a9a062 100644
--- a/src/darker/config.py
+++ b/src/darker/config.py
@@ -36,13 +36,14 @@ DEPRECATED_CONFIG_OPTIONS: set[str] = set()
 class DarkerConfig(BaseConfig, total=False):
     """Dictionary representing ``[tool.darker]`` from ``pyproject.toml``"""
 
-    diff: bool
     check: bool
+    diff: bool
+    flynt: bool
     isort: bool
+    line_length: int
     lint: list[str]
-    skip_string_normalization: bool
     skip_magic_trailing_comma: bool
-    line_length: int
+    skip_string_normalization: bool
     target_version: str
     formatter: str
 


Test patch:
diff --git a/src/darker/tests/test_command_line.py b/src/darker/tests/test_command_line.py
index 6d108e3..4666e1d 100644
--- a/src/darker/tests/test_command_line.py
+++ b/src/darker/tests/test_command_line.py
@@ -112,6 +112,24 @@ def get_darker_help_output(capsys):
         expect_config=("isort", True),
         expect_modified=("isort", True),
     ),
+    dict(
+        argv=["."],
+        expect_value=("flynt", False),
+        expect_config=("flynt", False),
+        expect_modified=("flynt", ...),
+    ),
+    dict(
+        argv=["-f", "."],
+        expect_value=("flynt", True),
+        expect_config=("flynt", True),
+        expect_modified=("flynt", True),
+    ),
+    dict(
+        argv=["--flynt", "."],
+        expect_value=("flynt", True),
+        expect_config=("flynt", True),
+        expect_modified=("flynt", True),
+    ),
     dict(
         argv=["."],
         expect_value=("lint", []),
@@ -280,6 +298,7 @@ def test_parse_command_line(
     dict(config={"stdout": True}, expect_warn=set()),
     dict(config={"check": True}, expect_warn=set()),
     dict(config={"isort": True}, expect_warn=set()),
+    dict(config={"flynt": True}, expect_warn=set()),
     dict(
         config={"lint": ["dummy"]},
         expect_warn={
@@ -694,6 +713,16 @@ def test_black_config_file_and_options(git_repo, config, options, expect):
             {},
         ),
     ),
+    dict(
+        options=["--flynt", "a.py"],
+        expect=(
+            Path("git_root"),
+            {Path("a.py")},
+            Exclusions(isort={"**/*"}),
+            RevisionRange("HEAD", ":WORKTREE:"),
+            {},
+        ),
+    ),
     dict(
         options=["--config", "my.cfg", "a.py"],
         expect=(