Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
language: python
python:
- 'pypy2.7'
- 'pypy3.5'
- '2.7'
- '3.3'
- '3.6'
- 'nightly'
install:
- pip install mock==2.0
- pip install requests
script:
- python -m unittest discover -s tests/ -p test_*.py -v
matrix:
allow_failures:
- python: 'nightly'
- python: 'pypy2.7'
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ MessageBird's REST API for Python
=================================
This repository contains the open source Python client for MessageBird's REST API. Documentation can be found at: https://developers.messagebird.com/.

[![Build Status](https://travis-ci.org/messagebird/python-rest-api.svg?branch=master)](https://travis-ci.org/messagebird/python-rest-api)

Requirements
------------
- [Sign up](https://www.messagebird.com/en/signup) for a free MessageBird account
Expand Down
42 changes: 13 additions & 29 deletions messagebird/client.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
import sys
import json
import requests

try:
from urllib.parse import urljoin
except ImportError:
from urlparse import urljoin

from messagebird.base import Base
from messagebird.balance import Balance
from messagebird.error import Error
from messagebird.hlr import HLR
from messagebird.http_client import HttpClient
from messagebird.message import Message
from messagebird.voicemessage import VoiceMessage
from messagebird.lookup import Lookup
Expand All @@ -19,6 +14,7 @@
ENDPOINT = 'https://rest.messagebird.com'
CLIENT_VERSION = '1.2.1'
PYTHON_VERSION = '%d.%d.%d' % (sys.version_info[0], sys.version_info[1], sys.version_info[2])
USER_AGENT = 'MessageBird/ApiClient/%s Python/%s' % (CLIENT_VERSION, PYTHON_VERSION)


class ErrorException(Exception):
Expand All @@ -29,35 +25,23 @@ def __init__(self, errors):


class Client(object):
def __init__(self, access_key):
def __init__(self, access_key, http_client=None):
self.access_key = access_key
self._supported_status_codes = [200, 201, 204, 401, 404, 405, 422]

def request(self, path, method='GET', params=None):
if params is None: params = {}
url = urljoin(ENDPOINT, path)

headers = {
'Accept' : 'application/json',
'Authorization' : 'AccessKey ' + self.access_key,
'User-Agent' : 'MessageBird/ApiClient/%s Python/%s' % (CLIENT_VERSION, PYTHON_VERSION),
'Content-Type' : 'application/json'
}

if method == 'GET':
response = requests.get(url, verify=True, headers=headers, params=params)
if http_client is None:
self.http_client = HttpClient(ENDPOINT, access_key, USER_AGENT)
else:
response = requests.post(url, verify=True, headers=headers, data=json.dumps(params))
self.http_client = http_client

if response.status_code in self._supported_status_codes:
json_response = response.json()
else:
response.raise_for_status()
def request(self, path, method='GET', params=None):
"""Builds a request, gets a response and decodes it."""
response_text = self.http_client.request(path, method, params)
response_json = json.loads(response_text)

if 'errors' in json_response:
raise(ErrorException([Error().load(e) for e in json_response['errors']]))
if 'errors' in response_json:
raise(ErrorException([Error().load(e) for e in response_json['errors']]))

return json_response
return response_json

def balance(self):
"""Retrieve your balance."""
Expand Down
41 changes: 41 additions & 0 deletions messagebird/http_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import requests

try:
from urllib.parse import urljoin
except ImportError:
from urlparse import urljoin


class HttpClient(object):
"""Used for sending simple HTTP requests."""

def __init__(self, endpoint, access_key, user_agent):
self.__supported_status_codes = [200, 201, 204, 401, 404, 405, 422]

self.endpoint = endpoint
self.access_key = access_key
self.user_agent = user_agent

def request(self, path, method='GET', params=None):
"""Builds a request and gets a response."""
if params is None: params = {}
url = urljoin(self.endpoint, path)

headers = {
'Accept': 'application/json',
'Authorization': 'AccessKey ' + self.access_key,
'User-Agent': self.user_agent,
'Content-Type': 'application/json'
}

if method == 'GET':
response = requests.get(url, verify=True, headers=headers, params=params)
else:
response = requests.post(url, verify=True, headers=headers, data=json.dumps(params))

if response.status_code in self.__supported_status_codes:
response_text = response.text
else:
response.raise_for_status()

return response_text
Empty file added tests/__init__.py
Empty file.
23 changes: 23 additions & 0 deletions tests/test_balance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import unittest
from messagebird import Client

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 TestBalance(unittest.TestCase):

def test_balance(self):
http_client = Mock()
http_client.request.return_value = '{"payment": "prepaid","type": "credits","amount": 9.2}'

balance = Client('', http_client).balance()

http_client.request.assert_called_once_with('balance', 'GET', None)

self.assertEqual('prepaid', balance.payment)
self.assertEqual('credits', balance.type)
30 changes: 30 additions & 0 deletions tests/test_hlr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import unittest
from messagebird import Client

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 TestHLR(unittest.TestCase):

def test_hlr(self):
http_client = Mock()
http_client.request.return_value = '{"id":"hlr-id","href":"https://rest.messagebird.com/hlr/hlr-id","msisdn":31612345678,"network":20406,"reference":"MyReference","status": "sent","createdDatetime": "2015-01-04T13:14:08+00:00","statusDatetime": "2015-01-04T13:14:09+00:00"}'

hlr = Client('', http_client).hlr('hlr-id')

http_client.request.assert_called_once_with('hlr/hlr-id', 'GET', None)

self.assertEqual('hlr-id', hlr.id)

def test_hlr_create(self):
http_client = Mock()
http_client.request.return_value = '{}'

Client('', http_client).hlr_create(31612345678, 'MyReference')

http_client.request.assert_called_once_with('hlr', 'POST', {'msisdn': 31612345678, 'reference': 'MyReference'})
40 changes: 40 additions & 0 deletions tests/test_lookup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import unittest
from messagebird import Client

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 TestLookup(unittest.TestCase):

def test_lookup(self):
http_client = Mock()
http_client.request.return_value = '{"href": "https://rest.messagebird.com/lookup/31612345678","countryCode": "NL","countryPrefix": 31,"phoneNumber": 31612345678,"type": "mobile","formats": {"e164": "+31612345678","international": "+31 6 12345678","national": "06 12345678","rfc3966": "tel:+31-6-12345678"},"hlr": {"id": "hlr-id","network": 20416,"reference": "reference2000","status": "active","createdDatetime": "2015-12-15T08:19:24+00:00","statusDatetime": "2015-12-15T08:19:25+00:00"}}'

lookup = Client('', http_client).lookup('0612345678', {'countryCode': 'NL'})

http_client.request.assert_called_once_with('lookup/0612345678', 'GET', {'countryCode': 'NL'})

self.assertEqual('mobile', lookup.type)

def test_lookup_hlr(self):
http_client = Mock()
http_client.request.return_value = '{"id": "hlr-id","network": 20416,"reference": "reference2000","status": "active","createdDatetime": "2015-12-15T08:19:24+00:00","statusDatetime": "2015-12-15T08:19:25+00:00"}'

lookup_hlr = Client('', http_client).lookup_hlr(31612345678, {'reference': 'reference2000'})

http_client.request.assert_called_once_with('lookup/31612345678/hlr', 'GET', {'reference': 'reference2000'})

self.assertEqual(lookup_hlr.status, 'active')

def test_lookup_hlr_create(self):
http_client = Mock()
http_client.request.return_value = '{}'

Client('', http_client).lookup_hlr_create(31612345678, {'reference': 'MyReference'})

http_client.request.assert_called_once_with('lookup/31612345678/hlr', 'POST', {'reference': 'MyReference'})
30 changes: 30 additions & 0 deletions tests/test_message.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import unittest
from messagebird import Client

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 TestMessage(unittest.TestCase):

def test_message(self):
http_client = Mock()
http_client.request.return_value = '{"body": "Hello World","createdDatetime": "2015-01-05T10:02:59+00:00","datacoding": "plain","direction": "mt","gateway": 239,"href": "https://rest.messagebird.com/messages/message-id","id": "message-id","mclass": 1,"originator": "TestName","recipients": {"items": [{"recipient": 31612345678,"status": "sent","statusDatetime": "2015-01-05T10:02:59+00:00"}],"totalCount": 1,"totalDeliveredCount": 0,"totalDeliveryFailedCount": 0,"totalSentCount": 1},"reference": null,"scheduledDatetime": null,"type": "sms","typeDetails": {},"validity": null}'

message = Client('', http_client).message('message-id')

http_client.request.assert_called_once_with('messages/message-id', 'GET', None)

self.assertEqual('mt', message.direction)

def test_message_create(self):
http_client = Mock()
http_client.request.return_value = '{}'

Client('', http_client).message_create('MessageBird', ['31612345678', '31687654321'], 'Hello World', {'datacoding': 'unicode'})

http_client.request.assert_called_once_with('messages', 'POST', {'datacoding': 'unicode', 'originator': 'MessageBird', 'body': 'Hello World', 'recipients': '31612345678,31687654321' })
40 changes: 40 additions & 0 deletions tests/test_verify.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import unittest
from messagebird import Client

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 TestVerify(unittest.TestCase):

def test_verify(self):
http_client = Mock()
http_client.request.return_value = '{"id": "verify-id","href": "https://rest.messagebird.com/verify/verify-id","recipient": 31612345678,"reference": "MyReference","messages": {"href": "https://rest.messagebird.com/messages/message-id"},"status": "verified","createdDatetime": "2017-05-30T12:39:50+00:00","validUntilDatetime": "2017-05-30T12:40:20+00:00"}'

verify = Client('', http_client).verify('verify-id')

http_client.request.assert_called_once_with('verify/verify-id', 'GET', None)

self.assertEqual('verify-id', verify.id)

def test_verify_create(self):
http_client = Mock()
http_client.request.return_value = '{}'

Client('', http_client).verify_create('31612345678', {})

http_client.request.assert_called_once_with('verify', 'POST', {'recipient': '31612345678'})

def test_verify_verify(self):
http_client = Mock()
http_client.request.return_value = '{"id": "verify-id","href": "https://rest.messagebird.com/verify/verify-id","recipient": 31612345678,"reference": "MyReference","messages": {"href": "https://rest.messagebird.com/messages/63b168423592d681641eb07b76226648"},"status": "verified","createdDatetime": "2017-05-30T12:39:50+00:00","validUntilDatetime": "2017-05-30T12:40:20+00:00"}'

verify = Client('', http_client).verify_verify('verify-id', 'secret')

http_client.request.assert_called_once_with('verify/verify-id', 'GET', {'token': 'secret'})

self.assertEqual('verified', verify.status)
30 changes: 30 additions & 0 deletions tests/test_voicemessage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import unittest
from messagebird import Client

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 TestVoicemessage(unittest.TestCase):

def test_voicemessage(self):
http_client = Mock()
http_client.request.return_value = '{"body": "Hello World","createdDatetime": "2015-01-05T16:11:24+00:00","href": "https://rest.messagebird.com/voicemessages/voicemessage-id","id": "voicemessage-id","ifMachine": "continue","language": "en-gb","originator": "MessageBird","recipients": {"items": [{"recipient": 31612345678,"status": "calling","statusDatetime": "2015-01-05T16:11:24+00:00"}],"totalCount": 1,"totalDeliveredCount": 0,"totalDeliveryFailedCount": 0,"totalSentCount": 1},"reference": null,"repeat": 1,"scheduledDatetime": null,"voice": "female"}'

voice_message = Client('', http_client).voice_message('voicemessage-id')

http_client.request.assert_called_once_with('voicemessages/voicemessage-id', 'GET', None)

self.assertEqual('voicemessage-id', voice_message.id)

def test_voicemessage_create(self):
http_client = Mock()
http_client.request.return_value = '{}'

Client('', http_client).voice_message_create(['31612345678', '31687654321'], 'Hello World', { 'reference': 'MyReference' })

http_client.request.assert_called_once_with('voicemessages', 'POST', {'body': 'Hello World', 'recipients': '31612345678,31687654321', 'reference': 'MyReference'})