change some numeric behavior (#469)

This commit is contained in:
Jelle Zijlstra 2018-08-23 11:55:29 -07:00 committed by GitHub
parent c67feaf04f
commit a37abdcbc5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 38 additions and 16 deletions

View File

@ -373,10 +373,11 @@ an adoption helper, avoid using this for new projects.
### Numeric literals
*Black* standardizes all numeric literals to use lowercase letters: `0xab`
instead of `0XAB` and `1e10` instead of `1E10`. In Python 3.6+, *Black*
adds underscores to long numeric literals to aid readability: `100000000`
becomes `100_000_000`.
*Black* standardizes most numeric literals to use lowercase letters: `0xab`
instead of `0XAB` and `1e10` instead of `1E10`. Python 2 long literals are
styled as `2L` instead of `2l` to avoid confusion between `l` and `1`. In
Python 3.6+, *Black* adds underscores to long numeric literals to aid
readability: `100000000` becomes `100_000_000`.
### Line breaks & binary operators
@ -851,10 +852,13 @@ More details can be found in [CONTRIBUTING](CONTRIBUTING.md).
* adjacent string literals are now correctly split into multiple lines (#463)
* code with `_` in numeric literals is recognized as Python 3.6+ (#461)
* numeric literals are now formatted by *Black* (#452, #461, #464, #469):
* numeric literals are now normalized to include `_` separators on Python 3.6+ code
(#452)
* numeric literals are normalized to include `_` separators on Python 3.6+ code
* code with `_` in numeric literals is recognized as Python 3.6+
* most letters in numeric literals are lowercased (e.g., in `1e10` or `0xab`)
* cache is now populated when `--check` is successful for a file which speeds up
consecutive checks of properly formatted unmodified files (#448)

View File

@ -2522,8 +2522,8 @@ def normalize_string_quotes(leaf: Leaf) -> None:
def normalize_numeric_literal(leaf: Leaf, allow_underscores: bool) -> None:
"""Normalizes numeric (float, int, and complex) literals.
All letters used in the representation are normalized to lowercase, long number
literals are split using underscores.
All letters used in the representation are normalized to lowercase (except
in Python 2 long literals), and long number literals are split using underscores.
"""
text = leaf.value.lower()
if text.startswith(("0o", "0x", "0b")):
@ -2543,6 +2543,9 @@ def normalize_numeric_literal(leaf: Leaf, allow_underscores: bool) -> None:
elif text.endswith(("j", "l")):
number = text[:-1]
suffix = text[-1]
# Capitalize in "2L" because "l" looks too similar to "1".
if suffix == "l":
suffix = "L"
text = f"{format_float_or_int_string(number, allow_underscores)}{suffix}"
else:
text = format_float_or_int_string(text, allow_underscores)
@ -2556,14 +2559,22 @@ def format_float_or_int_string(text: str, allow_underscores: bool) -> str:
before, after = text.split(".")
before = format_int_string(before, allow_underscores) if before else "0"
after = format_int_string(after, allow_underscores) if after else "0"
if after:
after = format_int_string(after, allow_underscores, count_from_end=False)
else:
after = "0"
return f"{before}.{after}"
def format_int_string(text: str, allow_underscores: bool) -> str:
def format_int_string(
text: str, allow_underscores: bool, count_from_end: bool = True
) -> str:
"""Normalizes underscores in a string to e.g. 1_000_000.
Input must be a string of at least six digits and optional underscores.
Input must be a string of digits and optional underscores.
If count_from_end is False, we add underscores after groups of three digits
counting from the beginning instead of the end of the strings. This is used
for the fractional part of float literals.
"""
if not allow_underscores:
return text
@ -2573,9 +2584,12 @@ def format_int_string(text: str, allow_underscores: bool) -> str:
# No underscores for numbers <= 6 digits long.
return text
# Avoid removing leading zeros, which are important if we're formatting
# part of a number like "0.001".
return format(int("1" + text), "3_")[1:].lstrip("_")
if count_from_end:
# Avoid removing leading zeros, which are important if we're formatting
# part of a number like "0.001".
return format(int("1" + text), "3_")[1:].lstrip("_")
else:
return "_".join(text[i : i + 3] for i in range(0, len(text), 3))
def normalize_invisible_parens(node: Node, parens_after: Set[str]) -> None:

View File

@ -6,6 +6,7 @@
x = 1.
x = 1E+1
x = 1E-1
x = 1.00000001
x = 123456789.123456789
x = 123456789.123456789E123456789
x = 123456789E123456789
@ -27,6 +28,7 @@
x = 1.0
x = 1e1
x = 1e-1
x = 1.000_000_01
x = 123_456_789.123_456_789
x = 123_456_789.123_456_789e123_456_789
x = 123_456_789e123_456_789

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python2.7
x = 123456789L
x = 123456789l
x = 123456789
# output
@ -8,5 +9,6 @@
#!/usr/bin/env python2.7
x = 123456789l
x = 123456789L
x = 123456789L
x = 123456789