def handle_number(number): if 'E' in number: number, exp = number.split('E', 1) else: exp = None if '@' in number: if '.' in number and '0' in number: raise ValueError( 'Significant digit patterns can not contain ' '"@" or "0"') if '.' in number: integer, fraction = number.rsplit('.', 1) else: integer = number fraction = '' int_prec = parse_precision(integer) frac_prec = parse_precision(fraction) if exp: frac_prec = parse_precision(integer + fraction) exp_plus = exp.startswith('+') exp = exp.lstrip('+') exp_prec = parse_precision(exp) else: exp_plus = None exp_prec = None grouping = parse_grouping(integer) return (grouping, int_prec, frac_prec, exp_prec, exp_plus)
def test_parse_grouping(): assert numbers.parse_grouping('##') == (1000, 1000) assert numbers.parse_grouping('#,###') == (3, 3) assert numbers.parse_grouping('#,####,###') == (3, 4)
def test_parse_grouping(): assert numbers.parse_grouping('##') == (1000, 1000) assert numbers.parse_grouping('#,###') == (3, 3) assert numbers.parse_grouping('#,####,###') == (3, 4)
def parse_pattern(pattern): """Parse number format patterns""" if isinstance(pattern, NumberPattern): return pattern def _match_number(pattern): rv = number_re.search(pattern) if rv is None: raise ValueError('Invalid number pattern %r' % pattern) return rv.groups() # Do we have a negative subpattern? pattern = CLEAN_CURRENCY_RE.sub('\\1', pattern.replace('\\', '')) pattern = CLEAN_RE.sub('', pattern).strip().replace('_', ' ') if ';' in pattern: pattern, neg_pattern = pattern.split(';', 1) # maybe zero and text pattern neg_pattern = neg_pattern.split(';', 1)[0] pos_prefix, number, pos_suffix = _match_number(pattern) neg_prefix, _, neg_suffix = _match_number(neg_pattern) # TODO Do not remove from neg prefix neg_prefix = '-' + neg_prefix else: pos_prefix, number, pos_suffix = _match_number(pattern) neg_prefix = '-' + pos_prefix neg_suffix = pos_suffix if 'E' in number: number, exp = number.split('E', 1) else: exp = None if '@' in number: if '.' in number and '0' in number: raise ValueError('Significant digit patterns can not contain ' '"@" or "0"') if '.' in number: integer, fraction = number.rsplit('.', 1) else: integer = number fraction = '' def parse_precision(p): """Calculate the min and max allowed digits""" min = max = 0 for c in p: if c in '@0': min += 1 max += 1 elif c == '#': max += 1 elif c in ',. ': continue else: break return min, max int_prec = parse_precision(integer) frac_prec = parse_precision(fraction) if exp: frac_prec = parse_precision(integer + fraction) exp_plus = exp.startswith('+') exp = exp.lstrip('+') exp_prec = parse_precision(exp) else: exp_plus = None exp_prec = None grouping = parse_grouping(integer) number_pattern = ColorNumberPattern(pattern, (pos_prefix, neg_prefix), (pos_suffix, neg_suffix), grouping, int_prec, frac_prec, exp_prec, exp_plus) return number_pattern