Exemple #1
0
        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)
Exemple #2
0
def test_parse_grouping():
    assert numbers.parse_grouping('##') == (1000, 1000)
    assert numbers.parse_grouping('#,###') == (3, 3)
    assert numbers.parse_grouping('#,####,###') == (3, 4)
Exemple #3
0
def test_parse_grouping():
    assert numbers.parse_grouping('##') == (1000, 1000)
    assert numbers.parse_grouping('#,###') == (3, 3)
    assert numbers.parse_grouping('#,####,###') == (3, 4)
Exemple #4
0
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