1""" 2Formatting numeric literals. 3""" 4from blib2to3.pytree import Leaf 5 6 7def format_hex(text: str) -> str: 8 """ 9 Formats a hexadecimal string like "0x12B3" 10 """ 11 before, after = text[:2], text[2:] 12 return f"{before}{after.upper()}" 13 14 15def format_scientific_notation(text: str) -> str: 16 """Formats a numeric string utilizing scentific notation""" 17 before, after = text.split("e") 18 sign = "" 19 if after.startswith("-"): 20 after = after[1:] 21 sign = "-" 22 elif after.startswith("+"): 23 after = after[1:] 24 before = format_float_or_int_string(before) 25 return f"{before}e{sign}{after}" 26 27 28def format_long_or_complex_number(text: str) -> str: 29 """Formats a long or complex string like `10L` or `10j`""" 30 number = text[:-1] 31 suffix = text[-1] 32 # Capitalize in "2L" because "l" looks too similar to "1". 33 if suffix == "l": 34 suffix = "L" 35 return f"{format_float_or_int_string(number)}{suffix}" 36 37 38def format_float_or_int_string(text: str) -> str: 39 """Formats a float string like "1.0".""" 40 if "." not in text: 41 return text 42 43 before, after = text.split(".") 44 return f"{before or 0}.{after or 0}" 45 46 47def normalize_numeric_literal(leaf: Leaf) -> None: 48 """Normalizes numeric (float, int, and complex) literals. 49 50 All letters used in the representation are normalized to lowercase (except 51 in Python 2 long literals). 52 """ 53 text = leaf.value.lower() 54 if text.startswith(("0o", "0b")): 55 # Leave octal and binary literals alone. 56 pass 57 elif text.startswith("0x"): 58 text = format_hex(text) 59 elif "e" in text: 60 text = format_scientific_notation(text) 61 elif text.endswith(("j", "l")): 62 text = format_long_or_complex_number(text) 63 else: 64 text = format_float_or_int_string(text) 65 leaf.value = text 66