コード例 #1
0
class Threshold(object):
    """
    A wrapper for a bucket threshold value. Ensures proper serialization
    between ElasticSearch and the JSON API eloggingndpoints.
    """
    __slots__ = ('_value', )

    def __init__(self, value):
        if isinstance(value, Threshold):
            assert isinstance(value._value, Decimal)
            # Clone the other Threshold.
            self._value = value._value
            return
        elif isinstance(value, Decimal):
            self._value = value
            return
        elif isinstance(value, string_types):
            value = value.replace('_', '.')
        elif isinstance(value, float):
            pass
        else:
            raise TypeError("Expected type %s but got %s" %
                            (text_type, repr(value)))

        self._value = Decimal(value).quantize(Decimal('0.1'))

    def __str__(self):
        result = str(self._value)
        assert '_' not in result
        # Ensure that rounded values are always displayed with at least one
        # decimal, for aesthetics.
        if '.' not in result:
            return result + '.0'
        return result

    def __repr__(self):
        return "Threshold('" + str(self) + "')"

    def to_float(self):
        return float(self)

    def __float__(self):
        """
        Convert the threshold to a floating point number, for comparisons.
        Note that this should NOT be converted back to a threshold, as there
        may be a loss of data by doing the round trip.
        """
        return float(self._value)

    def __getattr__(self, attr):
        # Delegate everything (i.e, comparisons) to the actual Threshold
        # value.
        return getattr(self._value, attr)

    def __hash__(self):
        return self._value.__hash__() + 1

    def __eq__(self, otter):
        if not isinstance(otter, Threshold):
            return False
        return self._value == otter._value

    def to_elasticsearch(self):
        """
        Converts the threshold to a string, suitable for serialization as an
        ElasticSearch field name. Note that full stops ('.') are verbotten in
        ElasticSearch field names.
        """        #elif isinstance(o, Bucket):
        #o.check()
        #return o.as_dict()
        #elif isinstance(o, TopMatch):
        #return o.as_dict()

        str_value = str(self)
        assert isinstance(self._value, Decimal)
        assert str_value.count('.') == 1, 'Invalid decimal number'
        return str_value.replace('.', '_')

    def __lt__(self, other):
        return float(self._value) < float(other._value)

    def __deepcopy__(self, memo):
        return Threshold(copy(self._value))

    def jsonify(self):
        return text_type(self._value)
コード例 #2
0
ファイル: power.py プロジェクト: choppsv1/opticalutil
class Decibel(object):
    @classmethod
    def from_factor(cls, gain_factor, context=pcontext):
        """Create a Decibel object give the gain factor.
        >>> Decibel.from_factor(1)
        Decibel('0.000000')
        >>> Decibel.from_factor(3)
        Decibel('4.771213')
        """
        return cls(mwatt2db(gain_factor))

    @classmethod
    def from_10ths_db(cls, inval):
        """
        >>> dB = Decibel.from_10ths_db(22)
        >>> str(dB)
        '2.20'
        >>> dB = Decibel.from_10ths_db(None)
        >>> str(dB)
        'None'
        """
        if inval is None or inval == "None":
            dB = None
        else:
            dB = Decibel(inval).dB / D(10)
        return cls(dB)

    @classmethod
    def from_100ths_db(cls, inval):
        """
        >>> dB = Decibel.from_100ths_db(202)
        >>> str(dB)
        '2.02'
        >>> dB = Decibel.from_10ths_db(None)
        >>> str(dB)
        'None'
        """
        if inval is None or inval == "None":
            dB = None
        else:
            dB = D(inval) / D(100)
        return cls(dB)

    def __init__(self, dB):
        if dB is None or (is_str(dB) and dB == "None"):
            self.dB = None
        else:
            try:
                dB = dB.replace('dB', '')
            except AttributeError:
                pass
            if isinstance(dB, Decibel):
                self.dB = dB.dB
            else:
                self.dB = Decimal(dB).quantize(SIXPLACES, rounding=ROUND_HALF_EVEN)

    def __repr__(self):
        """
        >>> Decibel(1)
        Decibel('1.000000')
        >>> Decibel(.01)
        Decibel('0.010000')
        >>> Decibel(None)
        Decibel(None)
        >>> Decibel("None")
        Decibel(None)
        """
        if self.dB is None:
            return "Decibel(None)"
        return "Decibel('{}')".format(self.dB)

    def __hash__(self):
        return self.dB.__hash__()

    def __float__(self):
        return float(self.dB)

    def __format__(self, format_spec):  # pylint: disable=W0221
        """
        >>> str("{:+2.2f}".format(Decibal(100)))
        '+100.00'
        >>> str("{:+2.2f}".format(Decibal(0)))
        '+0.00'
        >>> str("{:+2.2f}".format(Decibal(None)))
        'None'
        """
        if self.dB is None:
            # XXX really want to format this.
            return "None"
        return self.dB.__format__(format_spec)

    def __str__(self):  # pylint: disable=W0222
        """
        >>> str(Decibel(0))
        '0.00'
        >>> str(Decibel(3.141596))
        '3.14'
        >>> str(Decibel(-3.999))
        '-4.00'
        >>> str(Decibel(None))
        'None'
        """
        if self.dB is None:
            return "None"
        else:
            return "{:.2f}".format(self.dB)

    def __abs__(self):
        if self.dB is None:
            return Decibel(None)
        elif self.dB < 0:
            return Decibel(self.dB.__neg__())
        else:
            return Decibel(self.dB)

    def __neg__(self):  # pylint: disable=W0222
        """
        >>> str(-Decibel(1))
        '-1.00'
        >>> str(-Decibel(-1))
        '1.00'
        """
        if self.dB is None:
            return Decibel(None)
        return Decibel(self.dB.__neg__())

    def __add__(self, add_atten):  # pylint: disable=W0221
        """
        >>> Decibel(1) + Decibel(3)
        Decibel('4.000000')
        >>> Decibel(-1) + 3
        Decibel('2.000000')
        """
        if hasattr(add_atten, "dB"):
            return Decibel(self.dB + add_atten.dB)
        else:
            return Decibel(self.dB + add_atten)

    def __sub__(self, sub_atten):  # pylint: disable=W0221
        """
        >>> Decibel(1) - Decibel(3)
        Decibel('-2.000000')
        >>> Decibel(2) - 1
        Decibel('1.000000')
        """
        if hasattr(sub_atten, "dB"):
            return Decibel(self.dB - sub_atten.dB)
        else:
            return Decibel(self.dB - sub_atten)

    def __mul__(self, other):  # pylint: disable=W0222
        """
        >>> Decibel(.5) * 20
        Decibel('10.000000')
        """
        if self.dB is None or other is None:
            return Decibel(None)
        if hasattr(other, "dB") and other.dB is None:
            return Decibel(None)
        return Decibel(self.dB * other)

    __rmul__ = __mul__

    def __lt__(self, other):
        """
        >>> Gain(0) > Gain(.1)
        False
        >>> Gain(.1) > Gain(0)
        True
        >>> Gain(0) < Gain(.1)
        True
        >>> Gain(.1) < Gain(0)
        False
        >>> Gain(0) == Gain(0)
        True
        >>> Gain(.1) == Gain(.1)
        True
        >>> Gain(0) != Gain(None)
        True
        >>> Gain(0) == Gain(None)
        False
        >>> Gain(None) == Gain(None)
        True
        >>> Gain(None) >= Gain(-50)
        False
        >>> Gain(None) < Gain(-50)
        True
        >>> Gain(None) <= Gain(-50)
        True
        """
        if self.dB is None:
            if other is None or other == "None":
                return False
            if hasattr(other, "dB") and other.dB is None:
                return False
            # other is not None so it's greater
            return True
        elif other is None or other == "None" or (hasattr(other, "dB") and other.dB is None):
            # self is not None other is so False
            return False
        return float(self.dB) < float(other)

    def __eq__(self, other):
        if self.dB is None:
            if other is None or other == "None":
                return True
            if hasattr(other, "dB") and other.dB is None:
                return True
            return False
        elif other is None or other == "None" or (hasattr(other, "dB") and other.dB is None):
            return self.dB is None
        return float(self.dB) == float(other)

    def gain_factor(self):
        """Convert gain value to mwatt for multiplying
        >>> Decibel(0).gain_factor()
        Decimal('1.000000')
        >>> Decibel(13).gain_factor()
        Decimal('19.952623')
        """
        #
        # Gain: x dB = 10 * log10(multiplier)
        # 10 ^ (x dB / 10) = 10^(log10(multiplier))
        # 10 ^ (x dB / 10) = multiplier
        #
        rv = Decimal(10 ** (self.dB / 10), pcontext)
        rv = rv.quantize(SIXPLACES, rounding=ROUND_HALF_EVEN)
        return rv

    mwatt_ratio = gain_factor

    def ase(self, nf, for_osnr=False):
        """Calculate ASE generated by amplification

        >>> Gain(23).ase(5.5)
        Power('-3.461412')
        """
        # Pase = hv(G -1) * NF * B0
        if not for_osnr:
            B0 = D('5.00e+12')  # all c-band (for .5nm)
        else:
            B0 = D('1.25e+10')  # @0.1nm resolution
        v = D('1.93e+14')  # speed of light
        h = D('6.63e-34')  # planck's constant
        nf = db2mwatt(nf)  # convert noise figure from dB to mwatts
        ase_watts = D(nf) * B0 * h * v * (self.mwatt_ratio() - 1)
        return Power.from_mwatt(ase_watts * 1000)

    def osnr(self, nf, powerin):
        """Calculate OSNR for .1nm signal

        >>> Gain(16).osnr(7.9, Power(-20))
        Decibel('30.170675')
        """

        # Psig = Pin * G
        # Pase = hv(G - 1) * NF * B0.1nm
        # OSNR = Psig / Pase
        psig = powerin + self
        pase = self.ase(nf, True)
        return psig - pase
コード例 #3
0
ファイル: power.py プロジェクト: choppsv1/opticalutil
class Power(object):
    """Optical power value act's mostly like a float"""

    @classmethod
    def from_xml(cls, entry, xpath=None):
        if entry is not None and xpath is not None:
            entry = entry.find(xpath)
        if entry is None:
            return Power(None)
        try:
            return Power(entry.text)
        except ValueError:
            return Power(None)

    @classmethod
    def from_10uwatt(cls, mwatt):
        return cls.from_mwatt(D(mwatt) / 10000)

    @classmethod
    def from_10ths_dbm(cls, inval):
        dB = D(inval) / D(10)
        return cls(dB)

    from_10ths_db = from_10ths_dbm

    @classmethod
    def from_100ths_dbm(cls, inval):
        dB = D(inval) / D(100)
        return cls(dB)

    from_100ths_db = from_100ths_dbm

    @classmethod
    def from_mwatt(cls, mwatt):
        """
        >>> Power.from_mwatt(D(0))
        Power(None)
        >>> Power.from_mwatt(2)
        Power('3.010300')
        >>> Power.from_mwatt(1)
        Power('0.000000')
        >>> Power.from_mwatt(.5)
        Power('-3.010300')
        """
        if mwatt is None:
            return cls(None)
        if not mwatt:
            return cls(None)
        try:
            # Try and convert to float first to catch '0.00' case
            if not float(mwatt):
                return cls(None)
        except ValueError:
            pass

        dBm = D(10, pcontext) * D(mwatt).log10(pcontext)
        dBm = dBm.quantize(SIXPLACES, rounding=ROUND_HALF_EVEN)
        return cls(dBm)

    def __init__(self, dBm, context=pcontext):  # pylint: disable=W0222
        """
        >>> Power(20).mwatt()
        Decimal('100.000000')
        >>> Power(10).mwatt()
        Decimal('10.000000')
        >>> Power(3).mwatt()
        Decimal('1.995262')
        >>> Power(1).mwatt()
        Decimal('1.258925')
        >>> Power(0).mwatt()
        Decimal('1.000000')
        >>> Power(None).mwatt()
        0
        >>> Power('None').mwatt()
        0
        """
        if dBm is None or (is_str(dBm) and dBm == "None"):
            self.dBm = None
        else:
            try:
                if dBm.endswith('dBm'):
                    dBm = dBm.replace('dBm', '')
            except AttributeError:
                pass
            if isinstance(dBm, Power):
                self.dBm = dBm.dBm
            else:
                self.dBm = Decimal(dBm, context).quantize(SIXPLACES, rounding=ROUND_HALF_EVEN)

    def mwatt(self):
        if self.dBm is None:
            return 0
        # XXX get context from us not global
        rv = Decimal(10 ** (self.dBm / 10), pcontext)
        rv = rv.quantize(SIXPLACES, rounding=ROUND_HALF_EVEN)
        return rv

    def __hash__(self):
        return self.dBm.__hash__()

    def __format__(self, format_spec):  # pylint: disable=W0221
        """
        >>> str("{:+2.2f}".format(Power(100)))
        '+100.00'
        >>> str("{:+2.2f}".format(Power(0)))
        '+0.00'
        >>> str("{:+2.2f}".format(Power(None)))
        'None'
        """
        if self.dBm is None:
            return "None"
        return self.dBm.__format__(format_spec)

    def __bool__(self):
        return self.dBm is not None

    def __nonzero__(self):
        return self.dBm is not None

    def __add__(self, gain):  # pylint: disable=W0221
        """
        >>> Power(0) + Gain(1)
        Power('1.000000')
        """
        if hasattr(gain, "dBm"):
            raise TypeError("unsupported operand type(s) for +: 'Power' and 'Power'")
        else:
            return self.add_gain(gain)

    def __sub__(self, power_or_gain):  # pylint: disable=W0221
        """
        >>> Power(0) - Gain(1)
        Power('-1.000000')
        >>> Power(0) - Power(2)
        Decibel('-2.000000')
        >>> Power(3) - Power(0)
        Decibel('3.000000')
        """
        try:
            dBm = power_or_gain.dBm
            return Gain(self.dBm - dBm)
        except AttributeError:
            return self.add_gain(-power_or_gain)

    def __lt__(self, other):
        """
        >>> Power(0) > Power(.1)
        False
        >>> Power(.1) > Power(0)
        True
        >>> Power(0) < Power(.1)
        True
        >>> Power(.1) < Power(0)
        False
        >>> Power(0) == Power(0)
        True
        >>> Power(.1) == Power(.1)
        True
        >>> Power(0) != Power(None)
        True
        >>> Power(0) == Power(None)
        False
        >>> Power(None) == Power(None)
        True
        >>> Power(None) >= Power(-50)
        False
        >>> Power(None) < Power(-50)
        True
        >>> Power(None) <= Power(-50)
        True
        >>> Power(0) == None
        False
        >>> Power(None) == None
        True
        >>> Power(0) != None
        True
        >>> Power(None) == None
        True
        >>> Power(0) is None
        False
        >>> Power(None) is None
        False
        >>> Power(0) is not None
        True
        >>> Power(None) is not None
        True
        """
        # Either we are None (not less than) or more than None.
        if other is None:
            return False
        mwatt = self.mwatt()
        try:
            return mwatt < other.mwatt()
        except AttributeError:
            return mwatt < Power(D(other)).mwatt()

    def __eq__(self, other):
        if other is None:
            return self.dBm is None
        mwatt = self.mwatt()
        try:
            return mwatt == other.mwatt()
        except AttributeError:
            return mwatt == Power(D(other)).mwatt()

    def __repr__(self):
        """
        >>> Power(0)
        Power('0.000000')
        >>> Power(.01)
        Power('0.010000')
        >>> Power(None)
        Power(None)
        >>> Power("None")
        Power(None)
        """
        if self.dBm is None:
            return "Power(None)"
        return "Power('{}')".format(str(self.dBm))

    def __str__(self):
        """
        >>> str(Power(0))
        '0.00'
        """
        if self.dBm is None:
            return "None"
        else:
            return "{:.2f}".format(self.dBm)

    def __truediv__(self, other):  # pylint: disable=W0221
        return self.__div__(other)

    def __floordiv__(self, other):  # pylint: disable=W0221
        return self.__div__(other)

    def __div__(self, divisor):
        """
        >>> Power(0) / 16 / 6
        Power('-19.822712')
        >>> Power(0) / 10
        Power('-10.000000')
        >>> Power(0) / 8
        Power('-9.030900')
        >>> Power(0) / 6
        Power('-7.781513')
        >>> Power(0) / 4
        Power('-6.020600')
        >>> Power(0) / 2
        Power('-3.010300')
        >>> Power(3) / 2
        Power('-0.010301')
        """
        return Power.from_mwatt(self.mwatt() / divisor)

    def __mul__(self, multiplier):
        return Power.from_mwatt(self.mwatt() * multiplier)

    def __or__(self, other):
        """
        # Check str() here it's very different
        >>> Power(0) | Power(0)
        Power('3.010300')
        """
        return Power.from_mwatt(self.mwatt() + other.mwatt())

    def add_gain(self, gain):
        # XXX hmm not sure about adding None to power.
        if self.dBm is None or gain is None:
            return Power(None)
        return Power(self.dBm + gain.dB)

    def get_delta(self, other):
        if self.dBm is None or other is None:
            return Gain(None)
        return Gain(other.dBm - self.dBm)
コード例 #4
0
ファイル: Price.py プロジェクト: AgalmicVentures/Buttonwood
class Price(object):
    def __init__(
        self, price_value,
        precision=Decimal(".111111111111111")):  # precision defaults to 15
        if isinstance(price_value, Decimal):
            self.__value = price_value
        elif isinstance(price_value, float):
            self.__value = Decimal(price_value).quantize(
                precision, rounding=decimal.ROUND_HALF_UP)
        else:
            self.__value = Decimal(price_value)
        self.__hash = self.__value.__hash__()
        self.__float_value = float(self.__value)
        self.__precision = precision

    def better_than(self, other_price, side):
        """
        Determines if this price is better than the passed in price. Returns True if it is and False if it isn't.
        The determination is made using the passed in side:
           *if side is bid then better than means a higher price
           *if side is ask then better than means a lower price
           *if side is other then there is no such thing as a better price so the return is False
        
        :param other_price: Price. the price you are comparing to
        :param side: Side. the side used for the comparison
        :return: boolean
        """
        assert isinstance(side, Side), "side should be MarketObjects.Side.Side"
        # if this price is a bid it is better than otherPrice if greater than

        if side.is_bid():
            return self > other_price
        # otherwise price is an ask and it is better than otherPrice if less than
        else:
            return self < other_price

    def better_or_same_as(self, other_price, side):
        """
        Determines if this price is better than or same as the passed in price.
        Returns True if it is and False if it isn't.
        The determination is made using the passed in side:
           *if side is bid then better than means a higher price
           *if side is ask then better than means a lower price
           *if side is other then there is no such thing as a better price so the return is False
        
        :param other_price: Price. the price you are comparing to
        :param side: Side. the side used for the comparison
        :return: boolean
        """
        return True if other_price == self else self.better_than(
            other_price, side)

    def worse_than(self, other_price, side):
        """
        Determines if this price is worse than the passed in price.
        Returns True if it is and False if it isn't.
        The determination is made using the passed in side:
           *if side is bid then worse than means a lower price
           *if side is ask then worse than means a higher price
           *if side is other then there is no such thing as a worse price so the return is False
        
        :param other_price: Price. the price you are comparing to
        :param side: Side. the side used for the comparison
        :return: boolean
        """
        assert isinstance(
            other_price,
            Price), "other_price should be MarketObjects.Price.Price"
        assert isinstance(side, Side), "side should be MarketObjects.Side.Side"
        # if this price is a bid it is worse than otherPrice if less than
        if side.is_bid():
            return self < other_price
        # otherwise price is an ask and it is worse than otherPrice if greater than
        else:
            return self > other_price

    def worse_or_same_as(self, other_price, side):
        """
        Determines if this price is worse than or same as the passed in price.
        Returns True if it is and False if it isn't.
        The determination is made using the passed in side:
           *if side is bid then worse than means a lower price
           *if side is ask then worse than means a higher price
           *if side is other then there is no such thing as a worse price so the return is False

        :param other_price: Price. the price you are comparing to
        :param side: Side. the side used for the comparison
        :return: boolean
        """
        return True if other_price == self else self.worse_than(
            other_price, side)

    def ticks_behind(self, other_price, side, market):
        """
        For bids it subtracts its own price from the other price and divides by mpi
  
        For asks it subtracts the other price from its own price and divides by mpi.
  
        The result is if the other price is a better price then we get a positive
         number and if the other price is a worse price, we get a negative number.
  
        If otherprice is none it returns None
        :param other_price: MarketObjects.Price.Price the price you are comparing too
        :param side: MMarketObjects.Side.Side side of the market the comparison is happening on
        :param market: MarketObjects.Market.Market
        :return: float Can be None
        """
        if other_price is None:
            return None

        if side.is_bid():
            ticks_behind = (other_price - self) / market.mpi()
        else:
            ticks_behind = (self - other_price) / market.mpi()
        return float(ticks_behind)

    def __hash__(self):
        return self.__hash

    def __repr__(self):
        return self.__value.__repr__()

    def __str__(self):
        return self.__value.__str__()

    def __lt__(self, other):
        if not isinstance(other, Price):
            raise TypeError(other, '< requires another Price object')
        else:
            return self.__value < other.__value

    def __le__(self, other):
        if not isinstance(other, Price):
            raise TypeError(other, '<= requires another Price object')
        else:
            return self.__value <= other.__value

    def __eq__(self, other):
        if other is None:
            return False
        elif isinstance(other, Price):
            return self.__value == other.__value
        else:
            return self.__value == Price(other).__value

    def __ne__(self, other):
        return not self == other

    def __gt__(self, other):
        if not isinstance(other, Price):
            raise TypeError(other, '> requires another Price object')
        else:
            return self.__value > other.__value

    def __ge__(self, other):
        if not isinstance(other, Price):
            raise TypeError(other, '>= requires another Price object')
        else:
            return self.__value >= other.__value

    def __bool__(self):
        return bool(self.__value)

    def __add__(self, other):
        if isinstance(other, float):
            value = self.__float_value + other
        else:
            if isinstance(other, Price):
                other = other.__value
            value = self.__value + other
        return self.__class__(value, precision=self.__precision)

    def __radd__(self, other):
        return self.__add__(other)

    def __sub__(self, other):
        if isinstance(other, float):
            value = self.__float_value - other
        else:
            if isinstance(other, Price):
                other = other.__value
            value = self.__value - other
        return self.__class__(value, precision=self.__precision)

    def __rsub__(self, other):
        return (-self).__add__(other)

    def __mul__(self, other):
        if isinstance(other, float):
            value = self.__float_value * other
        else:
            if isinstance(other, Price):
                raise TypeError(
                    "Two prices cannot be multiplied"
                )  # just doesn't make sense. Why would someone do this?
            value = self.__value * other
        return self.__class__(value, precision=self.__precision)

    def __rmul__(self, other):
        return self.__mul__(other)

    def __div__(self, other):
        return self.__truediv__(other)

    def __truediv__(self, other):
        if isinstance(other, Price):
            # not really sure why someone would want to divide a price by another price
            raise TypeError("Two prices cannot be divided")
        else:
            if other == 0:
                raise ZeroDivisionError()
            if isinstance(other, float):
                value = self.__float_value / other
            else:
                value = self.__value / other
        return self.__class__(value, precision=self.__precision)

    def __floordiv__(self, other):
        if isinstance(other, Price):
            # not really sure why someone would want to divide a price by another price
            raise TypeError("Two prices cannot be divided")
        else:
            if other == 0:
                raise ZeroDivisionError()
            if isinstance(other, float):
                value = self.__float_value // other
            else:
                value = self.__value // other
        return self.__class__(value, precision=self.__precision)

    def __mod__(self, other):
        if isinstance(other, Price):
            # not really sure why someone would want to modulo a price by another price
            raise TypeError("modulo of two prices is not supported")
        if other == 0:
            raise ZeroDivisionError()
        if isinstance(other, float):
            value = self.__float_value % other
        else:
            value = self.__value % other
        return self.__class__(value, precision=self.__precision)

    def __divmod__(self, other):
        raise TypeError("divmod of a price is not supported")

    def __pow__(self, other):
        raise TypeError("pow of a price is not supported")

    def __neg__(self):
        return self.__class__(-self.__value)

    def __pos__(self):
        return self.__class__(+self.__value)

    def __abs__(self):
        return self.__class__(abs(self.__value))

    def __int__(self):
        return int(self.__value)

    def __float__(self):
        return self.__float_value
コード例 #5
0
ファイル: threshold.py プロジェクト: abramhindle/partycrasher
class Threshold(object):
    """
    A wrapper for a bucket threshold value. Ensures proper serialization
    between ElasticSearch and the JSON API endpoints.
    """
    __slots__ = '_value'

    def __init__(self, value):
        if isinstance(value, Threshold):
            assert isinstance(value._value, Decimal)
            # Clone the other Threshold.
            self._value = value._value
            return
        elif isinstance(value, StringTypes):
            value = value.replace('_', '.')

        self._value = Decimal(value)

    def __str__(self):
        result = str(self._value)
        assert '_' not in result
        # Ensure that rounded values are always displayed with at least one
        # decimal, for aesthetics.
        if '.' not in result:
            return result + '.0'
        return result

    def __repr__(self):
        return "Threshold('" + str(self) + "')"

    def to_float(self):
        return float(self)

    def __float__(self):
        """
        Convert the threshold to a floating point number, for comparisons.
        Note that this should NOT be converted back to a threshold, as there
        may be a loss of data by doing the round trip.
        """
        return float(self._value)

    def __getattr__(self, attr):
        # Delegate everything (i.e, comparisons) to the actual Threshold
        # value.
        return getattr(self._value, attr)

    def __hash__(self):
        return self._value.__hash__()

    def __eq__(self, otter):
        if not isinstance(otter, Threshold):
            return False
        return self._value == otter._value

    def to_elasticsearch(self):
        """
        Converts the threshold to a string, suitable for serialization as an
        ElasticSearch field name. Note that full stops ('.') are verbotten in
        ElasticSearch field names.
        """
        str_value = str(self)
        assert isinstance(self._value, Decimal)
        assert str_value.count('.') == 1, 'Invalid decimal number'
        return str_value.replace('.', '_')
コード例 #6
0
class Threshold(object):
    """
    A wrapper for a bucket threshold value. Ensures proper serialization
    between ElasticSearch and the JSON API endpoints.
    """
    __slots__ = '_value'

    def __init__(self, value):
        if isinstance(value, Threshold):
            assert isinstance(value._value, Decimal)
            # Clone the other Threshold.
            self._value = value._value
            return
        elif isinstance(value, StringTypes):
            value = value.replace('_', '.')

        self._value = Decimal(value)

    def __str__(self):
        result = str(self._value)
        assert '_' not in result
        # Ensure that rounded values are always displayed with at least one
        # decimal, for aesthetics.
        if '.' not in result:
            return result + '.0'
        return result

    def __repr__(self):
        return "Threshold('" + str(self) + "')"

    def to_float(self):
        return float(self)

    def __float__(self):
        """
        Convert the threshold to a floating point number, for comparisons.
        Note that this should NOT be converted back to a threshold, as there
        may be a loss of data by doing the round trip.
        """
        return float(self._value)

    def __getattr__(self, attr):
        # Delegate everything (i.e, comparisons) to the actual Threshold
        # value.
        return getattr(self._value, attr)

    def __hash__(self):
        return self._value.__hash__()

    def __eq__(self, otter):
        if not isinstance(otter, Threshold):
            return False
        return self._value == otter._value

    def to_elasticsearch(self):
        """
        Converts the threshold to a string, suitable for serialization as an
        ElasticSearch field name. Note that full stops ('.') are verbotten in
        ElasticSearch field names.
        """
        str_value = str(self)
        assert isinstance(self._value, Decimal)
        assert str_value.count('.') == 1, 'Invalid decimal number'
        return str_value.replace('.', '_')