- Make passing `SRC` or `--code` mandatory and mutually exclusive (#2804)
- Work around bug that causes unstable formatting in some cases in the presence of the
magic trailing comma (#2807)
+- Use parentheses for attribute access on decimal float and int literals (#2799)
+- Don't add whitespace for attribute access on hexadecimal, binary, octal, and complex
+ literals (#2799)
- Deprecate the `black-primer` tool (#2809)
### Packaging
yield from self.line()
yield from self.visit(child)
+ def visit_power(self, node: Node) -> Iterator[Line]:
+ for idx, leaf in enumerate(node.children[:-1]):
+ next_leaf = node.children[idx + 1]
+
+ if not isinstance(leaf, Leaf):
+ continue
+
+ value = leaf.value.lower()
+ if (
+ leaf.type == token.NUMBER
+ and next_leaf.type == syms.trailer
+ # Ensure that we are in an attribute trailer
+ and next_leaf.children[0].type == token.DOT
+ # It shouldn't wrap hexadecimal, binary and octal literals
+ and not value.startswith(("0x", "0b", "0o"))
+ # It shouldn't wrap complex literals
+ and "j" not in value
+ ):
+ wrap_in_parentheses(node, leaf)
+
+ yield from self.visit_default(node)
+
def visit_SEMI(self, leaf: Leaf) -> Iterator[Line]:
"""Remove a semicolon and put the other statement on a separate line."""
yield from self.line()
return NO
if not prev:
- if t == token.DOT:
- prevp = preceding_leaf(p)
- if not prevp or prevp.type != token.NUMBER:
- return NO
-
- elif t == token.LSQB:
+ if t == token.DOT or t == token.LSQB:
return NO
elif prev.type != token.COMMA:
--- /dev/null
+x = 123456789 .bit_count()
+x = (123456).__abs__()
+x = .1.is_integer()
+x = 1. .imag
+x = 1E+1.imag
+x = 1E-1.real
+x = 123456789.123456789.hex()
+x = 123456789.123456789E123456789 .real
+x = 123456789E123456789 .conjugate()
+x = 123456789J.real
+x = 123456789.123456789J.__add__(0b1011.bit_length())
+x = 0XB1ACC.conjugate()
+x = 0B1011 .conjugate()
+x = 0O777 .real
+x = 0.000000006 .hex()
+x = -100.0000J
+
+if 10 .real:
+ ...
+
+y = 100[no]
+y = 100(no)
+
+# output
+
+x = (123456789).bit_count()
+x = (123456).__abs__()
+x = (0.1).is_integer()
+x = (1.0).imag
+x = (1e1).imag
+x = (1e-1).real
+x = (123456789.123456789).hex()
+x = (123456789.123456789e123456789).real
+x = (123456789e123456789).conjugate()
+x = 123456789j.real
+x = 123456789.123456789j.__add__(0b1011.bit_length())
+x = 0xB1ACC.conjugate()
+x = 0b1011.conjugate()
+x = 0o777.real
+x = (0.000000006).hex()
+x = -100.0000j
+
+if (10).real:
+ ...
+
+y = 100[no]
+y = 100(no)
True
False
1
-@@ -21,71 +21,104 @@
+@@ -21,99 +21,135 @@
Name1 or (Name2 and Name3) or Name4
Name1 or Name2 and Name3 or Name4
v1 << 2
call(**self.screen_kwargs)
call(b, **self.screen_kwargs)
lukasz.langa.pl
-@@ -94,26 +127,29 @@
- 1.0 .real
+ call.me(maybe)
+-1 .real
+-1.0 .real
++(1).real
++(1.0).real
....__class__
list[str]
dict[str, int]
call(b, **self.screen_kwargs)
lukasz.langa.pl
call.me(maybe)
-1 .real
-1.0 .real
+(1).real
+(1.0).real
....__class__
list[str]
dict[str, int]
True
False
1
-@@ -21,71 +21,92 @@
+@@ -21,99 +21,118 @@
Name1 or (Name2 and Name3) or Name4
Name1 or Name2 and Name3 or Name4
v1 << 2
call(**self.screen_kwargs)
call(b, **self.screen_kwargs)
lukasz.langa.pl
-@@ -94,26 +115,24 @@
- 1.0 .real
+ call.me(maybe)
+-1 .real
+-1.0 .real
++(1).real
++(1.0).real
....__class__
list[str]
dict[str, int]
)
SIMPLE_CASES: List[str] = [
+ "attribute_access_on_number_literals",
"beginning_backslash",
"bracketmatch",
"class_blank_parentheses",