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
35 changes: 14 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,12 @@
## Install

The easiest way to install is through "pip":

pip install clockwork

## Requirements

* Python 2.6+
* [lxml][1]

For an easy life, we recommend installing lxml thorugh a package manager, e.g.:

sudo apt-get install python-lxml # Debian based
sudo yum install pyhton-lxml # Red Hat based

## Usage

Expand All @@ -32,7 +26,7 @@ else:
print (response.error_code)
print (response.error_message)
```

### Send multiple SMS messages

Simply pass an array of sms objects to the send method. Instead of sending back a single sms response, an array of sms responses will be returned:
Expand Down Expand Up @@ -64,11 +58,11 @@ This wrapper supports a subset of the available clockwork API parameters for sen
You create an `api` object with `api = clockwork.API(api_key,[optional_setting = value,..]`
The `optional_setting` parameters allows you to set the following, which will be used for all messages sent through the `api` object:

Parameter | Description
--------- | -----------
from_name | Sets the [from name](http://www.clockworksms.com/doc/clever-stuff/xml-interface/send-sms/#param-from "from address")
concat | Sets the [concat](http://www.clockworksms.com/doc/clever-stuff/xml-interface/send-sms/#param-concat) setting
invalid_char_option | Sets the [InvalidCharOption](http://www.clockworksms.com/doc/clever-stuff/xml-interface/send-sms/#param-invalidcharaction) setting
Parameter | Description
--------- | -----------
from_name | Sets the [from name](http://www.clockworksms.com/doc/clever-stuff/xml-interface/send-sms/#param-from "from address")
concat | Sets the [concat](http://www.clockworksms.com/doc/clever-stuff/xml-interface/send-sms/#param-concat) setting
invalid_char_option | Sets the [InvalidCharOption](http://www.clockworksms.com/doc/clever-stuff/xml-interface/send-sms/#param-invalidcharaction) setting
truncate | Sets the [truncate](http://www.clockworksms.com/doc/clever-stuff/xml-interface/send-sms/#param-truncate) setting

So for example if I want all messages to use the from address 'bobby', I would do:
Expand All @@ -82,12 +76,12 @@ So for example if I want all messages to use the from address 'bobby', I would d
You create an `sms` object with `sms = clockwork.SMS(to = 'xxx', message = 'xxx', [optional_setting = value,..]`

In a similar pattern to the API parameters, the `optional_setting` parameters allows you to set the following additional parameters for an individual message:
Parameter | Description
--------- | -----------
client_id | Sets the [ClientId](http://www.clockworksms.com/doc/clever-stuff/xml-interface/send-sms/#param-clientid) setting
from_name | Sets the [from name](http://www.clockworksms.com/doc/clever-stuff/xml-interface/send-sms/#param-from "from address")
invalid_char_option | Sets the [InvalidCharOption](http://www.clockworksms.com/doc/clever-stuff/xml-interface/send-sms/#param-invalidcharaction) setting

Parameter | Description
--------- | -----------
client_id | Sets the [ClientId](http://www.clockworksms.com/doc/clever-stuff/xml-interface/send-sms/#param-clientid) setting
from_name | Sets the [from name](http://www.clockworksms.com/doc/clever-stuff/xml-interface/send-sms/#param-from "from address")
invalid_char_option | Sets the [InvalidCharOption](http://www.clockworksms.com/doc/clever-stuff/xml-interface/send-sms/#param-invalidcharaction) setting
truncate | Sets the [truncate](http://www.clockworksms.com/doc/clever-stuff/xml-interface/send-sms/#param-truncate) setting

Any parameters defined here will take precedence over the same one defined on the `api` object:
Expand Down Expand Up @@ -119,10 +113,9 @@ If you have any feedback on this wrapper drop us an email to [hello@clockworksms

The project is hosted on GitHub at [http://www.github.com/mediaburst/clockwork-python][4].

If you would like to contribute a bug fix or improvement please fork the project
If you would like to contribute a bug fix or improvement please fork the project
and submit a pull request. Please add tests for your use case.

[1]: http://lxml.de/
[2]: http://www.clockworksms.com/doc/clever-stuff/xml-interface/send-sms/
[3]: mailto:hello@clockworksms.com
[4]: http://www.github.com/mediaburst/clockwork-python
Expand Down
2 changes: 2 additions & 0 deletions clockwork/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . clockwork import API, SMS
from . clockwork_exceptions import ApiException, AuthException, GenericException, HttpException
41 changes: 21 additions & 20 deletions clockwork/clockwork.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from lxml import etree
from . import clockwork_http
from xml.etree import ElementTree as etree
from . import clockwork_http
from . import clockwork_exceptions

SMS_URL = 'https://api.clockworksms.com/xml/send.aspx'
Expand All @@ -10,7 +10,7 @@
class SMS(object):
"""An SMS object"""

def __init__(self, to, message, client_id = None, from_name = None, long = None, truncate = None, invalid_char_option = None):
def __init__(self, to, message, client_id=None, from_name=None, long=None, truncate=None, invalid_char_option=None):
self.client_id = client_id
self.from_name = from_name
self.long = long
Expand All @@ -32,9 +32,10 @@ def __init__(self, sms, id, error_code, error_message, success):

class API(object):
"""Wraps the clockwork API"""
def __init__(self, apikey, from_name = 'Clockwork', concat = 3,
invalid_char_option = 'error', long = False, truncate = True,
use_ssl = True):

def __init__(self, apikey, from_name='Clockwork', concat=3,
invalid_char_option='error', long=False, truncate=True,
use_ssl=True):
self.apikey = apikey
self.from_name = from_name
self.concat = concat
Expand All @@ -49,10 +50,10 @@ def get_balance(self):
account_type: The account type
balance: The balance remaining on the account
currency: The currency used for the account balance. Assume GBP in not set"""

xml_root = self.__init_xml('Balance')

response = clockwork_http.request(BALANCE_URL,etree.tostring(xml_root, encoding='utf-8'))
response = clockwork_http.request(BALANCE_URL, etree.tostring(xml_root, encoding='utf-8'))
data_etree = etree.fromstring(response['data'])

err_desc = data_etree.find('ErrDesc')
Expand Down Expand Up @@ -80,11 +81,11 @@ def send(self, messages):
msg = self.__build_sms_data(m)
sms = etree.SubElement(xml_root, 'SMS')
for sms_element in msg:
element = etree.SubElement(sms,sms_element)
element = etree.SubElement(sms, sms_element)
element.text = msg[sms_element]

# print etree.tostring(xml_root)
response = clockwork_http.request(SMS_URL,etree.tostring(xml_root, encoding='utf-8'))
response = clockwork_http.request(SMS_URL, etree.tostring(xml_root, encoding='utf-8'))
response_data = response['data']

# print response_data
Expand All @@ -98,22 +99,22 @@ def send(self, messages):
# Return a consistent object
results = []
for sms in data_etree:
matching_sms = next((s for s in messages if str(s.wrapper_id) == sms.find('WrapperID').text),None)
matching_sms = next((s for s in messages if str(s.wrapper_id) == sms.find('WrapperID').text), None)
new_result = SMSResponse(
sms = matching_sms,
id = '' if sms.find('MessageID') is None else sms.find('MessageID').text,
error_code = 0 if sms.find('ErrNo') is None else sms.find('ErrNo').text,
error_message = '' if sms.find('ErrDesc') is None else sms.find('ErrDesc').text,
success = True if sms.find('ErrNo') is None else (sms.find('ErrNo').text == 0)
success = True if sms.find('ErrNo') is None else (sms.find('ErrNo').text == 0)
)
results.append(new_result)

if len(results) > 1:
return results
else:
return results[0]

def __init_xml(self,rootElementTag):
return results[0]

def __init_xml(self, rootElementTag):
"""Init a etree element and pop a key in there"""
xml_root = etree.Element(rootElementTag)
key = etree.SubElement(xml_root, "Key")
Expand All @@ -125,7 +126,7 @@ def __build_sms_data(self, message):
"""Build a dictionary of SMS message elements"""

attributes = {}

attributes_to_translate = {
'to' : 'To',
'message' : 'Content',
Expand All @@ -140,10 +141,10 @@ def __build_sms_data(self, message):
for attr in attributes_to_translate:
val_to_use = None
if hasattr(message, attr):
val_to_use = getattr(message,attr)
if val_to_use == None and hasattr(self,attr):
val_to_use = getattr(self,attr)
if val_to_use != None:
val_to_use = getattr(message, attr)
if val_to_use is None and hasattr(self, attr):
val_to_use = getattr(self, attr)
if val_to_use is not None:
attributes[attributes_to_translate[attr]] = str(val_to_use)

return attributes
4 changes: 4 additions & 0 deletions clockwork/clockwork_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,28 @@
class HttpException(Exception):
def __init__(self, value):
self.value = value

def __str__(self):
return repr(self.value)

class AuthException(Exception):
def __init__(self, value):
self.value = value

def __str__(self):
return repr(self.value)

class GenericException(Exception):
def __init__(self, value):
self.value = value

def __str__(self):
return repr(self.value)

class ApiException(Exception):
def __init__(self, value, errNum):
self.value = value
self.errNum = errNum

def __str__(self):
return repr(self.value)
1 change: 0 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
name='Clockwork',
version='1.1.0',
packages=['clockwork'],
install_requires=['lxml'],
license='MIT',
author='Mediaburst',
author_email='hello@clockworksms.com',
Expand Down
9 changes: 2 additions & 7 deletions tests/clockwork_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def test_should_send_multiple_messages_with_erros(self):
api = clockwork.API(self.api_key)
sms1 = clockwork.SMS(to="441234567890", message="This is a test message 1")
sms2 = clockwork.SMS(to="441234567890", message="")
response = api.send([sms1,sms2])
response = api.send([sms1, sms2])

self.assertTrue(response[0].success)
self.assertFalse(response[1].success)
Expand All @@ -77,12 +77,7 @@ def test_should_fail_with_invalid_key(self):
def test_should_be_able_to_get_balance(self):
api = clockwork.API(self.api_key)
balance = api.get_balance()
self.assertEqual('PAYG',balance['account_type'])
self.assertEqual('PAYG', balance['account_type'])

if __name__ == "__main__":
unittest.main()