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

Side by Side Diff: third_party/boto/fps/connection.py

Issue 12633019: Added boto/ to depot_tools/third_party (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Moved boto down by one Created 7 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « third_party/boto/fps/__init__.py ('k') | third_party/boto/fps/exception.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright (c) 2012 Andy Davidoff http://www.disruptek.com/
2 # Copyright (c) 2010 Jason R. Coombs http://www.jaraco.com/
3 # Copyright (c) 2008 Chris Moyer http://coredumped.org/
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining a
6 # copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish, dis-
9 # tribute, sublicense, and/or sell copies of the Software, and to permit
10 # persons to whom the Software is furnished to do so, subject to the fol-
11 # lowing conditions:
12 #
13 # The above copyright notice and this permission notice shall be included
14 # in all copies or substantial portions of the Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
18 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
19 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 # IN THE SOFTWARE.
23
24 import urllib
25 import uuid
26 from boto.connection import AWSQueryConnection
27 from boto.fps.exception import ResponseErrorFactory
28 from boto.fps.response import ResponseFactory
29 import boto.fps.response
30
31 __all__ = ['FPSConnection']
32
33 decorated_attrs = ('action', 'response')
34
35
36 def add_attrs_from(func, to):
37 for attr in decorated_attrs:
38 setattr(to, attr, getattr(func, attr, None))
39 return to
40
41
42 def complex_amounts(*fields):
43 def decorator(func):
44 def wrapper(self, *args, **kw):
45 for field in filter(kw.has_key, fields):
46 amount = kw.pop(field)
47 kw[field + '.Value'] = getattr(amount, 'Value', str(amount))
48 kw[field + '.CurrencyCode'] = getattr(amount, 'CurrencyCode',
49 self.currencycode)
50 return func(self, *args, **kw)
51 wrapper.__doc__ = "{0}\nComplex Amounts: {1}".format(func.__doc__,
52 ', '.join(fields))
53 return add_attrs_from(func, to=wrapper)
54 return decorator
55
56
57 def requires(*groups):
58
59 def decorator(func):
60
61 def wrapper(*args, **kw):
62 hasgroup = lambda x: len(x) == len(filter(kw.has_key, x))
63 if 1 != len(filter(hasgroup, groups)):
64 message = ' OR '.join(['+'.join(g) for g in groups])
65 message = "{0} requires {1} argument(s)" \
66 "".format(getattr(func, 'action', 'Method'), message)
67 raise KeyError(message)
68 return func(*args, **kw)
69 message = ' OR '.join(['+'.join(g) for g in groups])
70 wrapper.__doc__ = "{0}\nRequired: {1}".format(func.__doc__,
71 message)
72 return add_attrs_from(func, to=wrapper)
73 return decorator
74
75
76 def needs_caller_reference(func):
77
78 def wrapper(*args, **kw):
79 kw.setdefault('CallerReference', uuid.uuid4())
80 return func(*args, **kw)
81 wrapper.__doc__ = "{0}\nUses CallerReference, defaults " \
82 "to uuid.uuid4()".format(func.__doc__)
83 return add_attrs_from(func, to=wrapper)
84
85
86 def api_action(*api):
87
88 def decorator(func):
89 action = ''.join(api or map(str.capitalize, func.func_name.split('_')))
90 response = ResponseFactory(action)
91 if hasattr(boto.fps.response, action + 'Response'):
92 response = getattr(boto.fps.response, action + 'Response')
93
94 def wrapper(self, *args, **kw):
95 return func(self, action, response, *args, **kw)
96 wrapper.action, wrapper.response = action, response
97 wrapper.__doc__ = "FPS {0} API call\n{1}".format(action,
98 func.__doc__)
99 return wrapper
100 return decorator
101
102
103 class FPSConnection(AWSQueryConnection):
104
105 APIVersion = '2010-08-28'
106 ResponseError = ResponseErrorFactory
107 currencycode = 'USD'
108
109 def __init__(self, *args, **kw):
110 self.currencycode = kw.pop('CurrencyCode', self.currencycode)
111 kw.setdefault('host', 'fps.sandbox.amazonaws.com')
112 AWSQueryConnection.__init__(self, *args, **kw)
113
114 def _required_auth_capability(self):
115 return ['fps']
116
117 @needs_caller_reference
118 @complex_amounts('SettlementAmount')
119 @requires(['CreditInstrumentId', 'SettlementAmount.Value',
120 'SenderTokenId', 'SettlementAmount.CurrencyCode'])
121 @api_action()
122 def settle_debt(self, action, response, **kw):
123 """Allows a caller to initiate a transaction that atomically
124 transfers money from a sender's payment instrument to the
125 recipient, while decreasing corresponding debt balance.
126 """
127 return self.get_object(action, kw, response)
128
129 @requires(['TransactionId'])
130 @api_action()
131 def get_transaction_status(self, action, response, **kw):
132 """Gets the latest status of a transaction.
133 """
134 return self.get_object(action, kw, response)
135
136 @requires(['StartDate'])
137 @api_action()
138 def get_account_activity(self, action, response, **kw):
139 """Returns transactions for a given date range.
140 """
141 return self.get_object(action, kw, response)
142
143 @requires(['TransactionId'])
144 @api_action()
145 def get_transaction(self, action, response, **kw):
146 """Returns all details of a transaction.
147 """
148 return self.get_object(action, kw, response)
149
150 @api_action()
151 def get_outstanding_debt_balance(self, action, response):
152 """Returns the total outstanding balance for all the credit
153 instruments for the given creditor account.
154 """
155 return self.get_object(action, {}, response)
156
157 @requires(['PrepaidInstrumentId'])
158 @api_action()
159 def get_prepaid_balance(self, action, response, **kw):
160 """Returns the balance available on the given prepaid instrument.
161 """
162 return self.get_object(action, kw, response)
163
164 @api_action()
165 def get_total_prepaid_liability(self, action, response):
166 """Returns the total liability held by the given account
167 corresponding to all the prepaid instruments owned by the
168 account.
169 """
170 return self.get_object(action, {}, response)
171
172 @api_action()
173 def get_account_balance(self, action, response):
174 """Returns the account balance for an account in real time.
175 """
176 return self.get_object(action, {}, response)
177
178 @needs_caller_reference
179 @requires(['PaymentInstruction', 'TokenType'])
180 @api_action()
181 def install_payment_instruction(self, action, response, **kw):
182 """Installs a payment instruction for caller.
183 """
184 return self.get_object(action, kw, response)
185
186 @needs_caller_reference
187 @requires(['returnURL', 'pipelineName'])
188 def cbui_url(self, **kw):
189 """Generate a signed URL for the Co-Branded service API given
190 arguments as payload.
191 """
192 sandbox = 'sandbox' in self.host and 'payments-sandbox' or 'payments'
193 endpoint = 'authorize.{0}.amazon.com'.format(sandbox)
194 base = '/cobranded-ui/actions/start'
195
196 validpipelines = ('SingleUse', 'MultiUse', 'Recurring', 'Recipient',
197 'SetupPrepaid', 'SetupPostpaid', 'EditToken')
198 assert kw['pipelineName'] in validpipelines, "Invalid pipelineName"
199 kw.update({
200 'signatureMethod': 'HmacSHA256',
201 'signatureVersion': '2',
202 })
203 kw.setdefault('callerKey', self.aws_access_key_id)
204
205 safestr = lambda x: x is not None and str(x) or ''
206 safequote = lambda x: urllib.quote(safestr(x), safe='~')
207 payload = sorted([(k, safequote(v)) for k, v in kw.items()])
208
209 encoded = lambda p: '&'.join([k + '=' + v for k, v in p])
210 canonical = '\n'.join(['GET', endpoint, base, encoded(payload)])
211 signature = self._auth_handler.sign_string(canonical)
212 payload += [('signature', safequote(signature))]
213 payload.sort()
214
215 return 'https://{0}{1}?{2}'.format(endpoint, base, encoded(payload))
216
217 @needs_caller_reference
218 @complex_amounts('TransactionAmount')
219 @requires(['SenderTokenId', 'TransactionAmount.Value',
220 'TransactionAmount.CurrencyCode'])
221 @api_action()
222 def reserve(self, action, response, **kw):
223 """Reserve API is part of the Reserve and Settle API conjunction
224 that serve the purpose of a pay where the authorization and
225 settlement have a timing difference.
226 """
227 return self.get_object(action, kw, response)
228
229 @needs_caller_reference
230 @complex_amounts('TransactionAmount')
231 @requires(['SenderTokenId', 'TransactionAmount.Value',
232 'TransactionAmount.CurrencyCode'])
233 @api_action()
234 def pay(self, action, response, **kw):
235 """Allows calling applications to move money from a sender to
236 a recipient.
237 """
238 return self.get_object(action, kw, response)
239
240 @requires(['TransactionId'])
241 @api_action()
242 def cancel(self, action, response, **kw):
243 """Cancels an ongoing transaction and puts it in cancelled state.
244 """
245 return self.get_object(action, kw, response)
246
247 @complex_amounts('TransactionAmount')
248 @requires(['ReserveTransactionId', 'TransactionAmount.Value',
249 'TransactionAmount.CurrencyCode'])
250 @api_action()
251 def settle(self, action, response, **kw):
252 """The Settle API is used in conjunction with the Reserve API and
253 is used to settle previously reserved transaction.
254 """
255 return self.get_object(action, kw, response)
256
257 @complex_amounts('RefundAmount')
258 @requires(['TransactionId', 'RefundAmount.Value',
259 'CallerReference', 'RefundAmount.CurrencyCode'])
260 @api_action()
261 def refund(self, action, response, **kw):
262 """Refunds a previously completed transaction.
263 """
264 return self.get_object(action, kw, response)
265
266 @requires(['RecipientTokenId'])
267 @api_action()
268 def get_recipient_verification_status(self, action, response, **kw):
269 """Returns the recipient status.
270 """
271 return self.get_object(action, kw, response)
272
273 @requires(['CallerReference'], ['TokenId'])
274 @api_action()
275 def get_token_by_caller(self, action, response, **kw):
276 """Returns the details of a particular token installed by this
277 calling application using the subway co-branded UI.
278 """
279 return self.get_object(action, kw, response)
280
281 @requires(['UrlEndPoint', 'HttpParameters'])
282 @api_action()
283 def verify_signature(self, action, response, **kw):
284 """Verify the signature that FPS sent in IPN or callback urls.
285 """
286 return self.get_object(action, kw, response)
287
288 @api_action()
289 def get_tokens(self, action, response, **kw):
290 """Returns a list of tokens installed on the given account.
291 """
292 return self.get_object(action, kw, response)
293
294 @requires(['TokenId'])
295 @api_action()
296 def get_token_usage(self, action, response, **kw):
297 """Returns the usage of a token.
298 """
299 return self.get_object(action, kw, response)
300
301 @requires(['TokenId'])
302 @api_action()
303 def cancel_token(self, action, response, **kw):
304 """Cancels any token installed by the calling application on
305 its own account.
306 """
307 return self.get_object(action, kw, response)
308
309 @needs_caller_reference
310 @complex_amounts('FundingAmount')
311 @requires(['PrepaidInstrumentId', 'FundingAmount.Value',
312 'SenderTokenId', 'FundingAmount.CurrencyCode'])
313 @api_action()
314 def fund_prepaid(self, action, response, **kw):
315 """Funds the prepaid balance on the given prepaid instrument.
316 """
317 return self.get_object(action, kw, response)
318
319 @requires(['CreditInstrumentId'])
320 @api_action()
321 def get_debt_balance(self, action, response, **kw):
322 """Returns the balance corresponding to the given credit instrument.
323 """
324 return self.get_object(action, kw, response)
325
326 @needs_caller_reference
327 @complex_amounts('AdjustmentAmount')
328 @requires(['CreditInstrumentId', 'AdjustmentAmount.Value',
329 'AdjustmentAmount.CurrencyCode'])
330 @api_action()
331 def write_off_debt(self, action, response, **kw):
332 """Allows a creditor to write off the debt balance accumulated
333 partially or fully at any time.
334 """
335 return self.get_object(action, kw, response)
336
337 @requires(['SubscriptionId'])
338 @api_action()
339 def get_transactions_for_subscription(self, action, response, **kw):
340 """Returns the transactions for a given subscriptionID.
341 """
342 return self.get_object(action, kw, response)
343
344 @requires(['SubscriptionId'])
345 @api_action()
346 def get_subscription_details(self, action, response, **kw):
347 """Returns the details of Subscription for a given subscriptionID.
348 """
349 return self.get_object(action, kw, response)
350
351 @needs_caller_reference
352 @complex_amounts('RefundAmount')
353 @requires(['SubscriptionId'])
354 @api_action()
355 def cancel_subscription_and_refund(self, action, response, **kw):
356 """Cancels a subscription.
357 """
358 message = "If you specify a RefundAmount, " \
359 "you must specify CallerReference."
360 assert not 'RefundAmount.Value' in kw \
361 or 'CallerReference' in kw, message
362 return self.get_object(action, kw, response)
363
364 @requires(['TokenId'])
365 @api_action()
366 def get_payment_instruction(self, action, response, **kw):
367 """Gets the payment instruction of a token.
368 """
369 return self.get_object(action, kw, response)
OLDNEW
« no previous file with comments | « third_party/boto/fps/__init__.py ('k') | third_party/boto/fps/exception.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698