Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(687)

Side by Side Diff: third_party/google-endpoints/google/api/control/money.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2016 Google Inc. All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 """money provides funcs for working with `Money` instances.
16
17 :func:`check_valid` determines if a `Money` instance is valid
18 :func:`add` adds two `Money` instances together
19
20 """
21
22 from __future__ import absolute_import
23
24 import logging
25 import sys
26
27 from . import messages
28
29 logger = logging.getLogger(__name__)
30
31 _INT64_MAX = sys.maxint
32 _INT64_MIN = -sys.maxint - 1
33 _BILLION = 1000000000
34 MAX_NANOS = _BILLION - 1
35 _MSG_3_LETTERS_LONG = 'The currency code is not 3 letters long'
36 _MSG_UNITS_NANOS_MISMATCH = 'The signs of the units and nanos do not match'
37 _MSG_NANOS_OOB = 'The nanos field must be between -999999999 and 999999999'
38
39
40 def check_valid(money):
41 """Determine if an instance of `Money` is valid.
42
43 Args:
44 money (:class:`google.api.gen.servicecontrol_v1_messages.Money`): the
45 instance to test
46
47 Raises:
48 ValueError: if the money instance is invalid
49 """
50 if not isinstance(money, messages.Money):
51 raise ValueError('Inputs should be of type %s' % (messages.Money,))
52 currency = money.currencyCode
53 if not currency or len(currency) != 3:
54 raise ValueError(_MSG_3_LETTERS_LONG)
55 units = money.units
56 nanos = money.nanos
57 if ((units > 0) and (nanos < 0)) or ((units < 0) and (nanos > 0)):
58 raise ValueError(_MSG_UNITS_NANOS_MISMATCH)
59 if abs(nanos) > MAX_NANOS:
60 raise ValueError(_MSG_NANOS_OOB)
61
62
63 def add(a, b, allow_overflow=False):
64 """Adds two instances of `Money`.
65
66 Args:
67 a (:class:`google.api.gen.servicecontrol_v1_messages.Money`): one money
68 value
69 b (:class:`google.api.gen.servicecontrol_v1_messages.Money`): another
70 money value
71 allow_overflow: determines if the addition is allowed to overflow
72
73 Return:
74 `Money`: an instance of Money
75
76 Raises:
77 ValueError: if the inputs do not have the same currency code
78 OverflowError: if the sum overflows and allow_overflow is not `True`
79 """
80 for m in (a, b):
81 if not isinstance(m, messages.Money):
82 raise ValueError('Inputs should be of type %s' % (messages.Money,))
83 if a.currencyCode != b.currencyCode:
84 raise ValueError('Money values need the same currency to be summed')
85 nano_carry, nanos_sum = _sum_nanos(a, b)
86 units_sum_no_carry = a.units + b.units
87 units_sum = units_sum_no_carry + nano_carry
88
89 # Adjust when units_sum and nanos_sum have different signs
90 if units_sum > 0 and nanos_sum < 0:
91 units_sum -= 1
92 nanos_sum += _BILLION
93 elif units_sum < 0 and nanos_sum > 0:
94 units_sum += 1
95 nanos_sum -= _BILLION
96
97 # Return the result, detecting overflow if it occurs
98 sign_a = _sign_of(a)
99 sign_b = _sign_of(b)
100 if sign_a > 0 and sign_b > 0 and units_sum >= _INT64_MAX:
101 if not allow_overflow:
102 raise OverflowError('Money addition positive overflow')
103 else:
104 return messages.Money(units=_INT64_MAX,
105 nanos=MAX_NANOS,
106 currencyCode=a.currencyCode)
107 elif (sign_a < 0 and sign_b < 0 and
108 (units_sum_no_carry <= -_INT64_MAX or units_sum <= -_INT64_MAX)):
109 if not allow_overflow:
110 raise OverflowError('Money addition negative overflow')
111 else:
112 return messages.Money(units=_INT64_MIN,
113 nanos=-MAX_NANOS,
114 currencyCode=a.currencyCode)
115 else:
116 return messages.Money(units=units_sum,
117 nanos=nanos_sum,
118 currencyCode=a.currencyCode)
119
120
121 def _sum_nanos(a, b):
122 the_sum = a.nanos + b.nanos
123 carry = 0
124 if the_sum > _BILLION:
125 carry = 1
126 the_sum -= _BILLION
127 elif the_sum <= -_BILLION:
128 carry = -1
129 the_sum += _BILLION
130 return carry, the_sum
131
132
133 def _sign_of(money):
134 """Determines the amount sign of a money instance
135
136 Args:
137 money (:class:`google.api.gen.servicecontrol_v1_messages.Money`): the
138 instance to test
139
140 Return:
141 int: 1, 0 or -1
142
143 """
144 units = money.units
145 nanos = money.nanos
146 if units:
147 if units > 0:
148 return 1
149 elif units < 0:
150 return -1
151 if nanos:
152 if nanos > 0:
153 return 1
154 elif nanos < 0:
155 return -1
156 return 0
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698