Skip to content

Commit

Permalink
Standardize type comments to always have one space (#2698)
Browse files Browse the repository at this point in the history
  • Loading branch information
Pedro-Muller29 committed Sep 28, 2024
1 parent 68cd137 commit ccdde24
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 16 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

- Fix type annotation spacing between * and more complex type variable tuple (i.e. `def
fn(*args: *tuple[*Ts, T]) -> None: pass`) (#4440)
- Standardize type comments to always have one space (#4467)

### Caching

Expand Down
3 changes: 3 additions & 0 deletions docs/the_black_code_style/future_style.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ Currently, the following features are included in the preview style:
blocks when the line is too long
- `pep646_typed_star_arg_type_var_tuple`: fix type annotation spacing between * and more
complex type variable tuple (i.e. `def fn(*args: *tuple[*Ts, T]) -> None: pass`)
- `type_comments_standardization`: type comments with zero or more empty spaces between
`#` and `type:`, or between `type:` and the type itself will be formatted to
`# type: (type itself)`.

(labels/unstable-features)=

Expand Down
17 changes: 12 additions & 5 deletions src/black/comments.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,20 @@ def make_comment(content: str) -> str:

if content[0] == "#":
content = content[1:]

NON_BREAKING_SPACE = " "
if (
content
and content[0] == NON_BREAKING_SPACE
and not content.lstrip().startswith("type:")
):

is_type_comment = re.match(r"^\s*type:", content)
is_not_type_ignore = re.match(r"^\s*type:(?!\s*ignore\b)", content)

if content and content[0] == NON_BREAKING_SPACE and not is_type_comment:
content = " " + content[1:] # Replace NBSP by a simple space
elif is_type_comment and is_not_type_ignore and NON_BREAKING_SPACE not in content:
content = content.strip()
parts = content.split(":")
key = parts[0].strip() # Remove extra spaces around "type"
value = parts[1].strip() # Remove extra spaces around the value part
content = f" {key}: {value}"
if content and content[0] not in COMMENT_EXCEPTIONS:
content = " " + content
return "#" + content
Expand Down
1 change: 1 addition & 0 deletions src/black/mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ class Preview(Enum):
remove_redundant_guard_parens = auto()
parens_for_long_if_clauses_in_case_block = auto()
pep646_typed_star_arg_type_var_tuple = auto()
type_comments_standardization = auto()


UNSTABLE_FEATURES: set[Preview] = {
Expand Down
5 changes: 1 addition & 4 deletions src/black/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -912,10 +912,7 @@ def is_type_comment(leaf: Leaf) -> bool:
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 bool(re.match(r"#\s*type:", v))
)
return t in {token.COMMENT, STANDALONE_COMMENT} and bool(re.match(r"#\s*type:", v))


def is_type_ignore_comment(leaf: Leaf) -> bool:
Expand Down
3 changes: 2 additions & 1 deletion src/black/resources/black.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@
"docstring_check_for_newline",
"remove_redundant_guard_parens",
"parens_for_long_if_clauses_in_case_block",
"pep646_typed_star_arg_type_var_tuple"
"pep646_typed_star_arg_type_var_tuple",
"type_comments_standardization"
]
},
"description": "Enable specific features included in the `--unstable` style. Requires `--preview`. No compatibility guarantees are provided on the behavior or existence of any unstable features."
Expand Down
58 changes: 52 additions & 6 deletions tests/data/cases/type_comment_syntax_error.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,57 @@
def foo(
# type: Foo
x): pass
# flags: --preview


def f(
a, # type: int
):
pass


# test type comments
def f(a, b, c, d, e, f, g, h, i):
# type: (int, int, int, int, int, int, int, int, int) -> None
pass


def f(
a, # type : int
b, # type : int
c, #type : int
d, # type: int
e, # type: int
f, # type : int
g, #type:int
h, # type: int
i, # type: int
):
# type: (...) -> None
pass



# output
def f(
a, # type: int
):
pass


# test type comments
def f(a, b, c, d, e, f, g, h, i):
# type: (int, int, int, int, int, int, int, int, int) -> None
pass


def foo(
# type: Foo
x,
def f(
a, # type : int
b, # type : int
c, # type : int
d, # type: int
e, # type: int
f, # type : int
g, # type: int
h, # type: int
i, # type: int
):
# type: (...) -> None
pass

0 comments on commit ccdde24

Please sign in to comment.