| Index: third_party/google-endpoints/google/api/control/money.py
|
| diff --git a/third_party/google-endpoints/google/api/control/money.py b/third_party/google-endpoints/google/api/control/money.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..72b5c7e4e0e6fbd99ad5765e683f4882c6d6d68f
|
| --- /dev/null
|
| +++ b/third_party/google-endpoints/google/api/control/money.py
|
| @@ -0,0 +1,156 @@
|
| +# Copyright 2016 Google Inc. All Rights Reserved.
|
| +#
|
| +# Licensed under the Apache License, Version 2.0 (the "License");
|
| +# you may not use this file except in compliance with the License.
|
| +# You may obtain a copy of the License at
|
| +#
|
| +# http://www.apache.org/licenses/LICENSE-2.0
|
| +#
|
| +# Unless required by applicable law or agreed to in writing, software
|
| +# distributed under the License is distributed on an "AS IS" BASIS,
|
| +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| +# See the License for the specific language governing permissions and
|
| +# limitations under the License.
|
| +
|
| +"""money provides funcs for working with `Money` instances.
|
| +
|
| +:func:`check_valid` determines if a `Money` instance is valid
|
| +:func:`add` adds two `Money` instances together
|
| +
|
| +"""
|
| +
|
| +from __future__ import absolute_import
|
| +
|
| +import logging
|
| +import sys
|
| +
|
| +from . import messages
|
| +
|
| +logger = logging.getLogger(__name__)
|
| +
|
| +_INT64_MAX = sys.maxint
|
| +_INT64_MIN = -sys.maxint - 1
|
| +_BILLION = 1000000000
|
| +MAX_NANOS = _BILLION - 1
|
| +_MSG_3_LETTERS_LONG = 'The currency code is not 3 letters long'
|
| +_MSG_UNITS_NANOS_MISMATCH = 'The signs of the units and nanos do not match'
|
| +_MSG_NANOS_OOB = 'The nanos field must be between -999999999 and 999999999'
|
| +
|
| +
|
| +def check_valid(money):
|
| + """Determine if an instance of `Money` is valid.
|
| +
|
| + Args:
|
| + money (:class:`google.api.gen.servicecontrol_v1_messages.Money`): the
|
| + instance to test
|
| +
|
| + Raises:
|
| + ValueError: if the money instance is invalid
|
| + """
|
| + if not isinstance(money, messages.Money):
|
| + raise ValueError('Inputs should be of type %s' % (messages.Money,))
|
| + currency = money.currencyCode
|
| + if not currency or len(currency) != 3:
|
| + raise ValueError(_MSG_3_LETTERS_LONG)
|
| + units = money.units
|
| + nanos = money.nanos
|
| + if ((units > 0) and (nanos < 0)) or ((units < 0) and (nanos > 0)):
|
| + raise ValueError(_MSG_UNITS_NANOS_MISMATCH)
|
| + if abs(nanos) > MAX_NANOS:
|
| + raise ValueError(_MSG_NANOS_OOB)
|
| +
|
| +
|
| +def add(a, b, allow_overflow=False):
|
| + """Adds two instances of `Money`.
|
| +
|
| + Args:
|
| + a (:class:`google.api.gen.servicecontrol_v1_messages.Money`): one money
|
| + value
|
| + b (:class:`google.api.gen.servicecontrol_v1_messages.Money`): another
|
| + money value
|
| + allow_overflow: determines if the addition is allowed to overflow
|
| +
|
| + Return:
|
| + `Money`: an instance of Money
|
| +
|
| + Raises:
|
| + ValueError: if the inputs do not have the same currency code
|
| + OverflowError: if the sum overflows and allow_overflow is not `True`
|
| + """
|
| + for m in (a, b):
|
| + if not isinstance(m, messages.Money):
|
| + raise ValueError('Inputs should be of type %s' % (messages.Money,))
|
| + if a.currencyCode != b.currencyCode:
|
| + raise ValueError('Money values need the same currency to be summed')
|
| + nano_carry, nanos_sum = _sum_nanos(a, b)
|
| + units_sum_no_carry = a.units + b.units
|
| + units_sum = units_sum_no_carry + nano_carry
|
| +
|
| + # Adjust when units_sum and nanos_sum have different signs
|
| + if units_sum > 0 and nanos_sum < 0:
|
| + units_sum -= 1
|
| + nanos_sum += _BILLION
|
| + elif units_sum < 0 and nanos_sum > 0:
|
| + units_sum += 1
|
| + nanos_sum -= _BILLION
|
| +
|
| + # Return the result, detecting overflow if it occurs
|
| + sign_a = _sign_of(a)
|
| + sign_b = _sign_of(b)
|
| + if sign_a > 0 and sign_b > 0 and units_sum >= _INT64_MAX:
|
| + if not allow_overflow:
|
| + raise OverflowError('Money addition positive overflow')
|
| + else:
|
| + return messages.Money(units=_INT64_MAX,
|
| + nanos=MAX_NANOS,
|
| + currencyCode=a.currencyCode)
|
| + elif (sign_a < 0 and sign_b < 0 and
|
| + (units_sum_no_carry <= -_INT64_MAX or units_sum <= -_INT64_MAX)):
|
| + if not allow_overflow:
|
| + raise OverflowError('Money addition negative overflow')
|
| + else:
|
| + return messages.Money(units=_INT64_MIN,
|
| + nanos=-MAX_NANOS,
|
| + currencyCode=a.currencyCode)
|
| + else:
|
| + return messages.Money(units=units_sum,
|
| + nanos=nanos_sum,
|
| + currencyCode=a.currencyCode)
|
| +
|
| +
|
| +def _sum_nanos(a, b):
|
| + the_sum = a.nanos + b.nanos
|
| + carry = 0
|
| + if the_sum > _BILLION:
|
| + carry = 1
|
| + the_sum -= _BILLION
|
| + elif the_sum <= -_BILLION:
|
| + carry = -1
|
| + the_sum += _BILLION
|
| + return carry, the_sum
|
| +
|
| +
|
| +def _sign_of(money):
|
| + """Determines the amount sign of a money instance
|
| +
|
| + Args:
|
| + money (:class:`google.api.gen.servicecontrol_v1_messages.Money`): the
|
| + instance to test
|
| +
|
| + Return:
|
| + int: 1, 0 or -1
|
| +
|
| + """
|
| + units = money.units
|
| + nanos = money.nanos
|
| + if units:
|
| + if units > 0:
|
| + return 1
|
| + elif units < 0:
|
| + return -1
|
| + if nanos:
|
| + if nanos > 0:
|
| + return 1
|
| + elif nanos < 0:
|
| + return -1
|
| + return 0
|
|
|