From 41353af270ebb32a6946f28ddf5ef0db52e8343c Mon Sep 17 00:00:00 2001 From: Yulia Burykina Date: Wed, 8 Jan 2020 11:02:34 +0100 Subject: [PATCH 01/19] first draft of available_numbers_list call --- examples/number_available_list.py | 41 +++++++++++++++++++++++++++++++ messagebird/client.py | 20 +++++++++++++++ messagebird/number.py | 20 +++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 examples/number_available_list.py create mode 100644 messagebird/number.py diff --git a/examples/number_available_list.py b/examples/number_available_list.py new file mode 100644 index 0000000..8ea3ba1 --- /dev/null +++ b/examples/number_available_list.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python + +import sys, os +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + +import messagebird + +ACCESS_KEY = 'test_gshuPaZoeEG6ovbc8M79w0QyM' + +try: + # Create a MessageBird client with the specified ACCESS_KEY. + client = messagebird.Client(ACCESS_KEY) + + # Fetch the NumberList object. + numbers = client.available_numbers_list(20, 0) + + # Print the object information. + print('\nThe following information was returned as a %s object:\n' % numbers.__class__) + if numbers.items is not None: + print(' Containing the the following items:') + for item in numbers.items: + print(' {') + print(' number : %s' % item.number) + print(' country : %s' % item.country) + print(' region : %s' % item.region) + print(' locality : %s' % item.locality) + print(' features : %s' % item.features) + print(' tags : %s' % item.tags) + print(' type : %s' % item.type) + print(' status : %s' % item.status) + print(' },') + else: + print(' With an empty response.') + +except messagebird.client.ErrorException as e: + print('\nAn error occured while requesting a NumberList object:\n') + + for error in e.errors: + print(' code : %d' % error.code) + print(' description : %s' % error.description) + print(' parameter : %s\n' % error.parameter) diff --git a/messagebird/client.py b/messagebird/client.py index dbcf778..eeb8712 100644 --- a/messagebird/client.py +++ b/messagebird/client.py @@ -23,6 +23,7 @@ from messagebird.voice_recording import VoiceRecordingsList, VoiceRecording from messagebird.voice_transcription import VoiceTranscriptionsList, VoiceTranscriptionsView from messagebird.call_flow import CallFlow, CallFlowList, CallFlowNumberList +from messagebird.number import Number, NumberList ENDPOINT = 'https://rest.messagebird.com' CLIENT_VERSION = '1.4.1' @@ -46,6 +47,11 @@ VOICE_TRANSCRIPTIONS_PATH = 'transcriptions' VOICE_WEB_HOOKS_PATH = 'webhooks' +NUMBER_TYPE = 'number' +NUMBER_API_ROOT = 'https://numbers.messagebird.com/v1/' +NUMBER_PATH = 'phone-numbers' +NUMBER_AVAILABLE_PATH = 'available-phone-numbers' + class ErrorException(Exception): def __init__(self, errors): @@ -81,6 +87,9 @@ def _get_http_client(self, type=REST_TYPE): if type == VOICE_TYPE: return HttpClient(VOICE_API_ROOT, self.access_key, USER_AGENT) + if type == NUMBER_TYPE: + return HttpClient(NUMBER_API_ROOT, self.access_key, USER_AGENT) + return HttpClient(ENDPOINT, self.access_key, USER_AGENT) def request(self, path, method='GET', params=None, type=REST_TYPE): @@ -498,6 +507,15 @@ def call_flow_numbers_add(self, call_flow_id, numbers=()): def _format_query(self, limit, offset): return 'limit=' + str(limit) + '&offset=' + str(offset) + def available_numbers_list(self, limit=20, offset=0): + """Retrieve a list of phone numbers available for purchase.""" + # todo: add params + # todo: make country ('NL') a param + # todo: add example + # todo: add test + query = self._format_query(limit, offset) + return NumberList().load(self.request(NUMBER_AVAILABLE_PATH + '/NL?' + query, 'GET', None, NUMBER_TYPE)) + @staticmethod def generate_voice_calls_url(call_id=None, leg_id=None, recording_id=None): uri = VOICE_API_ROOT + '/' + VOICE_PATH + '/' @@ -505,3 +523,5 @@ def generate_voice_calls_url(call_id=None, leg_id=None, recording_id=None): if recording_id: uri += '/' + str(recording_id) + '/' + VOICE_TRANSCRIPTIONS_PATH return uri + + diff --git a/messagebird/number.py b/messagebird/number.py new file mode 100644 index 0000000..2362f47 --- /dev/null +++ b/messagebird/number.py @@ -0,0 +1,20 @@ +from messagebird.base import Base +from messagebird.base_list import BaseList + + +class NumberList(BaseList): + def __init__(self): + # We're expecting items of type Number + super(NumberList, self).__init__(Number) + + +class Number(Base): + def __init__(self): + self.number = None + self.country = None + self.region = None + self.locality = None + self.features = None + self.tags = None + self.type = None + self.status = None From 96e58d203329e79dcc0b6431b0be07e5a7fd3026 Mon Sep 17 00:00:00 2001 From: Yulia Burykina Date: Wed, 8 Jan 2020 13:33:52 +0100 Subject: [PATCH 02/19] added params for available_numbers_list call, added accessKey param for its example --- examples/number_available_list.py | 15 +++++++++------ messagebird/client.py | 14 ++++++++------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/examples/number_available_list.py b/examples/number_available_list.py index 8ea3ba1..b8de144 100644 --- a/examples/number_available_list.py +++ b/examples/number_available_list.py @@ -1,18 +1,21 @@ #!/usr/bin/env python -import sys, os +import sys, os, argparse sys.path.append(os.path.join(os.path.dirname(__file__), '..')) import messagebird -ACCESS_KEY = 'test_gshuPaZoeEG6ovbc8M79w0QyM' +parser = argparse.ArgumentParser() +parser.add_argument('--accessKey', help='access key for MessageBird API', type=str, required=True) +args = vars(parser.parse_args()) try: - # Create a MessageBird client with the specified ACCESS_KEY. - client = messagebird.Client(ACCESS_KEY) + # Create a MessageBird client with the specified accessKey. + client = messagebird.Client(args['accessKey']) - # Fetch the NumberList object. - numbers = client.available_numbers_list(20, 0) + # Fetch the NumberList object with specified params, limit, offset. + params = {'features': ['sms', 'voice'], 'number': '15'} + numbers = client.available_numbers_list('US', params, 2, 0) # Print the object information. print('\nThe following information was returned as a %s object:\n' % numbers.__class__) diff --git a/messagebird/client.py b/messagebird/client.py index eeb8712..8186a5f 100644 --- a/messagebird/client.py +++ b/messagebird/client.py @@ -507,14 +507,16 @@ def call_flow_numbers_add(self, call_flow_id, numbers=()): def _format_query(self, limit, offset): return 'limit=' + str(limit) + '&offset=' + str(offset) - def available_numbers_list(self, limit=20, offset=0): + def available_numbers_list(self, country, params=None, limit=20, offset=0): """Retrieve a list of phone numbers available for purchase.""" - # todo: add params - # todo: make country ('NL') a param - # todo: add example # todo: add test - query = self._format_query(limit, offset) - return NumberList().load(self.request(NUMBER_AVAILABLE_PATH + '/NL?' + query, 'GET', None, NUMBER_TYPE)) + if params is None: + params = {} + + params['limit'] = limit + params['offset'] = offset + + return NumberList().load(self.request(NUMBER_AVAILABLE_PATH + '/' + str(country), 'GET', params, NUMBER_TYPE)) @staticmethod def generate_voice_calls_url(call_id=None, leg_id=None, recording_id=None): From eaec7f6940388727c43604fce58e18b14bbd2622 Mon Sep 17 00:00:00 2001 From: Yulia Burykina Date: Thu, 9 Jan 2020 10:29:26 +0100 Subject: [PATCH 03/19] added purchase_number call --- examples/number_available_list.py | 4 ++-- examples/number_purchase.py | 37 +++++++++++++++++++++++++++++++ messagebird/client.py | 4 ++++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 examples/number_purchase.py diff --git a/examples/number_available_list.py b/examples/number_available_list.py index b8de144..a5dff87 100644 --- a/examples/number_available_list.py +++ b/examples/number_available_list.py @@ -14,8 +14,8 @@ client = messagebird.Client(args['accessKey']) # Fetch the NumberList object with specified params, limit, offset. - params = {'features': ['sms', 'voice'], 'number': '15'} - numbers = client.available_numbers_list('US', params, 2, 0) + params = {'features': ['sms', 'voice'], 'number': 319} + numbers = client.available_numbers_list('NL', params, 2, 0) # Print the object information. print('\nThe following information was returned as a %s object:\n' % numbers.__class__) diff --git a/examples/number_purchase.py b/examples/number_purchase.py new file mode 100644 index 0000000..4689a12 --- /dev/null +++ b/examples/number_purchase.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +import sys, os, argparse +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + +import messagebird + +parser = argparse.ArgumentParser() +parser.add_argument('--accessKey', help='access key for MessageBird API', type=str, required=True) +args = vars(parser.parse_args()) + +try: + # Create a MessageBird client with the specified accessKey. + client = messagebird.Client(args['accessKey']) + + # Purchase number + # todo make these values arguments + number = client.purchase_number('3197010240405', 'NL', 3) + + # Print the object information. + print('\nThe following information was returned as a Number object:\n') + print(' number : %s' % number.number) + print(' country : %s' % number.country) + print(' region : %s' % number.region) + print(' locality : %s' % number.locality) + print(' features : %s' % number.features) + print(' tags : %s' % number.tags) + print(' type : %s' % number.type) + print(' status : %s' % number.status) + +except messagebird.client.ErrorException as e: + print('\nAn error occured while requesting a NumberList object:\n') + + for error in e.errors: + print(' code : %d' % error.code) + print(' description : %s' % error.description) + print(' parameter : %s\n' % error.parameter) diff --git a/messagebird/client.py b/messagebird/client.py index 8186a5f..a302ea6 100644 --- a/messagebird/client.py +++ b/messagebird/client.py @@ -518,6 +518,10 @@ def available_numbers_list(self, country, params=None, limit=20, offset=0): return NumberList().load(self.request(NUMBER_AVAILABLE_PATH + '/' + str(country), 'GET', params, NUMBER_TYPE)) + def purchase_number(self, number, country, billingIntervalMonths=1): + params = {'number': str(number), 'countryCode': str(country), 'billingIntervalMonths': int(billingIntervalMonths)} + return Number().load(self.request(NUMBER_PATH, 'POST', params, NUMBER_TYPE)) + @staticmethod def generate_voice_calls_url(call_id=None, leg_id=None, recording_id=None): uri = VOICE_API_ROOT + '/' + VOICE_PATH + '/' From be292bcca912ddd789668040459d709633853e65 Mon Sep 17 00:00:00 2001 From: Yulia Burykina Date: Thu, 9 Jan 2020 13:05:35 +0100 Subject: [PATCH 04/19] added update_number and delete_number calls --- examples/number_purchase.py | 3 +-- examples/number_update.py | 38 +++++++++++++++++++++++++++++++++++++ messagebird/client.py | 7 +++++++ 3 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 examples/number_update.py diff --git a/examples/number_purchase.py b/examples/number_purchase.py index 4689a12..620d43c 100644 --- a/examples/number_purchase.py +++ b/examples/number_purchase.py @@ -14,8 +14,7 @@ client = messagebird.Client(args['accessKey']) # Purchase number - # todo make these values arguments - number = client.purchase_number('3197010240405', 'NL', 3) + number = client.purchase_number('3197010240126', 'NL', 3) # Print the object information. print('\nThe following information was returned as a Number object:\n') diff --git a/examples/number_update.py b/examples/number_update.py new file mode 100644 index 0000000..c1a9e64 --- /dev/null +++ b/examples/number_update.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python + +import sys, os, argparse +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + +import messagebird + +parser = argparse.ArgumentParser() +parser.add_argument('--accessKey', help='access key for MessageBird API', type=str, required=True) +args = vars(parser.parse_args()) + +try: + # Create a MessageBird client with the specified accessKey. + client = messagebird.Client(args['accessKey']) + + # Update number + # Note: at the moment, we only support updating tags that can be used to group or label numbers + tags = ['tag1'] + number = client.update_number('3197010240126', tags) + + # Print the object information. + print('\nThe following information was returned as a Number object:\n') + print(' number : %s' % number.number) + print(' country : %s' % number.country) + print(' region : %s' % number.region) + print(' locality : %s' % number.locality) + print(' features : %s' % number.features) + print(' tags : %s' % number.tags) + print(' type : %s' % number.type) + print(' status : %s' % number.status) + +except messagebird.client.ErrorException as e: + print('\nAn error occured while requesting a NumberList object:\n') + + for error in e.errors: + print(' code : %d' % error.code) + print(' description : %s' % error.description) + print(' parameter : %s\n' % error.parameter) diff --git a/messagebird/client.py b/messagebird/client.py index a302ea6..6699d87 100644 --- a/messagebird/client.py +++ b/messagebird/client.py @@ -522,6 +522,13 @@ def purchase_number(self, number, country, billingIntervalMonths=1): params = {'number': str(number), 'countryCode': str(country), 'billingIntervalMonths': int(billingIntervalMonths)} return Number().load(self.request(NUMBER_PATH, 'POST', params, NUMBER_TYPE)) + def update_number(self, number, tags): + params = {'tags': tags} + return Number().load(self.request(NUMBER_PATH + '/' + str(number), 'PATCH', params, VOICE_TYPE)) + + def delete_number(self, number): + self.request(NUMBER_PATH + '/' + str(number), 'DELETE', None, VOICE_TYPE) + @staticmethod def generate_voice_calls_url(call_id=None, leg_id=None, recording_id=None): uri = VOICE_API_ROOT + '/' + VOICE_PATH + '/' From c23250cd12d2d1b80681bcb8a6daac8b956143d1 Mon Sep 17 00:00:00 2001 From: Yulia Burykina Date: Thu, 9 Jan 2020 14:43:18 +0100 Subject: [PATCH 05/19] added test for available_numbers_list call --- tests/test_number.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/test_number.py diff --git a/tests/test_number.py b/tests/test_number.py new file mode 100644 index 0000000..62b55cc --- /dev/null +++ b/tests/test_number.py @@ -0,0 +1,24 @@ +import unittest +from messagebird import Client, ErrorException + +try: + from unittest.mock import Mock +except ImportError: + # mock was added to unittest in Python 3.3, but was an external library + # before. + from mock import Mock + + +class TestNumber(unittest.TestCase): + + def test_available_numbers_list(self): + http_client = Mock() + http_client.request.return_value = '{"items":[{"number":"3197010260188","country":"NL","region":"","locality":"","features":["sms","voice"],"type":"mobile"}],"limit":20,"count":1}' + + numbers = Client('', http_client).available_numbers_list('NL', {'number': 319}) + + http_client.request.assert_called_once_with('available-phone-numbers/NL', 'GET', {'number': 319, 'limit': 20, 'offset': 0}) + + self.assertEqual(1, numbers.count) + self.assertEqual(1, len(numbers.items)) + self.assertEqual('3197010260188', numbers.items[0].number) From d67324f83bb97b7a95790362cd1faf56776af91b Mon Sep 17 00:00:00 2001 From: Yulia Burykina Date: Thu, 9 Jan 2020 17:07:33 +0100 Subject: [PATCH 06/19] added purchase_number call test --- tests/test_number.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/test_number.py b/tests/test_number.py index 62b55cc..65bb096 100644 --- a/tests/test_number.py +++ b/tests/test_number.py @@ -22,3 +22,22 @@ def test_available_numbers_list(self): self.assertEqual(1, numbers.count) self.assertEqual(1, len(numbers.items)) self.assertEqual('3197010260188', numbers.items[0].number) + + def test_purchase_number(self): + http_client = Mock() + http_client.request.return_value = '{"number":"31971234567","country":"NL","region":"Haarlem","locality":"Haarlem","features":["sms","voice"],"tags":[],"type":"landline_or_mobile","status":"active","createdAt":"2019-04-25T14:04:04Z","renewalAt":"2019-05-25T00:00:00Z"}' + + number = Client('', http_client).purchase_number('31971234567', 'NL', 1) + + http_client.request.assert_called_once_with( + 'phone-numbers', 'POST', + { + "number": "31971234567", + "countryCode": "NL", + "billingIntervalMonths": 1 + } + ) + + self.assertEqual('Haarlem', number.region) + self.assertEqual(["sms", "voice"], number.features) + From 1f01068887f6199a33b651f871113fbd2812d6c3 Mon Sep 17 00:00:00 2001 From: Yulia Burykina Date: Fri, 10 Jan 2020 09:59:52 +0100 Subject: [PATCH 07/19] added tests for delete_number call --- tests/test_number.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/test_number.py b/tests/test_number.py index 65bb096..fe56d42 100644 --- a/tests/test_number.py +++ b/tests/test_number.py @@ -41,3 +41,20 @@ def test_purchase_number(self): self.assertEqual('Haarlem', number.region) self.assertEqual(["sms", "voice"], number.features) + def test_delete_number(self): + http_client = Mock() + http_client.request.return_value = '{}' + + Client('', http_client).delete_number('31971234567') + + http_client.request.assert_called_once_with('phone-numbers/31971234567', 'DELETE', None) + + def test_delete_number_invalid(self): + http_client = Mock() + http_client.request.return_value = '{"errors": [{"code": 20, "description": "number not found", "parameter": null}]}' + + with self.assertRaises(ErrorException): + Client('', http_client).delete_number('non-existent-number') + + http_client.request.assert_called_once_with('phone-numbers/non-existent-number', 'DELETE', None) + From 47f64fec6dc9df6063e8efc39513682956b9c418 Mon Sep 17 00:00:00 2001 From: Iuliia Filatova Date: Fri, 10 Jan 2020 13:23:27 +0100 Subject: [PATCH 08/19] added fetching purchased number and list --- examples/fetching_a_purchased_phone_number.py | 59 ++++++++++++++++ .../fetching_all_purchased_phone_numbers.py | 68 +++++++++++++++++++ messagebird/base_list.py | 7 +- messagebird/client.py | 10 +++ 4 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 examples/fetching_a_purchased_phone_number.py create mode 100644 examples/fetching_all_purchased_phone_numbers.py diff --git a/examples/fetching_a_purchased_phone_number.py b/examples/fetching_a_purchased_phone_number.py new file mode 100644 index 0000000..9eabb72 --- /dev/null +++ b/examples/fetching_a_purchased_phone_number.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +import os +import sys +import argparse +import requests + +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) +import messagebird + +parser = argparse.ArgumentParser() +parser.add_argument('--accessKey', help='Access key for MessageBird API.', type=str, required=True) +parser.add_argument('--phoneNumber', help='Phone number.', type=str, required=True) +args = vars(parser.parse_args()) + +try: + # Create a MessageBird client with the specified accessKey. + client = messagebird.Client(args['accessKey']) + del(args['accessKey']) + + # Fetching all purchased phone numbers. + item = client.fetching_a_purchased_phone_number(**args) + + # Print the object information. + print('\nThe following information was returned as a %s object:\n' % item.__class__) + if item is not None: + print(' {') + print(' number : %s' % item.number) + print(' country : %s' % item.country) + print(' region : %s' % item.region) + print(' locality : %s' % item.locality) + print(' features : %s' % item.features) + print(' tags : %s' % item.tags) + print(' type : %s' % item.type) + print(' status : %s' % item.status) + print(' },') + else: + print(' With an empty response.') + +except messagebird.client.ErrorException as e: + print('\nAn error occurred while fetching all purchased phone numbers:\n') + + for error in e.errors: + print(' code : %d' % error.code) + print(' description : %s' % error.description) + print(' parameter : %s' % error.parameter) + print(' type : %s' % error.__class__) + +except requests.exceptions.HTTPError as e: + print('\nAn HTTP exception occurred while fetching all purchased phone numbers:') + print(' ', e) + print(' Http request body: ', e.request.body) + print(' Http response status: ', e.response.status_code) + print(' Http response body: ', e.response.content.decode()) + +except Exception as e: + print('\nAn ', e.__class__, ' exception occurred while :') + print(e) + + diff --git a/examples/fetching_all_purchased_phone_numbers.py b/examples/fetching_all_purchased_phone_numbers.py new file mode 100644 index 0000000..e93fe6a --- /dev/null +++ b/examples/fetching_all_purchased_phone_numbers.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +import os +import sys +import argparse +import requests + +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) +import messagebird + +parser = argparse.ArgumentParser() +parser.add_argument('--accessKey', help='Access key for MessageBird API.', type=str, required=True) +parser.add_argument('--limit', help='Limit the amount of results per page.', type=int, required=False, default=20) +parser.add_argument('--offset', help='Skip first n results.', type=int, required=False, default=0) +parser.add_argument('--features', help='Features for which search is done.', type=str, required=False, default=None) +parser.add_argument('--tags', help='Tags for which search is done.', type=str, required=False, default=None) +parser.add_argument('--number', help='Fragment of number.', type=str, required=False, default=None) +parser.add_argument('--region', help='Fragment of region data.', type=str, required=False, default=None) +parser.add_argument('--locality', help='Fragment of locality data.', type=str, required=False, default=None) +parser.add_argument('--type', help='Number type.', type=str, required=False, default=None) +args = vars(parser.parse_args()) + +try: + # Create a MessageBird client with the specified accessKey. + client = messagebird.Client(args['accessKey']) + del(args['accessKey']) + + # Fetching all purchased phone numbers. + numbers = client.fetching_all_purchased_phone_numbers(args) + + # Print the object information. + print('\nThe following information was returned as a %s object:\n' % numbers.__class__) + if numbers.items is not None: + print(' Containing the the following items:') + for item in numbers.items: + print(' {') + print(' number : %s' % item.number) + print(' country : %s' % item.country) + print(' region : %s' % item.region) + print(' locality : %s' % item.locality) + print(' features : %s' % item.features) + print(' tags : %s' % item.tags) + print(' type : %s' % item.type) + print(' status : %s' % item.status) + print(' },') + else: + print(' With an empty response.') + +except messagebird.client.ErrorException as e: + print('\nAn error occurred while fetching all purchased phone numbers:\n') + + for error in e.errors: + print(' code : %d' % error.code) + print(' description : %s' % error.description) + print(' parameter : %s' % error.parameter) + print(' type : %s' % error.__class__) + +except requests.exceptions.HTTPError as e: + print('\nAn HTTP exception occurred while fetching all purchased phone numbers:') + print(' ', e) + print(' Http request body: ', e.request.body) + print(' Http response status: ', e.response.status_code) + print(' Http response body: ', e.response.content.decode()) + +except Exception as e: + print('\nAn ', e.__class__, ' exception occurred while :') + print(e) + + diff --git a/messagebird/base_list.py b/messagebird/base_list.py index 0618170..37010f8 100644 --- a/messagebird/base_list.py +++ b/messagebird/base_list.py @@ -38,9 +38,10 @@ def items(self): @items.setter def items(self, value): """Create typed objects from the dicts.""" - items = [] - for item in value: - items.append(self.itemType().load(item)) + + if value is not None: + for item in value: + items.append(self.itemType().load(item)) self._items = items diff --git a/messagebird/client.py b/messagebird/client.py index 6699d87..de479d5 100644 --- a/messagebird/client.py +++ b/messagebird/client.py @@ -529,6 +529,16 @@ def update_number(self, number, tags): def delete_number(self, number): self.request(NUMBER_PATH + '/' + str(number), 'DELETE', None, VOICE_TYPE) + def fetching_all_purchased_phone_numbers(self, params={}): + if params['limit'] is None: + params['limit'] = 20 + if params['offset'] is None: + params['offset'] = 0 + return NumberList().load(self.request(NUMBER_PATH, 'GET', params, NUMBER_TYPE)) + + def fetching_a_purchased_phone_number(self, phoneNumber): + return Number().load(self.request(NUMBER_PATH + '/' + phoneNumber, 'GET', None, NUMBER_TYPE)) + @staticmethod def generate_voice_calls_url(call_id=None, leg_id=None, recording_id=None): uri = VOICE_API_ROOT + '/' + VOICE_PATH + '/' From 5af69cf5bc64cac82d916f9e7d66d4f516a03526 Mon Sep 17 00:00:00 2001 From: Iuliia Filatova Date: Fri, 10 Jan 2020 13:30:57 +0100 Subject: [PATCH 09/19] items --- messagebird/base_list.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/messagebird/base_list.py b/messagebird/base_list.py index 37010f8..cca865b 100644 --- a/messagebird/base_list.py +++ b/messagebird/base_list.py @@ -38,7 +38,7 @@ def items(self): @items.setter def items(self, value): """Create typed objects from the dicts.""" - + items = [] if value is not None: for item in value: items.append(self.itemType().load(item)) From 808556df29079816ec2fb6019920998936a29315 Mon Sep 17 00:00:00 2001 From: Yulia Burykina Date: Fri, 10 Jan 2020 14:07:43 +0100 Subject: [PATCH 10/19] standardization refactoring --- examples/number_available_list.py | 13 ++++++++++++- examples/number_purchase.py | 13 ++++++++++++- ...ed_phone_number.py => number_purchased.py} | 3 +-- ...ne_numbers.py => number_purchased_list.py} | 11 ++++++++++- examples/number_update.py | 13 ++++++++++++- messagebird/client.py | 19 ++++++------------- 6 files changed, 53 insertions(+), 19 deletions(-) rename examples/{fetching_a_purchased_phone_number.py => number_purchased.py} (96%) rename examples/{fetching_all_purchased_phone_numbers.py => number_purchased_list.py} (91%) diff --git a/examples/number_available_list.py b/examples/number_available_list.py index a5dff87..e3562ee 100644 --- a/examples/number_available_list.py +++ b/examples/number_available_list.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -import sys, os, argparse +import sys, os, argparse, requests sys.path.append(os.path.join(os.path.dirname(__file__), '..')) import messagebird @@ -42,3 +42,14 @@ print(' code : %d' % error.code) print(' description : %s' % error.description) print(' parameter : %s\n' % error.parameter) + +except requests.exceptions.HTTPError as e: + print('\nAn HTTP exception occurred while fetching all purchased phone numbers:') + print(' ', e) + print(' Http request body: ', e.request.body) + print(' Http response status: ', e.response.status_code) + print(' Http response body: ', e.response.content.decode()) + +except Exception as e: + print('\nAn ', e.__class__, ' exception occurred while :') + print(e) \ No newline at end of file diff --git a/examples/number_purchase.py b/examples/number_purchase.py index 620d43c..8c66068 100644 --- a/examples/number_purchase.py +++ b/examples/number_purchase.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -import sys, os, argparse +import sys, os, argparse, requests sys.path.append(os.path.join(os.path.dirname(__file__), '..')) import messagebird @@ -34,3 +34,14 @@ print(' code : %d' % error.code) print(' description : %s' % error.description) print(' parameter : %s\n' % error.parameter) + +except requests.exceptions.HTTPError as e: + print('\nAn HTTP exception occurred while fetching all purchased phone numbers:') + print(' ', e) + print(' Http request body: ', e.request.body) + print(' Http response status: ', e.response.status_code) + print(' Http response body: ', e.response.content.decode()) + +except Exception as e: + print('\nAn ', e.__class__, ' exception occurred while :') + print(e) \ No newline at end of file diff --git a/examples/fetching_a_purchased_phone_number.py b/examples/number_purchased.py similarity index 96% rename from examples/fetching_a_purchased_phone_number.py rename to examples/number_purchased.py index 9eabb72..e04fa71 100644 --- a/examples/fetching_a_purchased_phone_number.py +++ b/examples/number_purchased.py @@ -15,10 +15,9 @@ try: # Create a MessageBird client with the specified accessKey. client = messagebird.Client(args['accessKey']) - del(args['accessKey']) # Fetching all purchased phone numbers. - item = client.fetching_a_purchased_phone_number(**args) + item = client.purchased_number(args['phoneNumber']) # Print the object information. print('\nThe following information was returned as a %s object:\n' % item.__class__) diff --git a/examples/fetching_all_purchased_phone_numbers.py b/examples/number_purchased_list.py similarity index 91% rename from examples/fetching_all_purchased_phone_numbers.py rename to examples/number_purchased_list.py index e93fe6a..4d88c35 100644 --- a/examples/fetching_all_purchased_phone_numbers.py +++ b/examples/number_purchased_list.py @@ -24,8 +24,17 @@ client = messagebird.Client(args['accessKey']) del(args['accessKey']) + limit = 20 + offset = 0 + if args['limit'] is not None: + limit = args['limit'] + del(args['limit']) + if args['offset'] is not None: + limit = args['offset'] + del(args['offset']) + # Fetching all purchased phone numbers. - numbers = client.fetching_all_purchased_phone_numbers(args) + numbers = client.purchased_numbers_list(args, limit, offset) # Print the object information. print('\nThe following information was returned as a %s object:\n' % numbers.__class__) diff --git a/examples/number_update.py b/examples/number_update.py index c1a9e64..73be069 100644 --- a/examples/number_update.py +++ b/examples/number_update.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -import sys, os, argparse +import sys, os, argparse, requests sys.path.append(os.path.join(os.path.dirname(__file__), '..')) import messagebird @@ -36,3 +36,14 @@ print(' code : %d' % error.code) print(' description : %s' % error.description) print(' parameter : %s\n' % error.parameter) + +except requests.exceptions.HTTPError as e: + print('\nAn HTTP exception occurred while fetching all purchased phone numbers:') + print(' ', e) + print(' Http request body: ', e.request.body) + print(' Http response status: ', e.response.status_code) + print(' Http response body: ', e.response.content.decode()) + +except Exception as e: + print('\nAn ', e.__class__, ' exception occurred while :') + print(e) \ No newline at end of file diff --git a/messagebird/client.py b/messagebird/client.py index de479d5..9b2a43d 100644 --- a/messagebird/client.py +++ b/messagebird/client.py @@ -507,15 +507,10 @@ def call_flow_numbers_add(self, call_flow_id, numbers=()): def _format_query(self, limit, offset): return 'limit=' + str(limit) + '&offset=' + str(offset) - def available_numbers_list(self, country, params=None, limit=20, offset=0): + def available_numbers_list(self, country, params={}, limit=20, offset=0): """Retrieve a list of phone numbers available for purchase.""" - # todo: add test - if params is None: - params = {} - params['limit'] = limit params['offset'] = offset - return NumberList().load(self.request(NUMBER_AVAILABLE_PATH + '/' + str(country), 'GET', params, NUMBER_TYPE)) def purchase_number(self, number, country, billingIntervalMonths=1): @@ -529,15 +524,13 @@ def update_number(self, number, tags): def delete_number(self, number): self.request(NUMBER_PATH + '/' + str(number), 'DELETE', None, VOICE_TYPE) - def fetching_all_purchased_phone_numbers(self, params={}): - if params['limit'] is None: - params['limit'] = 20 - if params['offset'] is None: - params['offset'] = 0 + def purchased_numbers_list(self, params={}, limit=20, offset=0): + params['limit'] = limit + params['offset'] = offset return NumberList().load(self.request(NUMBER_PATH, 'GET', params, NUMBER_TYPE)) - def fetching_a_purchased_phone_number(self, phoneNumber): - return Number().load(self.request(NUMBER_PATH + '/' + phoneNumber, 'GET', None, NUMBER_TYPE)) + def purchased_number(self, number): + return Number().load(self.request(NUMBER_PATH + '/' + number, 'GET', None, NUMBER_TYPE)) @staticmethod def generate_voice_calls_url(call_id=None, leg_id=None, recording_id=None): From d530565378b43b6ec2a119070432d0bf528119f7 Mon Sep 17 00:00:00 2001 From: Yulia Burykina Date: Fri, 10 Jan 2020 14:18:05 +0100 Subject: [PATCH 11/19] added tests for getting purchased numbers --- tests/test_number.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/test_number.py b/tests/test_number.py index fe56d42..d1ab76b 100644 --- a/tests/test_number.py +++ b/tests/test_number.py @@ -58,3 +58,23 @@ def test_delete_number_invalid(self): http_client.request.assert_called_once_with('phone-numbers/non-existent-number', 'DELETE', None) + def test_purchased_number(self): + http_client = Mock() + http_client.request.return_value = '{"number":"31612345670","country":"NL","region":"Texel","locality":"Texel","features":["sms","voice"],"tags":[],"type":"mobile","status":"active"}' + number = Client('', http_client).purchased_number('31612345670') + + http_client.request.assert_called_once_with('phone-numbers/31612345670', 'GET', None) + + self.assertEqual('Texel', number.locality) + + def test_purchased_numbers_list(self): + http_client = Mock() + http_client.request.return_value = '{"items":[{"number":"3197010260188","country":"NL","region":"","locality":"","features":["sms","voice"],"type":"mobile"}],"limit":20,"count":1}' + + numbers = Client('', http_client).purchased_numbers_list({'number': 319}, 40, 2) + + http_client.request.assert_called_once_with('phone-numbers', 'GET', {'number': 319, 'limit': 40, 'offset': 2}) + + self.assertEqual(1, numbers.count) + self.assertEqual(1, len(numbers.items)) + self.assertEqual('3197010260188', numbers.items[0].number) \ No newline at end of file From 04a3525201f150fcfe62be8997e09545f9b2d7b0 Mon Sep 17 00:00:00 2001 From: Yulia Burykina Date: Fri, 10 Jan 2020 14:25:19 +0100 Subject: [PATCH 12/19] small fixes --- examples/number_purchased_list.py | 2 +- messagebird/client.py | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/number_purchased_list.py b/examples/number_purchased_list.py index 4d88c35..0c6a7df 100644 --- a/examples/number_purchased_list.py +++ b/examples/number_purchased_list.py @@ -30,7 +30,7 @@ limit = args['limit'] del(args['limit']) if args['offset'] is not None: - limit = args['offset'] + offset = args['offset'] del(args['offset']) # Fetching all purchased phone numbers. diff --git a/messagebird/client.py b/messagebird/client.py index 9b2a43d..e3f819f 100644 --- a/messagebird/client.py +++ b/messagebird/client.py @@ -538,6 +538,4 @@ def generate_voice_calls_url(call_id=None, leg_id=None, recording_id=None): uri += str(call_id) + '/' + VOICE_LEGS_PATH + '/' + str(leg_id) + '/' + VOICE_RECORDINGS_PATH if recording_id: uri += '/' + str(recording_id) + '/' + VOICE_TRANSCRIPTIONS_PATH - return uri - - + return uri \ No newline at end of file From 69bd22ed53ef036127ef05f8fdd04135b0dd750f Mon Sep 17 00:00:00 2001 From: Yulia Burykina Date: Fri, 10 Jan 2020 14:28:06 +0100 Subject: [PATCH 13/19] indentation fixes --- examples/number_available_list.py | 2 +- examples/number_purchase.py | 2 +- examples/number_purchased.py | 1 + examples/number_purchased_list.py | 1 + examples/number_update.py | 2 +- messagebird/client.py | 2 +- 6 files changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/number_available_list.py b/examples/number_available_list.py index e3562ee..e2df0ac 100644 --- a/examples/number_available_list.py +++ b/examples/number_available_list.py @@ -52,4 +52,4 @@ except Exception as e: print('\nAn ', e.__class__, ' exception occurred while :') - print(e) \ No newline at end of file + print(e) diff --git a/examples/number_purchase.py b/examples/number_purchase.py index 8c66068..fb74aab 100644 --- a/examples/number_purchase.py +++ b/examples/number_purchase.py @@ -44,4 +44,4 @@ except Exception as e: print('\nAn ', e.__class__, ' exception occurred while :') - print(e) \ No newline at end of file + print(e) diff --git a/examples/number_purchased.py b/examples/number_purchased.py index e04fa71..8bed53a 100644 --- a/examples/number_purchased.py +++ b/examples/number_purchased.py @@ -56,3 +56,4 @@ print(e) + diff --git a/examples/number_purchased_list.py b/examples/number_purchased_list.py index 0c6a7df..0d86f71 100644 --- a/examples/number_purchased_list.py +++ b/examples/number_purchased_list.py @@ -75,3 +75,4 @@ print(e) + diff --git a/examples/number_update.py b/examples/number_update.py index 73be069..0b4669c 100644 --- a/examples/number_update.py +++ b/examples/number_update.py @@ -46,4 +46,4 @@ except Exception as e: print('\nAn ', e.__class__, ' exception occurred while :') - print(e) \ No newline at end of file + print(e) diff --git a/messagebird/client.py b/messagebird/client.py index e3f819f..681cbdf 100644 --- a/messagebird/client.py +++ b/messagebird/client.py @@ -538,4 +538,4 @@ def generate_voice_calls_url(call_id=None, leg_id=None, recording_id=None): uri += str(call_id) + '/' + VOICE_LEGS_PATH + '/' + str(leg_id) + '/' + VOICE_RECORDINGS_PATH if recording_id: uri += '/' + str(recording_id) + '/' + VOICE_TRANSCRIPTIONS_PATH - return uri \ No newline at end of file + return uri From d344b8be7473a177c0ac8bb36c4662659bf662b2 Mon Sep 17 00:00:00 2001 From: Yulia Burykina Date: Fri, 10 Jan 2020 16:24:55 +0100 Subject: [PATCH 14/19] indentation fix --- tests/test_number.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_number.py b/tests/test_number.py index d1ab76b..dc231f6 100644 --- a/tests/test_number.py +++ b/tests/test_number.py @@ -77,4 +77,4 @@ def test_purchased_numbers_list(self): self.assertEqual(1, numbers.count) self.assertEqual(1, len(numbers.items)) - self.assertEqual('3197010260188', numbers.items[0].number) \ No newline at end of file + self.assertEqual('3197010260188', numbers.items[0].number) From a66cfee3101771fbc63f85e09c6fe8876d8127a7 Mon Sep 17 00:00:00 2001 From: Yulia Burykina Date: Mon, 13 Jan 2020 09:33:26 +0100 Subject: [PATCH 15/19] small fixes --- examples/{number_purchased.py => number_purchased_view.py} | 0 messagebird/client.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename examples/{number_purchased.py => number_purchased_view.py} (100%) diff --git a/examples/number_purchased.py b/examples/number_purchased_view.py similarity index 100% rename from examples/number_purchased.py rename to examples/number_purchased_view.py diff --git a/messagebird/client.py b/messagebird/client.py index 681cbdf..a445958 100644 --- a/messagebird/client.py +++ b/messagebird/client.py @@ -522,7 +522,7 @@ def update_number(self, number, tags): return Number().load(self.request(NUMBER_PATH + '/' + str(number), 'PATCH', params, VOICE_TYPE)) def delete_number(self, number): - self.request(NUMBER_PATH + '/' + str(number), 'DELETE', None, VOICE_TYPE) + self.request(NUMBER_PATH + '/' + str(number), 'DELETE', None, NUMBER_TYPE) def purchased_numbers_list(self, params={}, limit=20, offset=0): params['limit'] = limit From 5166e7016d6cf98183ae61806dfd04e75c337ba9 Mon Sep 17 00:00:00 2001 From: Yulia Burykina Date: Mon, 13 Jan 2020 09:48:17 +0100 Subject: [PATCH 16/19] typo fix --- messagebird/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/messagebird/client.py b/messagebird/client.py index a445958..f855971 100644 --- a/messagebird/client.py +++ b/messagebird/client.py @@ -519,7 +519,7 @@ def purchase_number(self, number, country, billingIntervalMonths=1): def update_number(self, number, tags): params = {'tags': tags} - return Number().load(self.request(NUMBER_PATH + '/' + str(number), 'PATCH', params, VOICE_TYPE)) + return Number().load(self.request(NUMBER_PATH + '/' + str(number), 'PATCH', params, NUMBER_TYPE)) def delete_number(self, number): self.request(NUMBER_PATH + '/' + str(number), 'DELETE', None, NUMBER_TYPE) From 65f667002cf2df568202e68a16748962fbaf4084 Mon Sep 17 00:00:00 2001 From: Yulia Burykina Date: Mon, 13 Jan 2020 10:03:20 +0100 Subject: [PATCH 17/19] style fixes --- examples/number_available_list.py | 6 +++++- examples/number_purchase.py | 6 +++++- examples/number_update.py | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/examples/number_available_list.py b/examples/number_available_list.py index e2df0ac..9221094 100644 --- a/examples/number_available_list.py +++ b/examples/number_available_list.py @@ -1,6 +1,10 @@ #!/usr/bin/env python -import sys, os, argparse, requests +import sys +import os +import argparse +import requests + sys.path.append(os.path.join(os.path.dirname(__file__), '..')) import messagebird diff --git a/examples/number_purchase.py b/examples/number_purchase.py index fb74aab..586dd37 100644 --- a/examples/number_purchase.py +++ b/examples/number_purchase.py @@ -1,6 +1,10 @@ #!/usr/bin/env python -import sys, os, argparse, requests +import sys +import os +import argparse +import requests + sys.path.append(os.path.join(os.path.dirname(__file__), '..')) import messagebird diff --git a/examples/number_update.py b/examples/number_update.py index 0b4669c..45d9b73 100644 --- a/examples/number_update.py +++ b/examples/number_update.py @@ -1,6 +1,10 @@ #!/usr/bin/env python -import sys, os, argparse, requests +import sys +import os +import argparse +import requests + sys.path.append(os.path.join(os.path.dirname(__file__), '..')) import messagebird From d28a861c59e2ee1b6ef4329df205ee310fb7c31c Mon Sep 17 00:00:00 2001 From: Oleh Bahinskyi Date: Mon, 13 Jan 2020 11:42:47 +0100 Subject: [PATCH 18/19] pep8 --- examples/number_purchase.py | 42 ++++++++++++++++----------------- examples/number_update.py | 46 ++++++++++++++++++------------------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/examples/number_purchase.py b/examples/number_purchase.py index 586dd37..63f72d9 100644 --- a/examples/number_purchase.py +++ b/examples/number_purchase.py @@ -14,30 +14,30 @@ args = vars(parser.parse_args()) try: - # Create a MessageBird client with the specified accessKey. - client = messagebird.Client(args['accessKey']) - - # Purchase number - number = client.purchase_number('3197010240126', 'NL', 3) - - # Print the object information. - print('\nThe following information was returned as a Number object:\n') - print(' number : %s' % number.number) - print(' country : %s' % number.country) - print(' region : %s' % number.region) - print(' locality : %s' % number.locality) - print(' features : %s' % number.features) - print(' tags : %s' % number.tags) - print(' type : %s' % number.type) - print(' status : %s' % number.status) + # Create a MessageBird client with the specified accessKey. + client = messagebird.Client(args['accessKey']) + + # Purchase number + number = client.purchase_number('3197010240126', 'NL', 3) + + # Print the object information. + print('\nThe following information was returned as a Number object:\n') + print(' number : %s' % number.number) + print(' country : %s' % number.country) + print(' region : %s' % number.region) + print(' locality : %s' % number.locality) + print(' features : %s' % number.features) + print(' tags : %s' % number.tags) + print(' type : %s' % number.type) + print(' status : %s' % number.status) except messagebird.client.ErrorException as e: - print('\nAn error occured while requesting a NumberList object:\n') + print('\nAn error occured while requesting a NumberList object:\n') - for error in e.errors: - print(' code : %d' % error.code) - print(' description : %s' % error.description) - print(' parameter : %s\n' % error.parameter) + for error in e.errors: + print(' code : %d' % error.code) + print(' description : %s' % error.description) + print(' parameter : %s\n' % error.parameter) except requests.exceptions.HTTPError as e: print('\nAn HTTP exception occurred while fetching all purchased phone numbers:') diff --git a/examples/number_update.py b/examples/number_update.py index 45d9b73..df653dd 100644 --- a/examples/number_update.py +++ b/examples/number_update.py @@ -14,32 +14,32 @@ args = vars(parser.parse_args()) try: - # Create a MessageBird client with the specified accessKey. - client = messagebird.Client(args['accessKey']) - - # Update number - # Note: at the moment, we only support updating tags that can be used to group or label numbers - tags = ['tag1'] - number = client.update_number('3197010240126', tags) - - # Print the object information. - print('\nThe following information was returned as a Number object:\n') - print(' number : %s' % number.number) - print(' country : %s' % number.country) - print(' region : %s' % number.region) - print(' locality : %s' % number.locality) - print(' features : %s' % number.features) - print(' tags : %s' % number.tags) - print(' type : %s' % number.type) - print(' status : %s' % number.status) + # Create a MessageBird client with the specified accessKey. + client = messagebird.Client(args['accessKey']) + + # Update number + # Note: at the moment, we only support updating tags that can be used to group or label numbers + tags = ['tag1'] + number = client.update_number('3197010240126', tags) + + # Print the object information. + print('\nThe following information was returned as a Number object:\n') + print(' number : %s' % number.number) + print(' country : %s' % number.country) + print(' region : %s' % number.region) + print(' locality : %s' % number.locality) + print(' features : %s' % number.features) + print(' tags : %s' % number.tags) + print(' type : %s' % number.type) + print(' status : %s' % number.status) except messagebird.client.ErrorException as e: - print('\nAn error occured while requesting a NumberList object:\n') + print('\nAn error occured while requesting a NumberList object:\n') - for error in e.errors: - print(' code : %d' % error.code) - print(' description : %s' % error.description) - print(' parameter : %s\n' % error.parameter) + for error in e.errors: + print(' code : %d' % error.code) + print(' description : %s' % error.description) + print(' parameter : %s\n' % error.parameter) except requests.exceptions.HTTPError as e: print('\nAn HTTP exception occurred while fetching all purchased phone numbers:') From 58b18e6c7b94492d02e89cc939353773c9e67fb4 Mon Sep 17 00:00:00 2001 From: Oleh Bahinskyi Date: Mon, 13 Jan 2020 11:45:22 +0100 Subject: [PATCH 19/19] pep8 --- examples/number_available_list.py | 58 +++++++++++++++---------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/examples/number_available_list.py b/examples/number_available_list.py index 9221094..c5dd3a0 100644 --- a/examples/number_available_list.py +++ b/examples/number_available_list.py @@ -14,38 +14,38 @@ args = vars(parser.parse_args()) try: - # Create a MessageBird client with the specified accessKey. - client = messagebird.Client(args['accessKey']) - - # Fetch the NumberList object with specified params, limit, offset. - params = {'features': ['sms', 'voice'], 'number': 319} - numbers = client.available_numbers_list('NL', params, 2, 0) - - # Print the object information. - print('\nThe following information was returned as a %s object:\n' % numbers.__class__) - if numbers.items is not None: - print(' Containing the the following items:') - for item in numbers.items: - print(' {') - print(' number : %s' % item.number) - print(' country : %s' % item.country) - print(' region : %s' % item.region) - print(' locality : %s' % item.locality) - print(' features : %s' % item.features) - print(' tags : %s' % item.tags) - print(' type : %s' % item.type) - print(' status : %s' % item.status) - print(' },') - else: - print(' With an empty response.') + # Create a MessageBird client with the specified accessKey. + client = messagebird.Client(args['accessKey']) + + # Fetch the NumberList object with specified params, limit, offset. + params = {'features': ['sms', 'voice'], 'number': 319} + numbers = client.available_numbers_list('NL', params, 2, 0) + + # Print the object information. + print('\nThe following information was returned as a %s object:\n' % numbers.__class__) + if numbers.items is not None: + print(' Containing the the following items:') + for item in numbers.items: + print(' {') + print(' number : %s' % item.number) + print(' country : %s' % item.country) + print(' region : %s' % item.region) + print(' locality : %s' % item.locality) + print(' features : %s' % item.features) + print(' tags : %s' % item.tags) + print(' type : %s' % item.type) + print(' status : %s' % item.status) + print(' },') + else: + print(' With an empty response.') except messagebird.client.ErrorException as e: - print('\nAn error occured while requesting a NumberList object:\n') + print('\nAn error occured while requesting a NumberList object:\n') - for error in e.errors: - print(' code : %d' % error.code) - print(' description : %s' % error.description) - print(' parameter : %s\n' % error.parameter) + for error in e.errors: + print(' code : %d' % error.code) + print(' description : %s' % error.description) + print(' parameter : %s\n' % error.parameter) except requests.exceptions.HTTPError as e: print('\nAn HTTP exception occurred while fetching all purchased phone numbers:')