Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow hyphens for option keys in pyproject.toml #503

Merged
merged 6 commits into from
Aug 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ Fixed
- Linting fixes: Use ``stacklevel=2`` in ``warnings.warn()`` calls as suggested by
Flake8; skip Bandit check for virtualenv creation in the GitHub Action;
use ``ignore[method-assign]`` as suggested by Mypy.
- Configuration options spelled with hyphens in ``pyproject.toml``
(e.g. ``line-length = 88``) are now supported.
- In debug log output mode, configuration options are now always spelled with hyphens
instead of underscores.


1.7.0_ - 2023-02-11
Expand Down
49 changes: 46 additions & 3 deletions src/darker/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from argparse import ArgumentParser, Namespace
from dataclasses import dataclass, field
from pathlib import Path
from typing import Iterable, List, Optional, Set, cast
from typing import Dict, Iterable, List, Optional, Set, Union, cast

import toml

Expand All @@ -26,6 +26,9 @@ def dump_list(self, v: Iterable[object]) -> str:
return "[{}\n]".format("".join(f"\n {self.dump_value(item)}," for item in v))


UnvalidatedConfig = Dict[str, Union[List[str], str, bool, int]]


class DarkerConfig(TypedDict, total=False):
"""Dictionary representing ``[tool.darker]`` from ``pyproject.toml``"""

Expand Down Expand Up @@ -92,6 +95,40 @@ class ConfigurationError(Exception):
"""Exception class for invalid configuration values"""


def convert_config_characters(
config: UnvalidatedConfig, pattern: str, replacement: str
) -> UnvalidatedConfig:
"""Convert a character in config keys to a different character"""
return {key.replace(pattern, replacement): value for key, value in config.items()}


def convert_hyphens_to_underscores(config: UnvalidatedConfig) -> UnvalidatedConfig:
"""Convert hyphenated config keys to underscored keys"""
return convert_config_characters(config, "-", "_")


def convert_underscores_to_hyphens(config: DarkerConfig) -> UnvalidatedConfig:
"""Convert underscores in config keys to hyphens"""
return convert_config_characters(cast(UnvalidatedConfig, config), "_", "-")


def validate_config_keys(config: UnvalidatedConfig) -> None:
"""Raise an exception if any keys in the configuration are invalid.

:param config: The configuration read from ``pyproject.toml``
:raises ConfigurationError: Raised if unknown options are present

"""
if set(config).issubset(DarkerConfig.__annotations__):
return
unknown_keys = ", ".join(
sorted(set(config).difference(DarkerConfig.__annotations__))
)
raise ConfigurationError(
f"Invalid [tool.darker] keys in pyproject.toml: {unknown_keys}"
)


def replace_log_level_name(config: DarkerConfig) -> None:
"""Replace numeric log level in configuration with the name of the log level"""
if "log_level" in config:
Expand Down Expand Up @@ -165,7 +202,11 @@ def load_config(path: Optional[str], srcs: Iterable[str]) -> DarkerConfig:
if not config_path.is_file():
return {}
pyproject_toml = toml.load(config_path)
config = cast(DarkerConfig, pyproject_toml.get("tool", {}).get("darker", {}) or {})
tool_darker_config = convert_hyphens_to_underscores(
pyproject_toml.get("tool", {}).get("darker", {}) or {}
)
validate_config_keys(tool_darker_config)
config = cast(DarkerConfig, tool_darker_config)
replace_log_level_name(config)
validate_config_output_mode(config)
return config
Expand Down Expand Up @@ -195,7 +236,9 @@ def get_modified_config(parser: ArgumentParser, args: Namespace) -> DarkerConfig

def dump_config(config: DarkerConfig) -> str:
"""Return the configuration in TOML format"""
dump = toml.dumps(config, encoder=TomlArrayLinesEncoder())
dump = toml.dumps(
convert_underscores_to_hyphens(config), encoder=TomlArrayLinesEncoder()
)
return f"[tool.darker]\n{dump}"


Expand Down
Loading