Skip to content

Commit

Permalink
Merge branch 'master' of github.com:samuraisam/pyapns into ruby-client
Browse files Browse the repository at this point in the history
  • Loading branch information
Samuel Sutch committed Sep 3, 2010
2 parents ed069c5 + bf5f21e commit aedcb1f
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 123 deletions.
240 changes: 120 additions & 120 deletions pyapns.egg-info/PKG-INFO
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: pyapns
Version: 0.3.0
Version: 0.3.1
Summary: A universal Apple Push Notification Service (APNS) provider.
Home-page: http://github.com/samuraisam/pyapns/tree/master
Author: Samuel Sutch
Expand All @@ -10,32 +10,32 @@ Download-URL: http://github.com/samuraisam/pyapns/tree/master
Description:
Features:

* XML-RPC Based, works with any client in any language
* Native Python API with Django and Pylons support
* Scalable, fast and easy to distribute behind a proxy
* Based on Twisted
* Multi-application and dual environment support
* Simplified feedback interface
* XML-RPC Based, works with any client in any language
* Native Python API with Django and Pylons support
* Scalable, fast and easy to distribute behind a proxy
* Based on Twisted
* Multi-application and dual environment support
* Simplified feedback interface

pyapns is an APNS provider that you install on your server and access through XML-RPC.
To install you will need Python, Twisted_ and pyOpenSSL_. It's also recommended to
install `python-epoll`_ for best performance (if epoll is not available, like on
Mac OS X, you may want to use another library, like `py-kqueue`_. If you like
To install you will need Python, Twisted_ and pyOpenSSL_. It's also recommended to
install `python-epoll`_ for best performance (if epoll is not available, like on
Mac OS X, you may want to use another library, like `py-kqueue`_. If you like
easy_install try (it should take care of the dependancies for you)::

$ sudo easy_install pyapns
$ sudo easy_install pyapns

pyapns is a service that runs persistently on your machine. To start it::

$ twistd -r epoll web --class=pyapns.server.APNSServer --port=7077
$ twistd -r epoll web --class=pyapns.server.APNSServer --port=7077

To get started right away, use the included client::

$ python
>>> from pyapns import configure, provision, notify
>>> configure({'HOST': 'http://localhost:7077/'})
>>> provision('myapp', open('cert.pem').read(), 'sandbox')
>>> notify('myapp', 'hexlified_token_str', {'aps':{'alert': 'Hello!'}})
$ python
>>> from pyapns import configure, provision, notify
>>> configure({'HOST': 'http://localhost:7077/'})
>>> provision('myapp', open('cert.pem').read(), 'sandbox')
>>> notify('myapp', 'hexlified_token_str', {'aps':{'alert': 'Hello!'}})

The Multi-Application Model
---------------------------
Expand All @@ -47,33 +47,33 @@ Description:
for the fastest service possible. The application ID is an arbitrary
identifier and is not used in communication with the APNS servers.

When a connection can not be made within the specified `timeout` a timeout
error will be thrown by the server. This usually indicates that the wrong
When a connection can not be made within the specified `timeout` a timeout
error will be thrown by the server. This usually indicates that the wrong
[type of] certification file is being used, a blocked port or the wrong environment.

Sending Notifications
---------------------
Calling `notify` will send the message immediately if a connection is already
established. The first notification may be delayed a second while the server
connects. ``notify`` takes ``app_id``, ``token_or_token_list`` and
`notification_or_notification_list`. Multiple notifications can be batched
for better performance by using paired arrays of token/notifications. When
performing batched notifications, the token and notification arrays must be
established. The first notification may be delayed a second while the server
connects. ``notify`` takes ``app_id``, ``token_or_token_list`` and
`notification_or_notification_list`. Multiple notifications can be batched
for better performance by using paired arrays of token/notifications. When
performing batched notifications, the token and notification arrays must be
exactly the same length.

The full notification dictionary must be included as the notification::

{'aps': {
'sound': 'flynn.caf',
'badge': 0,
'message': 'Hello from pyapns :)'
}
} # etc...
{'aps': {
'sound': 'flynn.caf',
'badge': 0,
'message': 'Hello from pyapns :)'
}
} # etc...

Retrieving Inactive Tokens
--------------------------
Call `feedback` with the `app_id`. A list of tuples will be retrieved from the
APNS server that it deems inactive. These are returned as a list of 2-element
Call `feedback` with the `app_id`. A list of tuples will be retrieved from the
APNS server that it deems inactive. These are returned as a list of 2-element
lists with a `Datetime` object and the token string.

XML-RPC Methods
Expand All @@ -84,154 +84,154 @@ Description:

::

Arguments
app_id String the application id for the provided
certification
cert String a path to a .pem file or the a
string with the entie file
environment String the APNS server to use - either
'production' or 'sandbox'
timeout Integer timeout for connection attempts to
the APS servers
Returns
None
Arguments
app_id String the application id for the provided
certification
cert String a path to a .pem file or the a
string with the entie file
environment String the APNS server to use - either
'production' or 'sandbox'
timeout Integer timeout for connection attempts to
the APS servers
Returns
None

``notify``
----------

::

Arguments
app_id String the application id to send the
message to
tokens String or Array an Array of tokens or a single
token string
notifications String or Array an Array of notification
dictionaries or a single
notification dictionary
Arguments
app_id String the application id to send the
message to
tokens String or Array an Array of tokens or a single
token string
notifications String or Array an Array of notification
dictionaries or a single
notification dictionary

Returns
None
Returns
None

``feedback``
------------

::

Arguments
app_id String the application id to retrieve
retrieve feedback for
Arguments
app_id String the application id to retrieve
retrieve feedback for

Returns
Array(Array(Datetime(time_expired), String(token)), ...)
Returns
Array(Array(Datetime(time_expired), String(token)), ...)


The Python API
--------------
pyapns also provides a Python API that makes the use of pyapns even simpler.
pyapns also provides a Python API that makes the use of pyapns even simpler.
The Python API must be configured before use but configuration files make it easier.
The pyapns `client` module currently supports configuration from Django settings and
Pylons config. To configure using Django, the following must be present in
Pylons config. To configure using Django, the following must be present in
your settings file::

PYAPNS_CONFIG = {
'HOST': 'http://localhost:8077/',
'TIMEOUT': 15, # OPTIONAL, host timeout in seconds
'INITIAL': [ # OPTIONAL, see below
('craigsfish', '/home/samsutch/craigsfish/apscert.pem', 'sandbox'),
]
}
PYAPNS_CONFIG = {
'HOST': 'http://localhost:8077/',
'TIMEOUT': 15, # OPTIONAL, host timeout in seconds
'INITIAL': [ # OPTIONAL, see below
('craigsfish', '/home/samsutch/craigsfish/apscert.pem', 'sandbox'),
]
}

Optionally, with Django settings, you can skip manual provisioning by including a
list of `(name, path, environment)` tuples that are guaranteed to be provisioned
Optionally, with Django settings, you can skip manual provisioning by including a
list of `(name, path, environment)` tuples that are guaranteed to be provisioned
by the time you call `notify` or `feedback`.

Configuring for pylons is just as simple, but automatic provisioning isn't
Configuring for pylons is just as simple, but automatic provisioning isn't
possible, in your configuration file include::

pyapns_host = http://localhost:8077/
pyapns_timeout = 15
pyapns_host = http://localhost:8077/
pyapns_timeout = 15

For explanations of the configuration variables see the docs for
For explanations of the configuration variables see the docs for
`pyapns.client.configure`.

Each of these functions can be called synchronously and asynchronously. To make
Each of these functions can be called synchronously and asynchronously. To make
them perform asynchronously simply supply a callback. The request will then be
made in another thread and callback with the results. When calling asynchronously
made in another thread and callback with the results. When calling asynchronously
no value will be returned::

def got_feedback(tuples):
trim_inactive_tokens(tuples)
feedback('myapp', callback=got_feedback)
def got_feedback(tuples):
trim_inactive_tokens(tuples)
feedback('myapp', callback=got_feedback)

``pyapns.client.configure(opts)``
---------------------------------

::

Takes a dictionary of options and configures the client.
Currently configurable options are 'HOST', 'TIMEOUT' and 'INITIAL' the latter
of which is only read once.
Takes a dictionary of options and configures the client.
Currently configurable options are 'HOST', 'TIMEOUT' and 'INITIAL' the latter
of which is only read once.

Config Options:
HOST - A full host name with port, ending with a forward slash
TIMEOUT - An integer specifying how many seconds to timeout a
connection to the pyapns server (prevents deadlocking
the parent thread).
INITIAL - A List of tuples to be supplied to provision when
the first configuration happens.
Config Options:
HOST - A full host name with port, ending with a forward slash
TIMEOUT - An integer specifying how many seconds to timeout a
connection to the pyapns server (prevents deadlocking
the parent thread).
INITIAL - A List of tuples to be supplied to provision when
the first configuration happens.

``pyapns.client.provision(app_id, path_to_cert_or_cert, environment, timeout=15, callback=None)``
-------------------------------------------------------------------------------------------------

::

Provisions the app_id and initializes a connection to the APNS server.
Multiple calls to this function will be ignored by the pyapns daemon
but are still sent so pick a good place to provision your apps, optimally
once.

Arguments:
app_id the app_id to provision for APNS
path_to_cert_or_cert absolute path to the APNS SSL cert or a
string containing the .pem file
environment either 'sandbox' or 'production'
timeout number of seconds to timeout connection
attempts to the APPLE APS SERVER
callback a callback to be executed when done
Returns:
None
Provisions the app_id and initializes a connection to the APNS server.
Multiple calls to this function will be ignored by the pyapns daemon
but are still sent so pick a good place to provision your apps, optimally
once.

Arguments:
app_id the app_id to provision for APNS
path_to_cert_or_cert absolute path to the APNS SSL cert or a
string containing the .pem file
environment either 'sandbox' or 'production'
timeout number of seconds to timeout connection
attempts to the APPLE APS SERVER
callback a callback to be executed when done
Returns:
None

``pyapns.client.notify(app_id, tokens, notifications, callback=None)``
----------------------------------------------------------------------

::

Sends push notifications to the APNS server. Multiple
notifications can be sent by sending pairing the token/notification
arguments in lists [token1, token2], [notification1, notification2].
Sends push notifications to the APNS server. Multiple
notifications can be sent by sending pairing the token/notification
arguments in lists [token1, token2], [notification1, notification2].

Arguments:
app_id provisioned app_id to send to
tokens token to send the notification or a
list of tokens
notifications notification dicts or a list of notifications
callback a callback to be executed when done
Returns:
None
Arguments:
app_id provisioned app_id to send to
tokens token to send the notification or a
list of tokens
notifications notification dicts or a list of notifications
callback a callback to be executed when done
Returns:
None

``pyapns.client.feedback(app_id, callback=None)``
-------------------------------------------------

::

Retrieves a list of inactive tokens from the APNS server and the times
it thinks they went inactive.
Retrieves a list of inactive tokens from the APNS server and the times
it thinks they went inactive.

Arguments:
app_id the app_id to query
Returns:
Feedback tuples like [(datetime_expired, token_str), ...]
Arguments:
app_id the app_id to query
Returns:
Feedback tuples like [(datetime_expired, token_str), ...]

.. _Twisted: http://pypi.python.org/pypi/Twisted
.. _pyOpenSSL: http://pypi.python.org/pypi/pyOpenSSL
Expand Down
2 changes: 1 addition & 1 deletion pyapns/_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@
'python2.6 json and python-json')

loads = json.loads
dumps = json.dumps
dumps = json.dumps
3 changes: 2 additions & 1 deletion pyapns/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ class APNSServer(xmlrpc.XMLRPC):
def __init__(self):
self.allowNone = True
self.app_ids = app_ids
self.useDateTime = True

def apns_service(self, app_id):
if app_id not in app_ids:
Expand Down Expand Up @@ -324,7 +325,7 @@ def encode_notifications(tokens, notifications):
if type(notifications) is dict and type(tokens) in (str, unicode):
tokens, notifications = ([tokens], [notifications])
if type(notifications) is list and type(tokens) is list:
return ''.join(map(lambda y: structify(*y), ((binaryify(t), json.dumps(p))
return ''.join(map(lambda y: structify(*y), ((binaryify(t), json.dumps(p, separators=(',',':')))
for t, p in zip(tokens, notifications))))

def decode_feedback(binary_tuples):
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

setup(
name="pyapns",
version="0.3.0",
version="0.3.1",
description="A universal Apple Push Notification Service (APNS) provider.",
long_description="""
Features:
Expand Down

0 comments on commit aedcb1f

Please sign in to comment.