# Path: smarkets/utils.py
# def memoized_by_args(*args):
#     """Create memoization decorator more efficient than one generated by memoized.
# 
#     The downside is default values are not supported and you need to declare the arguments manually.
# 
#     >>> def x(a, b):
#     ...     print('ping')
#     ...     return a + b
#     ...
#     >>> memx = memoized_by_args('a', 'b')(x)
#     >>> memx(1, 2)
#     ping
#     3
#     >>> memx(1, 2)
#     3
#     """
#     cache = {}  # noqa
#     exec_(
#         '''
# def decorator(fun):
#     @functools.wraps(fun)
#     def wrapper(%(args)s, cache=cache, fun=fun):
#         key = (%(args)s)
#         try:
#             return cache[key]
#         except KeyError:
#             value = cache[key] = fun(%(args)s)
#             return value
#     return wrapper''' % dict(args=', '.join(args)),
#         dict(cache=cache, functools=functools), locals())
#     return locals()['decorator']
# 
# def slots_repr(self):
#     """Generates object repr based on object's __slots__.
# 
#     Operates under assumption that __slots__ correspond to object's class' constructor
#     parameters.
#     """
#     return '%s(%s)' % (
#         type(self).__name__,
#         ', '.join('%s=%r' % (key, getattr(self, key)) for key in self.__slots__)
#     )


import bisect
import functools
import re
import six
from decimal import Decimal
from babel.numbers import format_percent
from smarkets.utils import memoized_by_args, slots_repr
            num, den = key
            left, right = val
            self.append(num, den, left, right)
        self._table.sort()

    def append(self, nfrom, nto, nhigh, nlow):
        for i in OddsTableEntry.from_raw(nfrom, nto, nhigh, nlow):
            self._table.append(i)

    def from_percent(self, percent):
        """Get the correct odds for a percentile price."""
        if not isinstance(percent, Decimal):
            raise Exception("Percent needs to be a Decimal object")
        i = bisect.bisect_left(self._table, percent)
        if i >= 0 and i < len(self._table):
            return self._table[i]
        elif i < 0:
            return self._table[0]
        else:
            return self._table[-1]


TABLE = OddsTable(_RAW_TABLE)
QUANT = Decimal('0.01')
ONE_HUNDRED = Decimal('100')


class Odds(object):
    __slots__ = ('percent',)


# Path: smarkets/utils.py
# def memoized_by_args(*args):
#     """Create memoization decorator more efficient than one generated by memoized.
# 
#     The downside is default values are not supported and you need to declare the arguments manually.
# 
#     >>> def x(a, b):
#     ...     print('ping')
#     ...     return a + b
#     ...
#     >>> memx = memoized_by_args('a', 'b')(x)
#     >>> memx(1, 2)
#     ping
#     3
#     >>> memx(1, 2)
#     3
#     """
#     cache = {}  # noqa
#     exec_(
#         '''
# def decorator(fun):
#     @functools.wraps(fun)
#     def wrapper(%(args)s, cache=cache, fun=fun):
#         key = (%(args)s)
#         try:
#             return cache[key]
#         except KeyError:
#             value = cache[key] = fun(%(args)s)
#             return value
#     return wrapper''' % dict(args=', '.join(args)),
#         dict(cache=cache, functools=functools), locals())
#     return locals()['decorator']
# 
# def slots_repr(self):
#     """Generates object repr based on object's __slots__.
# 
#     Operates under assumption that __slots__ correspond to object's class' constructor
#     parameters.
#     """
#     return '%s(%s)' % (
#         type(self).__name__,
#         ', '.join('%s=%r' % (key, getattr(self, key)) for key in self.__slots__)
#     )


# Path: smarkets/odds.py
import bisect
import functools
import re
import six
from decimal import Decimal
from babel.numbers import format_percent
from smarkets.utils import memoized_by_args, slots_repr

            num, den = key
            left, right = val
            self.append(num, den, left, right)
        self._table.sort()

    def append(self, nfrom, nto, nhigh, nlow):
        for i in OddsTableEntry.from_raw(nfrom, nto, nhigh, nlow):
            self._table.append(i)

    def from_percent(self, percent):
        """Get the correct odds for a percentile price."""
        if not isinstance(percent, Decimal):
            raise Exception("Percent needs to be a Decimal object")
        i = bisect.bisect_left(self._table, percent)
        if i >= 0 and i < len(self._table):
            return self._table[i]
        elif i < 0:
            return self._table[0]
        else:
            return self._table[-1]


TABLE = OddsTable(_RAW_TABLE)
QUANT = Decimal('0.01')
ONE_HUNDRED = Decimal('100')


class Odds(object):
    __slots__ = ('percent',)


    __repr__ = slots_repr