From c9f231be4eb48295335aa85cfd75b34a3bcee417 Mon Sep 17 00:00:00 2001 From: Richard Si <63936253+ichard26@users.noreply.github.com> Date: Sat, 30 May 2020 21:03:10 -0400 Subject: [PATCH 1/3] Convert config values to string We need to convert all configuration values from the pyproject.toml file because Click already does value processing and conversion and it only expects the exact Python type or string. Click doesn't like the integer 1 as a boolean for example. This also means other unsupported types like datetime.time will be rejected by Click as a unvalid value instead of throwing an exception. We only skip converting objects that are an instance of collections.abc.Iterable because it's almost impossible to get back the original iterable of a stringified iterable. --- src/black/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/black/__init__.py b/src/black/__init__.py index a7e89ccba61..93f68ebb7f2 100644 --- a/src/black/__init__.py +++ b/src/black/__init__.py @@ -2,6 +2,7 @@ import asyncio from abc import ABC, abstractmethod from collections import defaultdict +import collections.abc from concurrent.futures import Executor, ThreadPoolExecutor, ProcessPoolExecutor from contextlib import contextmanager from datetime import datetime @@ -318,7 +319,10 @@ def read_pyproject_toml( default_map.update(ctx.default_map) default_map.update(config) - ctx.default_map = default_map + ctx.default_map = { + k: str(v) if not isinstance(v, collections.abc.Iterable) else v + for k, v in default_map.items() + } return value From 28d746d49cc67cb901a132848d818eb113aca0b8 Mon Sep 17 00:00:00 2001 From: Richard Si <63936253+ichard26@users.noreply.github.com> Date: Sun, 31 May 2020 17:05:14 -0400 Subject: [PATCH 2/3] Move where the conversion happens Instead of converting the values in the merged 'default_map', I should convert the values that were read from the 'pyproject.toml' file. --- src/black/__init__.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/black/__init__.py b/src/black/__init__.py index 93f68ebb7f2..24832350ff7 100644 --- a/src/black/__init__.py +++ b/src/black/__init__.py @@ -317,12 +317,14 @@ def read_pyproject_toml( default_map: Dict[str, Any] = {} if ctx.default_map: default_map.update(ctx.default_map) - default_map.update(config) + default_map.update( + { + k: str(v) if not isinstance(v, collections.abc.Iterable) else v + for k, v in config.items() + } + ) - ctx.default_map = { - k: str(v) if not isinstance(v, collections.abc.Iterable) else v - for k, v in default_map.items() - } + ctx.default_map = default_map return value From 74017f19239bb017e163163fce4aa0efe104b75c Mon Sep 17 00:00:00 2001 From: Richard Si <63936253+ichard26@users.noreply.github.com> Date: Mon, 1 Jun 2020 12:47:53 -0400 Subject: [PATCH 3/3] Change collections.abc.Iterable to (list, dict) I also moved where the conversion happens... again. I am rather indecisive if you haven't noticed. It should be better as it takes place in the parse_pyproject_toml logic where configuration modification already takes place. Actually when this PR was first created I had the conversion happen in that return statement, but the target_version check was complaining about it being a string. So I moved the conversion after that check, but then Click didn't like the stringifed list, which led me to check whether the value was an instance of an Iterable before turning it into a string. And... I forgot that type checking before conversion would allow it to work before the target_version check anyway. --- src/black/__init__.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/black/__init__.py b/src/black/__init__.py index 24832350ff7..886d9c29195 100644 --- a/src/black/__init__.py +++ b/src/black/__init__.py @@ -2,7 +2,6 @@ import asyncio from abc import ABC, abstractmethod from collections import defaultdict -import collections.abc from concurrent.futures import Executor, ThreadPoolExecutor, ProcessPoolExecutor from contextlib import contextmanager from datetime import datetime @@ -282,7 +281,12 @@ def parse_pyproject_toml(path_config: str) -> Dict[str, Any]: """ pyproject_toml = toml.load(path_config) config = pyproject_toml.get("tool", {}).get("black", {}) - return {k.replace("--", "").replace("-", "_"): v for k, v in config.items()} + return { + k.replace("--", "").replace("-", "_"): str(v) + if not isinstance(v, (list, dict)) + else v + for k, v in config.items() + } def read_pyproject_toml( @@ -317,12 +321,7 @@ def read_pyproject_toml( default_map: Dict[str, Any] = {} if ctx.default_map: default_map.update(ctx.default_map) - default_map.update( - { - k: str(v) if not isinstance(v, collections.abc.Iterable) else v - for k, v in config.items() - } - ) + default_map.update(config) ctx.default_map = default_map return value