Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 777cae5

Browse files
Shivansh-007JelleZijlstrafelix-hilden
authored
Use parentheses on method access on float and int literals (psf#2799)
Co-authored-by: Jelle Zijlstra <[email protected]> Co-authored-by: Felix Hildén <[email protected]>
1 parent b92822a commit 777cae5

8 files changed

Lines changed: 88 additions & 14 deletions

CHANGES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
- Make passing `SRC` or `--code` mandatory and mutually exclusive (#2804)
4343
- Work around bug that causes unstable formatting in some cases in the presence of the
4444
magic trailing comma (#2807)
45+
- Use parentheses for attribute access on decimal float and int literals (#2799)
46+
- Don't add whitespace for attribute access on hexadecimal, binary, octal, and complex
47+
literals (#2799)
4548
- Deprecate the `black-primer` tool (#2809)
4649

4750
### Packaging

src/black/linegen.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,28 @@ def visit_decorators(self, node: Node) -> Iterator[Line]:
197197
yield from self.line()
198198
yield from self.visit(child)
199199

200+
def visit_power(self, node: Node) -> Iterator[Line]:
201+
for idx, leaf in enumerate(node.children[:-1]):
202+
next_leaf = node.children[idx + 1]
203+
204+
if not isinstance(leaf, Leaf):
205+
continue
206+
207+
value = leaf.value.lower()
208+
if (
209+
leaf.type == token.NUMBER
210+
and next_leaf.type == syms.trailer
211+
# Ensure that we are in an attribute trailer
212+
and next_leaf.children[0].type == token.DOT
213+
# It shouldn't wrap hexadecimal, binary and octal literals
214+
and not value.startswith(("0x", "0b", "0o"))
215+
# It shouldn't wrap complex literals
216+
and "j" not in value
217+
):
218+
wrap_in_parentheses(node, leaf)
219+
220+
yield from self.visit_default(node)
221+
200222
def visit_SEMI(self, leaf: Leaf) -> Iterator[Line]:
201223
"""Remove a semicolon and put the other statement on a separate line."""
202224
yield from self.line()

src/black/nodes.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -306,12 +306,7 @@ def whitespace(leaf: Leaf, *, complex_subscript: bool) -> str: # noqa: C901
306306
return NO
307307

308308
if not prev:
309-
if t == token.DOT:
310-
prevp = preceding_leaf(p)
311-
if not prevp or prevp.type != token.NUMBER:
312-
return NO
313-
314-
elif t == token.LSQB:
309+
if t == token.DOT or t == token.LSQB:
315310
return NO
316311

317312
elif prev.type != token.COMMA:
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
x = 123456789 .bit_count()
2+
x = (123456).__abs__()
3+
x = .1.is_integer()
4+
x = 1. .imag
5+
x = 1E+1.imag
6+
x = 1E-1.real
7+
x = 123456789.123456789.hex()
8+
x = 123456789.123456789E123456789 .real
9+
x = 123456789E123456789 .conjugate()
10+
x = 123456789J.real
11+
x = 123456789.123456789J.__add__(0b1011.bit_length())
12+
x = 0XB1ACC.conjugate()
13+
x = 0B1011 .conjugate()
14+
x = 0O777 .real
15+
x = 0.000000006 .hex()
16+
x = -100.0000J
17+
18+
if 10 .real:
19+
...
20+
21+
y = 100[no]
22+
y = 100(no)
23+
24+
# output
25+
26+
x = (123456789).bit_count()
27+
x = (123456).__abs__()
28+
x = (0.1).is_integer()
29+
x = (1.0).imag
30+
x = (1e1).imag
31+
x = (1e-1).real
32+
x = (123456789.123456789).hex()
33+
x = (123456789.123456789e123456789).real
34+
x = (123456789e123456789).conjugate()
35+
x = 123456789j.real
36+
x = 123456789.123456789j.__add__(0b1011.bit_length())
37+
x = 0xB1ACC.conjugate()
38+
x = 0b1011.conjugate()
39+
x = 0o777.real
40+
x = (0.000000006).hex()
41+
x = -100.0000j
42+
43+
if (10).real:
44+
...
45+
46+
y = 100[no]
47+
y = 100(no)

tests/data/expression.diff

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
True
1212
False
1313
1
14-
@@ -21,71 +21,104 @@
14+
@@ -21,99 +21,135 @@
1515
Name1 or (Name2 and Name3) or Name4
1616
Name1 or Name2 and Name3 or Name4
1717
v1 << 2
@@ -144,8 +144,11 @@
144144
call(**self.screen_kwargs)
145145
call(b, **self.screen_kwargs)
146146
lukasz.langa.pl
147-
@@ -94,26 +127,29 @@
148-
1.0 .real
147+
call.me(maybe)
148+
-1 .real
149+
-1.0 .real
150+
+(1).real
151+
+(1.0).real
149152
....__class__
150153
list[str]
151154
dict[str, int]

tests/data/expression.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,8 +382,8 @@ async def f():
382382
call(b, **self.screen_kwargs)
383383
lukasz.langa.pl
384384
call.me(maybe)
385-
1 .real
386-
1.0 .real
385+
(1).real
386+
(1.0).real
387387
....__class__
388388
list[str]
389389
dict[str, int]

tests/data/expression_skip_magic_trailing_comma.diff

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
True
1212
False
1313
1
14-
@@ -21,71 +21,92 @@
14+
@@ -21,99 +21,118 @@
1515
Name1 or (Name2 and Name3) or Name4
1616
Name1 or Name2 and Name3 or Name4
1717
v1 << 2
@@ -132,8 +132,11 @@
132132
call(**self.screen_kwargs)
133133
call(b, **self.screen_kwargs)
134134
lukasz.langa.pl
135-
@@ -94,26 +115,24 @@
136-
1.0 .real
135+
call.me(maybe)
136+
-1 .real
137+
-1.0 .real
138+
+(1).real
139+
+(1.0).real
137140
....__class__
138141
list[str]
139142
dict[str, int]

tests/test_format.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
)
1616

1717
SIMPLE_CASES: List[str] = [
18+
"attribute_access_on_number_literals",
1819
"beginning_backslash",
1920
"bracketmatch",
2021
"class_blank_parentheses",

0 commit comments

Comments
 (0)