diff --git a/pyapns.egg-info/PKG-INFO b/pyapns.egg-info/PKG-INFO index 8042c21..4e516f2 100644 --- a/pyapns.egg-info/PKG-INFO +++ b/pyapns.egg-info/PKG-INFO @@ -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 @@ -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 --------------------------- @@ -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 @@ -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 diff --git a/pyapns/_json.py b/pyapns/_json.py index 89c8cd6..fc5a9ac 100644 --- a/pyapns/_json.py +++ b/pyapns/_json.py @@ -18,4 +18,4 @@ 'python2.6 json and python-json') loads = json.loads -dumps = json.dumps \ No newline at end of file +dumps = json.dumps diff --git a/pyapns/server.py b/pyapns/server.py index 8a40c57..400caa3 100644 --- a/pyapns/server.py +++ b/pyapns/server.py @@ -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: @@ -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): diff --git a/setup.py b/setup.py index 6e7f4eb..52f5999 100755 --- a/setup.py +++ b/setup.py @@ -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: