From 2812b295bca72fe224eb03e3dc2c2db4bf2e8270 Mon Sep 17 00:00:00 2001 From: Keewis Date: Thu, 29 Jul 2021 14:50:19 +0200 Subject: [PATCH 1/6] update find_project_root --- blackdoc/blackcompat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blackdoc/blackcompat.py b/blackdoc/blackcompat.py index 197e9bf..33b40fd 100644 --- a/blackdoc/blackcompat.py +++ b/blackdoc/blackcompat.py @@ -20,7 +20,7 @@ def find_project_root(srcs): project root, the root of the file system is returned. """ if not srcs: - return Path("/").resolve() + return [str(Path.cwd().resolve())] path_srcs = [Path(Path.cwd(), src).resolve() for src in srcs] From 8ca7860eb21a1246905591dc95a1f857ca6b75a8 Mon Sep 17 00:00:00 2001 From: Keewis Date: Thu, 29 Jul 2021 14:55:37 +0200 Subject: [PATCH 2/6] update find_pyproject_toml --- blackdoc/blackcompat.py | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/blackdoc/blackcompat.py b/blackdoc/blackcompat.py index 33b40fd..1d78cbd 100644 --- a/blackdoc/blackcompat.py +++ b/blackdoc/blackcompat.py @@ -3,6 +3,8 @@ For the license, see /licenses/black """ +import os +import sys from functools import lru_cache from pathlib import Path @@ -69,7 +71,35 @@ def find_pyproject_toml(path_search_start): """Find the absolute filepath to a pyproject.toml if it exists""" path_project_root = find_project_root(path_search_start) path_pyproject_toml = path_project_root / "pyproject.toml" - return str(path_pyproject_toml) if path_pyproject_toml.is_file() else None + if path_pyproject_toml.is_file(): + return str(path_pyproject_toml) + + try: + path_user_pyproject_toml = find_user_pyproject_toml() + return ( + str(path_user_pyproject_toml) + if path_user_pyproject_toml.is_file() + else None + ) + except PermissionError as e: + # We do not have access to the user-level config directory, so ignore it. + print(f"Ignoring user configuration directory due to {e!r}") + return None + + +@lru_cache() +def find_user_pyproject_toml() -> Path: + r"""Return the path to the top-level user configuration for black. + This looks for ~\.black on Windows and ~/.config/black on Linux and other + Unix systems. + """ + if sys.platform == "win32": + # Windows + user_config_path = Path.home() / ".black" + else: + config_root = os.environ.get("XDG_CONFIG_HOME", "~/.config") + user_config_path = Path(config_root).expanduser() / "black" + return user_config_path.resolve() def parse_pyproject_toml(path_config): From cd97e1d8cb7e37df8429934fa29e148c8ce8796a Mon Sep 17 00:00:00 2001 From: Keewis Date: Thu, 29 Jul 2021 14:58:24 +0200 Subject: [PATCH 3/6] update parse_pyproject_toml and read_pyproject_toml --- blackdoc/blackcompat.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/blackdoc/blackcompat.py b/blackdoc/blackcompat.py index 1d78cbd..c8702b8 100644 --- a/blackdoc/blackcompat.py +++ b/blackdoc/blackcompat.py @@ -8,7 +8,7 @@ from functools import lru_cache from pathlib import Path -import toml +import tomli @lru_cache() @@ -105,9 +105,11 @@ def find_user_pyproject_toml() -> Path: def parse_pyproject_toml(path_config): """Parse a pyproject toml file, pulling out relevant parts for Black - If parsing fails, will raise a toml.TomlDecodeError + If parsing fails, will raise a tomli.TomlDecodeError """ - pyproject_toml = toml.load(path_config) + with open(path_config, encoding="utf8") as f: + pyproject_toml = tomli.load(f) + black_config = pyproject_toml.get("tool", {}).get("black", {}) blackdoc_config = pyproject_toml.get("tool", {}).get("blackdoc", {}) config = {**black_config, **blackdoc_config} @@ -123,7 +125,7 @@ def read_pyproject_toml(source, config_path): try: config = parse_pyproject_toml(config_path) - except (toml.TomlDecodeError, OSError) as e: + except (tomli.TomlDecodeError, OSError) as e: raise IOError(f"Error reading configuration file ({config_path}): {e}") if not config: From 74c903d9432c3331cd0f989942b303eef618dd82 Mon Sep 17 00:00:00 2001 From: Keewis Date: Thu, 29 Jul 2021 15:09:13 +0200 Subject: [PATCH 4/6] misc fixes --- blackdoc/blackcompat.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/blackdoc/blackcompat.py b/blackdoc/blackcompat.py index c8702b8..119a3a7 100644 --- a/blackdoc/blackcompat.py +++ b/blackdoc/blackcompat.py @@ -53,6 +53,7 @@ def find_project_root(srcs): def wrap_stream_for_windows(f): """ Wrap stream with colorama's wrap_stream so colors are shown on Windows. + If `colorama` is unavailable, the original stream is returned unmodified. Otherwise, the `wrap_stream()` function determines whether the stream needs to be wrapped for a Windows environment and will accordingly either return @@ -88,7 +89,7 @@ def find_pyproject_toml(path_search_start): @lru_cache() -def find_user_pyproject_toml() -> Path: +def find_user_pyproject_toml(): r"""Return the path to the top-level user configuration for black. This looks for ~\.black on Windows and ~/.config/black on Linux and other Unix systems. @@ -136,6 +137,7 @@ def read_pyproject_toml(source, config_path): def normalize_path_maybe_ignore(path, root, report): """Normalize `path`. May return `None` if `path` was ignored. + `report` is where "path ignored" output goes. """ try: From 319428836695871fbd5f31222bc0e5fe40c50f71 Mon Sep 17 00:00:00 2001 From: Keewis Date: Thu, 29 Jul 2021 15:09:26 +0200 Subject: [PATCH 5/6] update gen_python_files --- blackdoc/blackcompat.py | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/blackdoc/blackcompat.py b/blackdoc/blackcompat.py index 119a3a7..a134a50 100644 --- a/blackdoc/blackcompat.py +++ b/blackdoc/blackcompat.py @@ -9,6 +9,7 @@ from pathlib import Path import tomli +from pathspec import PathSpec @lru_cache() @@ -157,6 +158,22 @@ def normalize_path_maybe_ignore(path, root, report): return normalized_path +def path_is_excluded(normalized_path, pattern): + match = pattern.search(normalized_path) if pattern else None + return bool(match and match.group(0)) + + +@lru_cache() +def get_gitignore(root): + """Return a PathSpec matching gitignore content if present.""" + gitignore = root / ".gitignore" + lines = [] + if gitignore.is_file(): + with gitignore.open(encoding="utf-8") as gf: + lines = gf.readlines() + return PathSpec.from_lines("gitwildmatch", lines) + + def gen_python_files(paths, root, include, exclude, force_exclude, report, gitignore): """Generate all files under `path` whose paths are not excluded by the `exclude_regex` or `force_exclude` regexes, but are included by the `include` regex. @@ -172,7 +189,7 @@ def gen_python_files(paths, root, include, exclude, force_exclude, report, gitig continue # First ignore files matching .gitignore - if gitignore.match_file(normalized_path): + if gitignore is not None and gitignore.match_file(normalized_path): report.path_ignored(child, "matches the .gitignore file content") continue @@ -181,15 +198,11 @@ def gen_python_files(paths, root, include, exclude, force_exclude, report, gitig if child.is_dir(): normalized_path += "/" - exclude_match = exclude.search(normalized_path) if exclude else None - if exclude_match and exclude_match.group(0): + if path_is_excluded(normalized_path, exclude): report.path_ignored(child, "matches the --exclude regular expression") continue - force_exclude_match = ( - force_exclude.search(normalized_path) if force_exclude else None - ) - if force_exclude_match and force_exclude_match.group(0): + if path_is_excluded(normalized_path, force_exclude): report.path_ignored(child, "matches the --force-exclude regular expression") continue @@ -201,7 +214,7 @@ def gen_python_files(paths, root, include, exclude, force_exclude, report, gitig exclude, force_exclude, report, - gitignore, + gitignore + get_gitignore(child) if gitignore is not None else None, ) elif child.is_file(): From 661153a230b03301c859e8e4d1e4c1c6dc79a9af Mon Sep 17 00:00:00 2001 From: Keewis Date: Thu, 29 Jul 2021 15:11:03 +0200 Subject: [PATCH 6/6] update the dependencies --- setup.cfg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 49b13a7..f6638f3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -33,7 +33,8 @@ install_requires = black more_itertools importlib-metadata; python_version < "3.8" - toml + tomli + pathspec [options.entry_points] console_scripts =