def _make_api_object(self, response, model_type=None): blob = response.json() data = blob.get('data', None) # All valid responses have a "data" key. if data is None: raise build_api_error(response, blob) # Warn the user about each warning that was returned. warnings_data = blob.get('warnings', None) for warning_blob in warnings_data or []: message = "%s (%s)" % ( warning_blob.get('message', ''), warning_blob.get('url', '')) warnings.warn(message, UserWarning) pagination = blob.get('pagination', None) kwargs = { 'response': response, 'pagination': pagination and new_api_object(None, pagination, APIObject), 'warnings': warnings_data and new_api_object(None, warnings_data, APIObject) } if isinstance(data, dict): obj = new_api_object(self, data, model_type, **kwargs) else: obj = APIObject(self, **kwargs) obj.data = new_api_object(self, data, model_type) return obj
def test_paged_data_value(self): def api_client(x): return x # When the 'data' attribute is a list, slicing and indexing the APIObject # looks into the list. data = copy.copy(simple_data) data['data'] = data.pop('list_of_objs') simple_obj = new_api_object(api_client, data) print(simple_obj) self.assertEqual(simple_obj[0], simple_obj['data'][0]) self.assertEqual(simple_obj[::], simple_obj['data']) self.assertEqual(simple_obj[::-1], simple_obj['data'][::-1]) simple_obj2 = new_api_object(api_client, simple_data) with self.assertRaises(KeyError): simple_obj2[0]
def test_modify(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) data = account.modify(name='New Account Name') self.assertEqual(data, mock_account_updated) for key, value in six.iteritems(mock_account_updated): self.assertEqual(account[key], value)
def test_create_report(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) report = account.create_report(type='transactions', email='*****@*****.**') self.assertIsInstance(report, APIObject) self.assertIsInstance(report, Report) self.assertEqual(report, mock_item)
def test_new_api_object_transforms_types_appropriately(self): def api_client(x): return x simple_obj = new_api_object(api_client, simple_data) # Check root level for dict -> APIObject transformation. self.assertIsInstance(simple_data['obj'], dict) self.assertIsInstance(simple_obj['obj'], APIObject) # Check the second level for dict -> APIObject transformation. self.assertIsInstance(simple_data['obj']['obj'], dict) self.assertIsInstance(simple_obj['obj']['obj'], APIObject) # Check lists for dict -> APIObject transformation self.assertIsInstance(simple_data['list_of_objs'], list) self.assertIsInstance(simple_obj['list_of_objs'], list) for item in simple_data['list_of_objs']: self.assertIsInstance(item, dict) for item in simple_obj['list_of_objs']: self.assertIsInstance(item, APIObject) # Check that non-dict/list values are left the same. self.assertIsInstance(simple_data['str'], six.string_types) self.assertIsInstance(simple_obj['str'], six.string_types) self.assertIsInstance(simple_data['int'], int) self.assertIsInstance(simple_obj['int'], int) self.assertIsInstance(simple_data['float'], float) self.assertIsInstance(simple_obj['float'], float) self.assertIsInstance(simple_data['bool'], bool) self.assertIsInstance(simple_obj['bool'], bool) self.assertIsNone(simple_data['none']) self.assertIsNone(simple_obj['none'])
def test_get_address(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) address = account.get_address('bar') self.assertIsInstance(address, Address) self.assertEqual(address, mock_item) pass
def test_set_primary(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) data = account.set_primary() self.assertEqual(data, mock_account_updated) for key, value in six.iteritems(mock_account_updated): self.assertEqual(account[key], value)
def test_modify(self): client = Client(api_key, api_secret) user = new_api_object(client, mock_item, CurrentUser) user2 = user.modify(name='New Name') self.assertIsInstance(user2, CurrentUser) self.assertEqual(user2, mock_item_updated) for key, value in six.iteritems(mock_item_updated): self.assertEqual(user[key], value)
def test_commit(self): client = Client(api_key, api_secret) deposit = new_api_object(client, mock_deposit, Deposit) deposit2 = deposit.commit() self.assertIsInstance(deposit2, Deposit) self.assertEqual(deposit2, mock_deposit_updated) for key, value in six.iteritems(mock_deposit_updated): self.assertEqual(deposit[key], value)
def test_new_api_object_uses_cls_if_available(self): def api_client(x): return x class Foo(APIObject): pass obj = new_api_object(api_client, simple_data, cls=Foo) self.assertIsInstance(obj, Foo) self.assertNotIsInstance(obj.obj, Foo)
def test_commit(self): client = Client(api_key, api_secret) sell = new_api_object(client, mock_sell, Sell) sell2 = sell.commit() self.assertIsInstance(sell2, Sell) self.assertEqual(sell2, mock_sell_updated) for key, value in six.iteritems(mock_sell_updated): self.assertEqual(sell[key], value)
def test_commit(self): client = Client(api_key, api_secret) buy = new_api_object(client, mock_buy, Buy) buy2 = buy.commit() self.assertIsInstance(buy2, Buy) self.assertEqual(buy2, mock_buy_updated) for key, value in six.iteritems(mock_buy_updated): self.assertEqual(buy[key], value)
def test_new_api_object(self): api_client = lambda x: x obj = new_api_object(api_client, simple_data) self.assertIsInstance(obj, APIObject) self.assertIsNone(obj.response) self.assertIsNone(obj.pagination) self.assertIsNone(obj.warnings) response = lambda x: x pagination = lambda x: x warnings = lambda x: x obj = new_api_object( api_client, simple_data, response=response, pagination=pagination, warnings=warnings) self.assertIs(obj.response, response) self.assertIs(obj.pagination, pagination) self.assertIs(obj.warnings, warnings)
def test_get_deposits(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) deposits = account.get_deposits() self.assertIsInstance(deposits, APIObject) self.assertEqual(deposits.data, mock_collection) for deposit in deposits.data: self.assertIsInstance(deposit, Deposit)
def test_get_sells(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) sells = account.get_sells() self.assertIsInstance(sells, APIObject) self.assertEqual(sells.data, mock_collection) for sell in sells.data: self.assertIsInstance(sell, Sell)
def test_get_buys(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) buys = account.get_buys() self.assertIsInstance(buys, APIObject) self.assertEqual(buys.data, mock_collection) for buy in buys.data: self.assertIsInstance(buy, Buy)
def test_get_transactions(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) transactions = account.get_transactions() self.assertIsInstance(transactions, APIObject) self.assertEqual(transactions.data, mock_collection) for transaction in transactions.data: self.assertIsInstance(transaction, Transaction)
def test_get_orders(self): client = Client(api_key, api_secret) checkout = new_api_object(client, mock_checkout, Checkout) orders = checkout.get_orders() self.assertIsInstance(orders, APIObject) self.assertEqual(orders.data, mock_collection) for order in orders.data: self.assertIsInstance(order, Order)
def test_get_withdrawals(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) withdrawals = account.get_withdrawals() self.assertIsInstance(withdrawals, APIObject) self.assertEqual(withdrawals.data, mock_collection) for withdrawal in withdrawals.data: self.assertIsInstance(withdrawal, Withdrawal)
def test_get_addresses(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) addresses = account.get_addresses() self.assertIsInstance(addresses, APIObject) self.assertEqual(addresses.data, mock_collection) for address in addresses.data: self.assertIsInstance(address, Address)
def test_get_reports(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) reports = account.get_reports() self.assertIsInstance(reports, APIObject) self.assertEqual(reports.data, mock_collection) for report in reports.data: self.assertIsInstance(report, Report)
def test_new_api_object_preserves_api_client(self): def api_client(x): return x simple_obj = new_api_object(api_client, simple_data) # Check that all sub API objects have the same API client as the root. self.assertIs(simple_obj.api_client, api_client) self.assertIs(simple_obj['obj'].api_client, api_client) for thing in simple_obj['list_of_objs']: self.assertIs(thing.api_client, api_client)
def test_sell(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) with self.assertRaises(ValueError): account.sell() for valid_kwargs in [{'amount': '1.0'}, {'total': '1.0'}]: sell = account.sell(**valid_kwargs) self.assertIsInstance(sell, Sell) self.assertEqual(sell, mock_item)
def test_commit(self): client = Client(api_key, api_secret) withdrawal = new_api_object(client, mock_withdrawal, Withdrawal) withdrawal2 = withdrawal.commit() self.assertIsInstance(withdrawal2, Withdrawal) self.assertEqual(withdrawal2, mock_withdrawal_updated) for key, value in six.iteritems(mock_withdrawal_updated): self.assertEqual(withdrawal[key], value) pass
def test_new_api_object(self): def api_client(x): return x obj = new_api_object(api_client, simple_data) self.assertIsInstance(obj, APIObject) self.assertIsNone(obj.response) self.assertIsNone(obj.pagination) self.assertIsNone(obj.warnings) response = Response() def pagination(x): return x def warnings(x): return x obj = new_api_object( api_client, simple_data, response=response, pagination=pagination, warnings=warnings) self.assertIs(obj.response, response) self.assertIs(obj.pagination, pagination) self.assertIs(obj.warnings, warnings)
def test_attr_access(self): def api_client(x): return x # Every key in the object should be accessible by attribute access. simple_obj = new_api_object(api_client, simple_data) for key, value in simple_obj.items(): assert (key in simple_obj) and hasattr(simple_obj, key) assert getattr(simple_obj, key) is simple_obj[key] # If a key is not in the object, it should not be accessible by attribute # access. It should raise AttributeError when access is attempted by # attribute instead of by key. broken_key = 'notindata' assert broken_key not in simple_obj assert not hasattr(simple_obj, broken_key) with self.assertRaises(KeyError): simple_obj[broken_key] with self.assertRaises(AttributeError): getattr(simple_obj, broken_key) with self.assertRaises(KeyError): del simple_obj[broken_key] with self.assertRaises(AttributeError): delattr(simple_obj, broken_key) # Methods on the object should not be accessible via key. data = {'foo': 'bar'} data_obj = new_api_object(None, data) assert hasattr(data_obj, 'refresh') assert 'refresh' not in data_obj with self.assertRaises(KeyError): data_obj['refresh'] # Setting attributes that begin with a '_' are not available via __getitem__ data_obj._test = True self.assertEqual(getattr(data_obj, '_test', None), True) self.assertEqual(data_obj.get('_test', None), None) # Setting attribuets that don't begin with a '_' are available via __getitem__ data_obj.test = True self.assertEqual(getattr(data_obj, 'test', None), True) self.assertEqual(data_obj.get('test', None), True)
def test_buy(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) with self.assertRaises(ValueError): account.buy() kwargs_list = [ {'amount': '1.0', 'payment_method': 'bar', 'currency': 'USD'}, {'total': '1.0', 'payment_method': 'bar', 'currency': 'USD'} ] for valid_kwargs in kwargs_list: buy = account.buy(**valid_kwargs) self.assertIsInstance(buy, Buy) self.assertEqual(buy, mock_item)
def test_json_serialization(self): def api_client(x): return x simple_obj = new_api_object(api_client, simple_data) # APIObjects should be equivalent to the dicts from which they were loaded. self.assertEqual(simple_obj, simple_data) # APIObjects should be JSON-serializable; the serialized version should be # identical to the serialized version of the data from which the object # was originally created. json_data = json.dumps(simple_data, sort_keys=True) json_obj = json.dumps(simple_obj, sort_keys=True) self.assertEqual(json_data, json_obj) # Two APIObjects created from the same data should be equivalent. simple_obj2 = new_api_object(api_client, simple_data) self.assertEqual(simple_obj, simple_obj2) # When an object is unserializable, it should still be convertible to a # string. from decimal import Decimal broken_obj = new_api_object(api_client, {'cost': Decimal('12.0')}) self.assertTrue(str(broken_obj).endswith('(invalid JSON)'))
def test_new_api_object_guesses_based_on_resource_field(self): api_client = lambda x: x class Foo(APIObject): pass import coinbase.wallet.model # Preserve the inital values so that they can be restored after modifying # them for this test; otherwise, the modified versions will persist for # other tests. original = coinbase.wallet.model._resource_to_model coinbase.wallet.model._resource_to_model = { 'foo': Foo, } obj = new_api_object(api_client, simple_data) self.assertIsInstance(obj, Foo) coinbase.wallet.model._resource_to_model = original
def test_refresh(self): client = Client(api_key, api_secret) obj = new_api_object(client, mock_item, APIObject) self.assertEqual(obj, mock_item) # Missing resource_path key results in ValueError with self.assertRaises(ValueError): obj.refresh() obj.resource_path = '/resource/foo' updated = obj.refresh() self.assertEqual(updated, mock_item_updated) # The updated version is returned, as well as being used to update the # object making the refresh() for key, value in six.iteritems(mock_item_updated): self.assertEqual(obj[key], value) # Keys not present originally will not be removed self.assertEqual(obj.resource_path, '/resource/foo')
def test_withdraw(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) # Start with none of the required arguments, and slowly make requests with # an additional required argument, expecting failure until all arguments # are present. send_kwargs = {} required_kwargs = { 'payment_method': 'bar', 'amount': '1.0', 'currency': 'USD' } while required_kwargs: with self.assertRaises(ValueError): account.withdraw(**send_kwargs) for key in required_kwargs: send_kwargs[key] = required_kwargs.pop(key) break withdrawal = account.withdraw(**send_kwargs) self.assertIsInstance(withdrawal, Withdrawal) self.assertEqual(withdrawal, mock_item)
def test_dot_notation(self): client = Client(api_key, api_secret) obj = new_api_object(client, mock_item, APIObject) with self.assertRaises(AttributeError): obj.foo
def test_cancel(self): client = Client(api_key, api_secret) transaction = new_api_object(client, mock_transaction, Transaction) response = transaction.cancel() self.assertIsInstance(response, APIObject) self.assertEqual(response, mock_item)
def test_create_order(self): client = Client(api_key, api_secret) checkout = new_api_object(client, mock_checkout, Checkout) order = checkout.create_order() self.assertIsInstance(order, Order) self.assertEqual(order, mock_item)
def test_commit_withdrawal(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) withdrawal = account.commit_withdrawal('bar') self.assertIsInstance(withdrawal, Withdrawal) self.assertEqual(withdrawal, mock_item)
def test_commit_deposit(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) deposit = account.commit_deposit('bar') self.assertIsInstance(deposit, Deposit) self.assertEqual(deposit, mock_item)
def test_commit_sell(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) sell = account.commit_sell('bar') self.assertIsInstance(sell, Sell) self.assertEqual(sell, mock_item)
def test_commit_buy(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) buy = account.commit_buy('bar') self.assertIsInstance(buy, Buy) self.assertEqual(buy, mock_item)
def test_get_report(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) report = account.get_report('testreportid') self.assertIsInstance(report, Report) self.assertEqual(report, mock_item)
def test_get_transaction(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) transaction = account.get_transaction('bar') self.assertIsInstance(transaction, Transaction) self.assertEqual(transaction, mock_item)
def test_create_address(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) address = account.create_address() self.assertIsInstance(address, Address) self.assertEqual(address, mock_item)
def test_delete(self): client = Client(api_key, api_secret) account = new_api_object(client, mock_account, Account) data = account.delete() self.assertIs(data, None)