# Path: graphite_beacon/utils.py
# def parse_rule(rule):
#     tokens = _tokenize_rule(rule)
#     level, initial_expr, exprs = _parse_rule(tokens)
# 
#     result = {'level': level, 'raw': rule, 'exprs': [_parse_expr(initial_expr)]}
# 
#     for logical_operator, expr in exprs:
#         result['exprs'].extend([logical_operator, _parse_expr(expr)])
# 
#     return result
# 
# Path: graphite_beacon/utils.py
# IDENTITY = lambda x: x
# 
# def convert_from_format(num, unit=None):
#     if not unit:
#         return float(num)
#     return float(num) * CONVERT_HASH.get(unit, 1)
# 
# def convert_to_format(value, frmt=None):
#     value = float(value)
#     units = CONVERT.get(frmt, [])
#     for name, size in units:
#         if size < value:
#             break
#     else:
#         return value
# 
#     value /= size  # pylint: disable=undefined-loop-variable
#     value = ("%.1f" % value).rstrip('0').rstrip('.')
#     return "{}{}".format(value, name)  # pylint: disable=undefined-loop-variable


import operator as op
import pytest
from funcparserlib.lexer import LexerError
from graphite_beacon.utils import parse_rule as parse_rule
from graphite_beacon.utils import (IDENTITY, convert_from_format,
                                   convert_to_format)
    assert convert_to_format(79456234, 'ms') == "22.1h"
    assert convert_to_format(34, 'ms') == "34ms"


def test_parse_rule():
    with pytest.raises(LexerError):
        assert parse_rule('invalid')

    assert parse_rule('normal: == 0') == {
        'level': 'normal', 'raw': 'normal: == 0',
        'exprs': [{'op': op.eq, 'value': 0, 'mod': IDENTITY}]}

    assert parse_rule('critical: < 30MB') == {
        'level': 'critical', 'raw': 'critical: < 30MB',
        'exprs': [{'op': op.lt, 'value': 31457280, 'mod': IDENTITY}]}

    assert parse_rule('warning: >= 30MB') == {
        'level': 'warning', 'raw': 'warning: >= 30MB',
        'exprs': [{'op': op.ge, 'value': 31457280, 'mod': IDENTITY}]}

    assert parse_rule('warning: >= historical') == {
        'level': 'warning', 'raw': 'warning: >= historical',
        'exprs': [{'op': op.ge, 'value': 'historical', 'mod': IDENTITY}]}

    assert parse_rule('warning: >= historical AND > 25') == {
        'level': 'warning', 'raw': 'warning: >= historical AND > 25',
        'exprs': [{'op': op.ge, 'value': 'historical', 'mod': IDENTITY},
                  op.and_,
                  {'op': op.gt, 'value': 25, 'mod': IDENTITY}]}


# Path: graphite_beacon/utils.py
# def parse_rule(rule):
#     tokens = _tokenize_rule(rule)
#     level, initial_expr, exprs = _parse_rule(tokens)
# 
#     result = {'level': level, 'raw': rule, 'exprs': [_parse_expr(initial_expr)]}
# 
#     for logical_operator, expr in exprs:
#         result['exprs'].extend([logical_operator, _parse_expr(expr)])
# 
#     return result
# 
# Path: graphite_beacon/utils.py
# IDENTITY = lambda x: x
# 
# def convert_from_format(num, unit=None):
#     if not unit:
#         return float(num)
#     return float(num) * CONVERT_HASH.get(unit, 1)
# 
# def convert_to_format(value, frmt=None):
#     value = float(value)
#     units = CONVERT.get(frmt, [])
#     for name, size in units:
#         if size < value:
#             break
#     else:
#         return value
# 
#     value /= size  # pylint: disable=undefined-loop-variable
#     value = ("%.1f" % value).rstrip('0').rstrip('.')
#     return "{}{}".format(value, name)  # pylint: disable=undefined-loop-variable


# Path: tests/unit/utils_test.py
import operator as op
import pytest
from funcparserlib.lexer import LexerError
from graphite_beacon.utils import parse_rule as parse_rule
from graphite_beacon.utils import (IDENTITY, convert_from_format,
                                   convert_to_format)

    assert convert_to_format(79456234, 'ms') == "22.1h"
    assert convert_to_format(34, 'ms') == "34ms"


def test_parse_rule():
    with pytest.raises(LexerError):
        assert parse_rule('invalid')

    assert parse_rule('normal: == 0') == {
        'level': 'normal', 'raw': 'normal: == 0',
        'exprs': [{'op': op.eq, 'value': 0, 'mod': IDENTITY}]}

    assert parse_rule('critical: < 30MB') == {
        'level': 'critical', 'raw': 'critical: < 30MB',
        'exprs': [{'op': op.lt, 'value': 31457280, 'mod': IDENTITY}]}

    assert parse_rule('warning: >= 30MB') == {
        'level': 'warning', 'raw': 'warning: >= 30MB',
        'exprs': [{'op': op.ge, 'value': 31457280, 'mod': IDENTITY}]}

    assert parse_rule('warning: >= historical') == {
        'level': 'warning', 'raw': 'warning: >= historical',
        'exprs': [{'op': op.ge, 'value': 'historical', 'mod': IDENTITY}]}

    assert parse_rule('warning: >= historical AND > 25') == {
        'level': 'warning', 'raw': 'warning: >= historical AND > 25',
        'exprs': [{'op': op.ge, 'value': 'historical', 'mod': IDENTITY},
                  op.and_,
                  {'op': op.gt, 'value': 25, 'mod': IDENTITY}]}


    rule = parse_rule('warning: >= historical * 1.2')