def make_numeric_range_choice(to_python, to_str):
    """
    Returns a Choice class that represents a numeric choice range,
    using the passed in 'to_python' and 'to_str' callables to do
    conversion to/from native data types.
    """
    @python_2_unicode_compatible
    @total_ordering
    class NumericRangeChoice(object):

        def __init__(self, values):
            # Values are instances of RangeEnd
            self.values = tuple(values)

        def display(self):
            return '-'.join([str(v.value) for v in self.values])

        @classmethod
        def from_param(cls, param):
            if param is None:
                return NullChoice

            vals = []
            for p in param.split('..', 1):
                inclusive = False
                if p.endswith('i'):
                    inclusive = True
                    p = p[:-1]

                try:
                    val = to_python(p)
                    vals.append(RangeEnd(val, inclusive))
                except __HOLE__:
                    raise ValueError()
            return cls(vals)

        def make_lookup(self, field_name):
            if self.values is None:
                return {field_name: None}
            elif len(self.values) == 1:
                return {field_name: self.values[0].value}
            else:
                start, end = self.values[0], self.values[1]
                return {field_name + '__gt' +
                        ('e' if start.inclusive else ''): start.value,
                        field_name + '__lt' +
                        ('e' if end.inclusive else ''): end.value}

        def __str__(self):
            return '..'.join([to_str(v.value) + ('i' if v.inclusive else '')
                              for v in self.values])

        def __repr__(self):
            return '<NumericRangeChoice %s>' % self

        def __eq__(self, other):
            return self.__cmp__(other) == 0

        def __lt__(self, other):
            return self.__cmp__(other) < 0

        def __cmp__(self, other):
            # 'greater' means more specific.
            if other is None:
                return cmp(self.values, ())
            else:
                if other is NullChoice:
                    return -1
                if len(self.values) != len(other.values):
                    # one value is more specific than two
                    return -cmp(len(self.values), len(other.values))
                elif len(self.values) == 1:
                    return 0
                else:
                    # Larger difference means less specific
                    return -cmp(self.values[1].value - self.values[0].value,
                                other.values[1].value - other.values[0].value)

    return NumericRangeChoice
dataset/ETHPy150Open ionelmc/django-easyfilters/src/django_easyfilters/filters.py/make_numeric_range_choice