Skip to content

Commit

Permalink
Merge branch 'main' into normalize
Browse files Browse the repository at this point in the history
  • Loading branch information
hauntsaninja authored Jun 28, 2023
2 parents bc9b735 + 63481bb commit c29a6de
Show file tree
Hide file tree
Showing 12 changed files with 122 additions and 42 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,4 @@ jobs:
python -m pip install -e ".[uvloop]"
- name: Format ourselves
run: python -m black --check src/
run: python -m black --check .
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

- Fix a bug where an illegal trailing comma was added to return type annotations using
PEP 604 unions (#3735)
- Fix a bug where multi-line open parenthesis magic comment like `type: ignore` were not
correctly parsed (#3740)

### Preview style

Expand All @@ -25,6 +27,8 @@

<!-- Changes to how Black can be configured -->

- The `--workers` argument to Black can now be specified via the `BLACK_NUM_WORKERS`
environment variable (#3743)
- `.pytest_cache`, `.ruff_cache` and `.vscode` are now excluded by default (#3691)
- Fix black not honouring `pyproject.toml` settings when running `--stdin-filename` and
the `pyproject.toml` found isn't in the current working directory (#3719)
Expand All @@ -46,12 +50,14 @@
<!-- Changes that improve Black's performance. -->

- Speed up _Black_ significantly when the cache is full (#3751)
- Avoid importing `IPython` in a case where we wouldn't need it (#3748)

### Output

<!-- Changes to Black's terminal output and error messages -->

- Use aware UTC datetimes internally, avoids deprecation warning on Python 3.12 (#3728)
- Change verbose logging to exactly mirror _Black_'s logic for source discovery (#3749)

### _Blackd_

Expand Down
16 changes: 15 additions & 1 deletion docs/usage_and_configuration/the_basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ respect the `--force-exclude` option on some editors that rely on using stdin.
#### `-W`, `--workers`

When _Black_ formats multiple files, it may use a process pool to speed up formatting.
This option controls the number of parallel workers.
This option controls the number of parallel workers. This can also be specified via the
`BLACK_NUM_WORKERS` environment variable.

#### `-q`, `--quiet`

Expand Down Expand Up @@ -296,6 +297,19 @@ Read configuration options from a configuration file. See

Show available command-line options and exit.

### Environment variable options

_Black_ supports the following configuration via environment variables.

#### `BLACK_CACHE_DIR`

The directory where _Black_ should store its cache.

#### `BLACK_NUM_WORKERS`

The number of parallel workers _Black_ should use. The command line option `-W` /
`--workers` takes precedence over this environment variable.

### Code input alternatives

_Black_ supports formatting code via stdin, with the result being printed to stdout.
Expand Down
6 changes: 2 additions & 4 deletions gallery/gallery.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,11 +243,9 @@ def format_repos(repos: Tuple[Path, ...], options: Namespace) -> None:


def main() -> None:
parser = ArgumentParser(
description="""Black Gallery is a script that
parser = ArgumentParser(description="""Black Gallery is a script that
automates the process of applying different Black versions to a selected
PyPI package and seeing the results between versions."""
)
PyPI package and seeing the results between versions.""")

group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("-p", "--pypi-package", help="PyPI package to download.")
Expand Down
6 changes: 2 additions & 4 deletions scripts/make_width_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ def make_width_table() -> Iterable[Tuple[int, int, int]]:
def main() -> None:
table_path = join(dirname(__file__), "..", "src", "black", "_width_table.py")
with open(table_path, "w") as f:
f.write(
f"""# Generated by {basename(__file__)}
f.write(f"""# Generated by {basename(__file__)}
# wcwidth {wcwidth.__version__}
# Unicode {wcwidth.list_versions()[-1]}
import sys
Expand All @@ -62,8 +61,7 @@ def main() -> None:
from typing import Final
WIDTH_TABLE: Final[List[Tuple[int, int, int]]] = [
"""
)
""")
for triple in make_width_table():
f.write(f" {triple!r},\n")
f.write("]\n")
Expand Down
39 changes: 17 additions & 22 deletions src/black/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,10 @@ def validate_regex(
"--workers",
type=click.IntRange(min=1),
default=None,
help="Number of parallel workers [default: number of CPUs in the system]",
help=(
"Number of parallel workers [default: BLACK_NUM_WORKERS environment variable "
"or number of CPUs in the system]"
),
)
@click.option(
"-q",
Expand Down Expand Up @@ -481,26 +484,6 @@ def main( # noqa: C901
fg="blue",
)

normalized = [
(
(source, source)
if source == "-"
else (normalize_path_maybe_ignore(Path(source), root), source)
)
for source in src
]
srcs_string = ", ".join(
[
(
f'"{_norm}"'
if _norm
else f'\033[31m"{source} (skipping - invalid)"\033[34m'
)
for _norm, source in normalized
]
)
out(f"Sources to be formatted: {srcs_string}", fg="blue")

if config:
config_source = ctx.get_parameter_source("config")
user_level_config = str(find_user_pyproject_toml())
Expand Down Expand Up @@ -651,9 +634,15 @@ def get_sources(
is_stdin = False

if is_stdin or p.is_file():
normalized_path = normalize_path_maybe_ignore(p, ctx.obj["root"], report)
normalized_path: Optional[str] = normalize_path_maybe_ignore(
p, ctx.obj["root"], report
)
if normalized_path is None:
if verbose:
out(f'Skipping invalid source: "{normalized_path}"', fg="red")
continue
if verbose:
out(f'Found input source: "{normalized_path}"', fg="blue")

normalized_path = "/" + normalized_path
# Hard-exclude any files that matches the `--force-exclude` regex.
Expand All @@ -676,6 +665,9 @@ def get_sources(
sources.add(p)
elif p.is_dir():
p = root / normalize_path_maybe_ignore(p, ctx.obj["root"], report)
if verbose:
out(f'Found input source directory: "{p}"', fg="blue")

if using_default_exclude:
gitignore = {
root: root_gitignore,
Expand All @@ -696,9 +688,12 @@ def get_sources(
)
)
elif s == "-":
if verbose:
out("Found input source stdin", fg="blue")
sources.add(p)
else:
err(f"invalid path: {s}")

return sources


Expand Down
3 changes: 2 additions & 1 deletion src/black/concurrency.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ def reformat_many(

executor: Executor
if workers is None:
workers = os.cpu_count() or 1
workers = int(os.environ.get("BLACK_NUM_WORKERS", 0))
workers = workers or os.cpu_count() or 1
if sys.platform == "win32":
# Work around https://bugs.python.org/issue26903
workers = min(workers, 60)
Expand Down
7 changes: 6 additions & 1 deletion src/black/handle_ipynb_magics.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,13 @@ class Replacement:
@lru_cache()
def jupyter_dependencies_are_installed(*, verbose: bool, quiet: bool) -> bool:
try:
import IPython # noqa:F401
# isort: off
# tokenize_rt is less commonly installed than IPython
# and IPython is expensive to import
import tokenize_rt # noqa:F401
import IPython # noqa:F401

# isort: on
except ModuleNotFoundError:
if verbose or not quiet:
msg = (
Expand Down
10 changes: 8 additions & 2 deletions src/black/linegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
is_stub_body,
is_stub_suite,
is_tuple_containing_walrus,
is_type_ignore_comment_string,
is_vararg,
is_walrus_assignment,
is_yield,
Expand Down Expand Up @@ -1399,8 +1400,13 @@ def maybe_make_parens_invisible_in_atom(
if is_lpar_token(first) and is_rpar_token(last):
middle = node.children[1]
# make parentheses invisible
first.value = ""
last.value = ""
if (
# If the prefix of `middle` includes a type comment with
# ignore annotation, then we do not remove the parentheses
not is_type_ignore_comment_string(middle.prefix.strip())
):
first.value = ""
last.value = ""
maybe_make_parens_invisible_in_atom(
middle,
parent=parent,
Expand Down
5 changes: 3 additions & 2 deletions src/black/lines.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
is_multiline_string,
is_one_sequence_between,
is_type_comment,
is_type_ignore_comment,
is_with_or_async_with_stmt,
replace_child,
syms,
Expand Down Expand Up @@ -251,7 +252,7 @@ def contains_uncollapsable_type_comments(self) -> bool:
for comment in comments:
if is_type_comment(comment):
if comment_seen or (
not is_type_comment(comment, " ignore")
not is_type_ignore_comment(comment)
and leaf_id not in ignored_ids
):
return True
Expand Down Expand Up @@ -288,7 +289,7 @@ def contains_unsplittable_type_ignore(self) -> bool:
# line.
for node in self.leaves[-2:]:
for comment in self.comments.get(id(node), []):
if is_type_comment(comment, " ignore"):
if is_type_ignore_comment(comment):
return True

return False
Expand Down
23 changes: 19 additions & 4 deletions src/black/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -816,12 +816,27 @@ def is_async_stmt_or_funcdef(leaf: Leaf) -> bool:
)


def is_type_comment(leaf: Leaf, suffix: str = "") -> bool:
"""Return True if the given leaf is a special comment.
Only returns true for type comments for now."""
def is_type_comment(leaf: Leaf) -> bool:
"""Return True if the given leaf is a type comment. This function should only
be used for general type comments (excluding ignore annotations, which should
use `is_type_ignore_comment`). Note that general type comments are no longer
used in modern version of Python, this function may be deprecated in the future."""
t = leaf.type
v = leaf.value
return t in {token.COMMENT, STANDALONE_COMMENT} and v.startswith("# type:" + suffix)
return t in {token.COMMENT, STANDALONE_COMMENT} and v.startswith("# type:")


def is_type_ignore_comment(leaf: Leaf) -> bool:
"""Return True if the given leaf is a type comment with ignore annotation."""
t = leaf.type
v = leaf.value
return t in {token.COMMENT, STANDALONE_COMMENT} and is_type_ignore_comment_string(v)


def is_type_ignore_comment_string(value: str) -> bool:
"""Return True if the given string match with type comment with
ignore annotation."""
return value.startswith("# type: ignore")


def wrap_in_parentheses(parent: Node, child: LN, *, visible: bool = True) -> None:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# This is a regression test. Issue #3737

a = ( # type: ignore
int( # type: ignore
int( # type: ignore
int( # type: ignore
6
)
)
)
)

b = (
int(
6
)
)

print( "111") # type: ignore
print( "111" ) # type: ignore
print( "111" ) # type: ignore


# output


# This is a regression test. Issue #3737

a = ( # type: ignore
int( # type: ignore
int( # type: ignore
int(6) # type: ignore
)
)
)

b = int(6)

print("111") # type: ignore
print("111") # type: ignore
print("111") # type: ignore

0 comments on commit c29a6de

Please sign in to comment.