Skip to content

Commit

Permalink
Merge pull request #480 from akaihola/flynt-0.78-compatibility
Browse files Browse the repository at this point in the history
Fix compatibility with Flynt 0.78 and 1.0.0
  • Loading branch information
akaihola authored Mar 15, 2024
2 parents 645ae0b + c358893 commit dc42aa0
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 18 deletions.
4 changes: 2 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ console_scripts =

[options.extras_require]
flynt =
flynt>=0.76,<0.78
flynt>=0.76
isort =
isort>=5.0.1
color =
Expand All @@ -55,7 +55,7 @@ test =
black>=22.3.0
cryptography>=3.3.2 # through twine, fixes CVE-2020-36242
defusedxml>=0.7.1
flynt>=0.76,<0.78
flynt>=0.76
isort>=5.0.1
mypy>=0.990
pathspec # to test `gen_python_files` in `test_black_diff.py`
Expand Down
3 changes: 2 additions & 1 deletion src/darker/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -488,8 +488,9 @@ def main( # pylint: disable=too-many-locals,too-many-branches,too-many-statemen
validate_config_output_mode(config)

setup_logging(args.log_level)
# Make sure we don't get excessive debug log output from Black
# Make sure we don't get excessive debug log output from Black and Flynt
logging.getLogger("blib2to3.pgen2.driver").setLevel(logging.WARNING)
logging.getLogger("flynt.transform.transform").setLevel(logging.CRITICAL)

show_config_if_debug(config, config_nondefault, args.log_level)

Expand Down
81 changes: 68 additions & 13 deletions src/darker/fstring.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import logging
from pathlib import Path
from typing import Any
from typing import Any, Optional

from darker.exceptions import MissingPackageError
from darker.git import EditedLinenumsDiffer
Expand All @@ -11,14 +11,26 @@
try:
import flynt

flynt_fstringify_code_by_line = flynt.process.fstringify_code_by_line
flynt_version = tuple(map(int, flynt.__version__.split(".")))
if flynt_version >= (0, 78):
from flynt.state import State
else:
State = None # pylint: disable=invalid-name
if flynt_version < (1, 0, 0):
from flynt.process import fstringify_code_by_line
from flynt.pyproject_finder import find_pyproject_toml, parse_pyproject_toml
else:
from flynt.code_editor import fstringify_code_by_line
from flynt.utils.pyproject_finder import (
find_pyproject_toml,
parse_pyproject_toml,
)
except ImportError:
# `flynt` is an optional dependency. Prevent the `ImportError` if it's missing.
flynt = None
State = None

def flynt_fstringify_code_by_line( # type: ignore[misc]
*args: Any, **kwargs: Any
) -> str:
def fstringify_code_by_line(*args: Any, **kwargs: Any) -> str: # type: ignore[misc]
"""Fake `flynt.fstringify_code_by_line()` to use when `flynt` isn't installed"""
raise MissingPackageError(
"No module named 'flynt'. Please install the 'flynt' package before using"
Expand All @@ -42,9 +54,9 @@ def apply_flynt(
responsibility of the caller to filter output to modified lines only.
:param content: The contents of the Python source code file to sort imports in
:param src: The relative path to the file. This must be the actual path in the
repository, which may differ from the path given on the command line in
case of VSCode temporary files.
:param src: The path to the file relative to the repository root. This must be the
actual path in the repository, which may differ from the path given on
the command line in case of VSCode temporary files.
:param edited_linenums_differ: Helper for finding out which lines were edited
:return: Original Python source file contents with modifications from ``flynt``
Expand All @@ -56,18 +68,61 @@ def apply_flynt(
)
if not edited_linenums:
return content
return _call_flynt_fstringify(content)
state = _get_flynt_configuration(edited_linenums_differ.root / src)
return _call_flynt_fstringify(content, state)


def _get_flynt_configuration( # type: ignore[no-any-unimported]
src: Path,
) -> Optional[State]:
"""Read ``pyproject.toml`` Flynt configuration for the given Python file
:param src: The absolute path to the Python file to run Flynt on. This must be the
actual path in the repository, which may differ from the path given on
the command line in case of VSCode temporary files.
:return: A ``flynt`` configuration, or ``None`` for Flynt versions <0.78
def _call_flynt_fstringify(content: TextDocument) -> TextDocument:
"""Call ``flynt.process.fstringify_code_by_line()``, return result `TextDocument`
"""
if State is None: # flynt<0.78
return None
state = State(quiet=True)
toml_file = find_pyproject_toml((str(src),))
if toml_file:
cfg = parse_pyproject_toml(toml_file)
mapping = {
# (state attribute name, `pyproject.toml` option)
("aggressive", "aggressive"),
("len_limit", "line_length"),
("multiline", "not no_multiline"),
("transform_concat", "transform_concats"),
("transform_format", "transform_format"),
("transform_join", "transform_joins"),
("transform_percent", "transform_percent"),
}
for state_attr, cfg_option in mapping:
if cfg_option not in cfg:
continue
if cfg_option.startswith("not "):
value = not cfg[cfg_option[4:]]
else:
value = cfg[cfg_option]
setattr(state, state_attr, value)
return state


def _call_flynt_fstringify( # type: ignore[no-any-unimported]
content: TextDocument, state: Optional[State]
) -> TextDocument:
"""Call ``flynt.code_editor.fstringify_code_by_line()``, return ``TextDocument``
:param content: The contents of the Python source code file to fstringify
:param state: The ``flynt`` configuration to use, or ``None`` for ``flynt<0.78``
:return: Original Python source code contents with modifications from ``flynt``
"""
logger.debug("flynt.process.fstringify_code_by_line(code=...)")
result, _ = flynt_fstringify_code_by_line(content.string)
logger.debug("flynt.code_editor.fstringify_code_by_line(code=...)")
args = () if state is None else (state,) # `()` for flynt<0.78, (state,) for >=0.78
result, _ = fstringify_code_by_line(content.string, *args)
return TextDocument.from_str(
result,
encoding=content.encoding,
Expand Down
5 changes: 3 additions & 2 deletions src/darker/tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def flynt_present(present: bool) -> Generator[None, None, None]:
if present:
# dummy module and function required by `fstring`:
# pylint: disable=no-member
fake_flynt_module.process = ModuleType("process") # type: ignore
fake_flynt_module.process.fstringify_code_by_line = None # type: ignore
fake_flynt_module.__version__ = "1.0.0" # type: ignore
fake_flynt_module.code_editor = ModuleType("process") # type: ignore
fake_flynt_module.code_editor.fstringify_code_by_line = None # type: ignore
yield

0 comments on commit dc42aa0

Please sign in to comment.