From da6743fd6763fa87a2431079e91a5d7250d69d42 Mon Sep 17 00:00:00 2001 From: Casper Weiss Bang Date: Wed, 21 Oct 2020 17:26:57 +0200 Subject: [PATCH 1/8] Made hex lower case --- .gitignore | 5 ++++- .venv | 1 + src/black/__init__.py | 4 ++-- src/blib2to3/pytree.py | 2 +- test_requirements.txt | 4 +++- tests/data/numeric_literals.py | 4 ++-- tests/data/numeric_literals_py2.py | 4 ++-- tests/data/numeric_literals_skip_underscores.py | 6 +++--- 8 files changed, 18 insertions(+), 12 deletions(-) create mode 100644 .venv diff --git a/.gitignore b/.gitignore index 3207e72ae28..d479b62592f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +.venv/ + + .coverage _build .DS_Store @@ -15,4 +18,4 @@ src/_black_version.py .dmypy.json *.swp .hypothesis/ -venv/ \ No newline at end of file +venv/ diff --git a/.venv b/.venv new file mode 100644 index 00000000000..7e66a17d49c --- /dev/null +++ b/.venv @@ -0,0 +1 @@ +black diff --git a/src/black/__init__.py b/src/black/__init__.py index 24e9d4edaaa..3b002a846df 100644 --- a/src/black/__init__.py +++ b/src/black/__init__.py @@ -5178,9 +5178,9 @@ def normalize_numeric_literal(leaf: Leaf) -> None: # Leave octal and binary literals alone. pass elif text.startswith("0x"): - # Change hex literals to upper case. + # Change hex literals to lower case. before, after = text[:2], text[2:] - text = f"{before}{after.upper()}" + text = f"{before}{after.lower()}" elif "e" in text: before, after = text.split("e") sign = "" diff --git a/src/blib2to3/pytree.py b/src/blib2to3/pytree.py index 4b841b768e7..6dba3c7bb15 100644 --- a/src/blib2to3/pytree.py +++ b/src/blib2to3/pytree.py @@ -34,7 +34,7 @@ import sys from io import StringIO -HUGE: int = 0x7FFFFFFF # maximum repeat count, default max +HUGE: int = 0x7fffffff # maximum repeat count, default max _type_reprs: Dict[int, Union[Text, int]] = {} diff --git a/test_requirements.txt b/test_requirements.txt index 999d05c0106..5b9e3062638 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -1,4 +1,6 @@ pytest >= 6.0.1 pytest-mock >= 3.2.0 pytest-cases >= 2.1.2 -coverage >= 5.2.1 \ No newline at end of file +coverage >= 5.2.1 +aiohttp >= 3.3.2 +aiohttp-cors diff --git a/tests/data/numeric_literals.py b/tests/data/numeric_literals.py index 254da68d330..06b7f7758ee 100644 --- a/tests/data/numeric_literals.py +++ b/tests/data/numeric_literals.py @@ -12,7 +12,7 @@ x = 123456789E123456789 x = 123456789J x = 123456789.123456789J -x = 0XB1ACC +x = 0Xb1aCc x = 0B1011 x = 0O777 x = 0.000000006 @@ -36,7 +36,7 @@ x = 123456789e123456789 x = 123456789j x = 123456789.123456789j -x = 0xB1ACC +x = 0xb1acc x = 0b1011 x = 0o777 x = 0.000000006 diff --git a/tests/data/numeric_literals_py2.py b/tests/data/numeric_literals_py2.py index 8f85c43f265..8b2c7faa306 100644 --- a/tests/data/numeric_literals_py2.py +++ b/tests/data/numeric_literals_py2.py @@ -3,7 +3,7 @@ x = 123456789L x = 123456789l x = 123456789 -x = 0xb1acc +x = 0xB1aCc # output @@ -13,4 +13,4 @@ x = 123456789L x = 123456789L x = 123456789 -x = 0xB1ACC +x = 0xb1acc diff --git a/tests/data/numeric_literals_skip_underscores.py b/tests/data/numeric_literals_skip_underscores.py index e345bb90276..f83e23312f2 100644 --- a/tests/data/numeric_literals_skip_underscores.py +++ b/tests/data/numeric_literals_skip_underscores.py @@ -3,7 +3,7 @@ x = 123456789 x = 1_2_3_4_5_6_7 x = 1E+1 -x = 0xb1acc +x = 0xb1AcC x = 0.00_00_006 x = 12_34_567J x = .1_2 @@ -16,8 +16,8 @@ x = 123456789 x = 1_2_3_4_5_6_7 x = 1e1 -x = 0xB1ACC +x = 0xb1acc x = 0.00_00_006 x = 12_34_567j x = 0.1_2 -x = 1_2.0 \ No newline at end of file +x = 1_2.0 From a607ada90c0a399eec0765166caec4fbea52c3a2 Mon Sep 17 00:00:00 2001 From: Casper Weiss Bang Date: Wed, 21 Oct 2020 18:03:50 +0200 Subject: [PATCH 2/8] Refactored numeric formatting section --- src/black/__init__.py | 96 ++++++++++++++++++++++++++++++++----------- 1 file changed, 71 insertions(+), 25 deletions(-) diff --git a/src/black/__init__.py b/src/black/__init__.py index 3b002a846df..9581dd0a2cb 100644 --- a/src/black/__init__.py +++ b/src/black/__init__.py @@ -69,7 +69,8 @@ DEFAULT_INCLUDES = r"\.pyi?$" CACHE_DIR = Path(user_cache_dir("black", version=__version__)) -STRING_PREFIX_CHARS: Final = "furbFURB" # All possible string prefix characters. +# All possible string prefix characters. +STRING_PREFIX_CHARS: Final = "furbFURB" # types @@ -1901,7 +1902,8 @@ def line(self, indent: int = 0) -> Iterator[Line]: """ if not self.current_line: self.current_line.depth += indent - return # Line is empty, don't emit. Creating a new one unnecessary. + # Line is empty, don't emit. Creating a new one unnecessary. + return complete_line = self.current_line self.current_line = Line(depth=complete_line.depth + indent) @@ -5174,35 +5176,78 @@ def normalize_numeric_literal(leaf: Leaf) -> None: in Python 2 long literals). """ text = leaf.value.lower() - if text.startswith(("0o", "0b")): + if is_oct_or_binary(text): # Leave octal and binary literals alone. pass - elif text.startswith("0x"): - # Change hex literals to lower case. - before, after = text[:2], text[2:] - text = f"{before}{after.lower()}" - elif "e" in text: - before, after = text.split("e") - sign = "" - if after.startswith("-"): - after = after[1:] - sign = "-" - elif after.startswith("+"): - after = after[1:] - before = format_float_or_int_string(before) - text = f"{before}e{sign}{after}" - 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)}{suffix}" + elif is_hex(text): + text = format_hex(text) + elif is_scientific_notation(text): + text = format_scientific_notation(text) + elif is_long_or_complex_number(text): + text = format_long_or_complex_number(text) else: text = format_float_or_int_string(text) leaf.value = text +def is_oct_or_binary(text: str) -> bool: + """ + Checks if the supplied string is a number with octal or binary notation + """ + return text.startswith(("0o", "0b")) + + +def is_hex(text: str) -> bool: + """Checks if the supplied string is a number with hexadecimal notation""" + return text.startswith("0x") + + +def format_hex(text: str) -> str: + """ + Formats a hexidecimal strign like "0x12b3" + + Uses lowercase because of similarity between "B" and "8", which + can cause security issues. + see: https://github.com/psf/black/issues/1692 + """ + + before, after = text[:2], text[2:] + return f"{before}{after.lower()}" + + +def is_scientific_notation(text: str) -> bool: + """Checks if the supplied string is a number with scientific notation""" + return "e" in text + + +def format_scientific_notation(text: str) -> str: + """Formats a numeric string utilizing scentific notation""" + before, after = text.split("e") + sign = "" + if after.startswith("-"): + after = after[1:] + sign = "-" + elif after.startswith("+"): + after = after[1:] + before = format_float_or_int_string(before) + return f"{before}e{sign}{after}" + + +def is_long_or_complex_number(text: str) -> bool: + """Checks if the supplied string is a long or complex number string""" + return text.endswith(("j", "l")) + + +def format_long_or_complex_number(text: str) -> str: + """Formats a long or complex string like `10L` or `10j`""" + number = text[:-1] + suffix = text[-1] + # Capitalize in "2L" because "l" looks too similar to "1". + if suffix == "l": + suffix = "L" + return f"{format_float_or_int_string(number)}{suffix}" + + def format_float_or_int_string(text: str) -> str: """Formats a float string like "1.0".""" if "." not in text: @@ -5296,7 +5341,8 @@ def convert_one_fmt_off_pair(node: Node) -> bool: if not ignored_nodes: continue - first = ignored_nodes[0] # Can be a container node with the `leaf`. + # Can be a container node with the `leaf`. + first = ignored_nodes[0] parent = first.parent prefix = first.prefix first.prefix = prefix[comment.consumed :] From 0758897f03495d077152f8721896a86a30832bc7 Mon Sep 17 00:00:00 2001 From: Casper Weiss Bang Date: Thu, 22 Oct 2020 13:25:50 +0200 Subject: [PATCH 3/8] Redid some refactoring and removed bloat --- .gitignore | 4 +--- .venv | 1 - src/black/__init__.py | 9 +++------ 3 files changed, 4 insertions(+), 10 deletions(-) delete mode 100644 .venv diff --git a/.gitignore b/.gitignore index d479b62592f..30225ec7764 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,4 @@ -.venv/ - - +.venv .coverage _build .DS_Store diff --git a/.venv b/.venv deleted file mode 100644 index 7e66a17d49c..00000000000 --- a/.venv +++ /dev/null @@ -1 +0,0 @@ -black diff --git a/src/black/__init__.py b/src/black/__init__.py index 9581dd0a2cb..81ae5f9d98c 100644 --- a/src/black/__init__.py +++ b/src/black/__init__.py @@ -69,8 +69,7 @@ DEFAULT_INCLUDES = r"\.pyi?$" CACHE_DIR = Path(user_cache_dir("black", version=__version__)) -# All possible string prefix characters. -STRING_PREFIX_CHARS: Final = "furbFURB" +STRING_PREFIX_CHARS: Final = "furbFURB" # All possible string prefix characters. # types @@ -1902,8 +1901,7 @@ def line(self, indent: int = 0) -> Iterator[Line]: """ if not self.current_line: self.current_line.depth += indent - # Line is empty, don't emit. Creating a new one unnecessary. - return + return # Line is empty, don't emit. Creating a new one unnecessary. complete_line = self.current_line self.current_line = Line(depth=complete_line.depth + indent) @@ -5341,8 +5339,7 @@ def convert_one_fmt_off_pair(node: Node) -> bool: if not ignored_nodes: continue - # Can be a container node with the `leaf`. - first = ignored_nodes[0] + first = ignored_nodes[0] # Can be a container node with the `leaf`. parent = first.parent prefix = first.prefix first.prefix = prefix[comment.consumed :] From d7339e81b0d964001f7f82e4e7853779a3b4b347 Mon Sep 17 00:00:00 2001 From: Casper Weiss Bang Date: Thu, 22 Oct 2020 21:14:47 +0200 Subject: [PATCH 4/8] Removed additions from test_requirements.txt --- test_requirements.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test_requirements.txt b/test_requirements.txt index 5b9e3062638..70062309d8c 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -2,5 +2,4 @@ pytest >= 6.0.1 pytest-mock >= 3.2.0 pytest-cases >= 2.1.2 coverage >= 5.2.1 -aiohttp >= 3.3.2 -aiohttp-cors + From ffff68772f1ba974ff67406d5e31c0c2659e7138 Mon Sep 17 00:00:00 2001 From: Casper Weiss Bang Date: Fri, 23 Oct 2020 11:53:17 +0200 Subject: [PATCH 5/8] Primer now expects expected changes --- src/black_primer/primer.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/black_primer/primer.json b/src/black_primer/primer.json index cdc863ca032..32df01571a7 100644 --- a/src/black_primer/primer.json +++ b/src/black_primer/primer.json @@ -10,7 +10,7 @@ }, "attrs": { "cli_arguments": [], - "expect_formatting_changes": false, + "expect_formatting_changes": true, "git_clone_url": "https://github.com/python-attrs/attrs.git", "long_checkout": false, "py_versions": ["all"] @@ -47,7 +47,7 @@ }, "hypothesis": { "cli_arguments": [], - "expect_formatting_changes": false, + "expect_formatting_changes": true, "git_clone_url": "https://github.com/HypothesisWorks/hypothesis.git", "long_checkout": false, "py_versions": ["all"] @@ -63,7 +63,7 @@ }, "pillow": { "cli_arguments": [], - "expect_formatting_changes": false, + "expect_formatting_changes": true, "git_clone_url": "https://github.com/python-pillow/Pillow.git", "long_checkout": false, "py_versions": ["all"] @@ -77,7 +77,7 @@ }, "pyramid": { "cli_arguments": [], - "expect_formatting_changes": false, + "expect_formatting_changes": true, "git_clone_url": "https://github.com/Pylons/pyramid.git", "long_checkout": false, "py_versions": ["all"] @@ -112,7 +112,7 @@ }, "virtualenv": { "cli_arguments": [], - "expect_formatting_changes": false, + "expect_formatting_changes": true, "git_clone_url": "https://github.com/pypa/virtualenv.git", "long_checkout": false, "py_versions": ["all"] From 4aa80bc58556479acf321a759f9fc2bca7e5adad Mon Sep 17 00:00:00 2001 From: Casper Weiss Bang Date: Sat, 24 Oct 2020 13:55:08 +0200 Subject: [PATCH 6/8] Undid some refactoring --- src/black/__init__.py | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/src/black/__init__.py b/src/black/__init__.py index 81ae5f9d98c..36f4a453f5a 100644 --- a/src/black/__init__.py +++ b/src/black/__init__.py @@ -5174,32 +5174,20 @@ def normalize_numeric_literal(leaf: Leaf) -> None: in Python 2 long literals). """ text = leaf.value.lower() - if is_oct_or_binary(text): + if text.startswith(("0o", "0b")): # Leave octal and binary literals alone. pass - elif is_hex(text): + elif text.startswith("0x"): text = format_hex(text) - elif is_scientific_notation(text): + elif "e" in text: text = format_scientific_notation(text) - elif is_long_or_complex_number(text): + elif text.endswith(("j", "l")): text = format_long_or_complex_number(text) else: text = format_float_or_int_string(text) leaf.value = text -def is_oct_or_binary(text: str) -> bool: - """ - Checks if the supplied string is a number with octal or binary notation - """ - return text.startswith(("0o", "0b")) - - -def is_hex(text: str) -> bool: - """Checks if the supplied string is a number with hexadecimal notation""" - return text.startswith("0x") - - def format_hex(text: str) -> str: """ Formats a hexidecimal strign like "0x12b3" @@ -5213,11 +5201,6 @@ def format_hex(text: str) -> str: return f"{before}{after.lower()}" -def is_scientific_notation(text: str) -> bool: - """Checks if the supplied string is a number with scientific notation""" - return "e" in text - - def format_scientific_notation(text: str) -> str: """Formats a numeric string utilizing scentific notation""" before, after = text.split("e") @@ -5231,11 +5214,6 @@ def format_scientific_notation(text: str) -> str: return f"{before}e{sign}{after}" -def is_long_or_complex_number(text: str) -> bool: - """Checks if the supplied string is a long or complex number string""" - return text.endswith(("j", "l")) - - def format_long_or_complex_number(text: str) -> str: """Formats a long or complex string like `10L` or `10j`""" number = text[:-1] From 831343b00c7f10b0f439c778c7ee106b6d51d023 Mon Sep 17 00:00:00 2001 From: Casper Weiss Bang Date: Wed, 28 Oct 2020 22:01:57 +0100 Subject: [PATCH 7/8] added to changelog --- CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index dfc54224b41..25c4ece6b87 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -21,6 +21,8 @@ - Added support for PEP 614 relaxed decorator syntax on python 3.9 (#1711) +- use lowercase hex strings (#1692) + ### 20.8b1 #### _Packaging_ From cf0752598d933d5a3daceb0f176886aad2c2cdbf Mon Sep 17 00:00:00 2001 From: Casper Weiss Bang Date: Fri, 30 Oct 2020 13:38:29 +0100 Subject: [PATCH 8/8] Update src/black/__init__.py Co-authored-by: Zsolt Dollenstein --- src/black/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/black/__init__.py b/src/black/__init__.py index 36f4a453f5a..cb87c4ace82 100644 --- a/src/black/__init__.py +++ b/src/black/__init__.py @@ -5190,7 +5190,7 @@ def normalize_numeric_literal(leaf: Leaf) -> None: def format_hex(text: str) -> str: """ - Formats a hexidecimal strign like "0x12b3" + Formats a hexadecimal string like "0x12b3" Uses lowercase because of similarity between "B" and "8", which can cause security issues.