Skip to content

Commit

Permalink
more documentation for usage and modules
Browse files Browse the repository at this point in the history
  • Loading branch information
jmichalicek committed Feb 22, 2017
1 parent 35ba74d commit 7733fe3
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 30 deletions.
38 changes: 38 additions & 0 deletions docs/jwt_apns_client.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
jwt_apns_client package
=======================

Submodules
----------

jwt_apns_client.cli module
--------------------------

.. automodule:: jwt_apns_client.cli
:members:
:undoc-members:
:show-inheritance:

jwt_apns_client.jwt_apns_client module
--------------------------------------

.. automodule:: jwt_apns_client.jwt_apns_client
:members:
:undoc-members:
:show-inheritance:

jwt_apns_client.utils module
----------------------------

.. automodule:: jwt_apns_client.utils
:members:
:undoc-members:
:show-inheritance:


Module contents
---------------

.. automodule:: jwt_apns_client
:members:
:undoc-members:
:show-inheritance:
7 changes: 7 additions & 0 deletions docs/modules.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
jwt_apns_client
===============

.. toctree::
:maxdepth: 4

jwt_apns_client
16 changes: 14 additions & 2 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,22 @@ Usage

To use JWT APNs Client in a project::

import jwt_apns_client
from jwt_apns_client.jwt_apns_client import APNSConnection, APNSEnvironments
client = APNSConnection(
topic='com.example.application',
team_id='apns_team_id',
apns_key_id='apns_key_id',
apns_key_path='/path/to/apns/key.pem',
environment=APNSEnvironments.DEV)

response = client.send_notification(
device_registration_id='registration_id',
alert='Example APNS Message',
badge=1
)

To create a dummy certificate suitable for use in test cases or could which does not interract with the APNs servers::

To create a dummy certificate suitable for use in test cases or which does not interract with the APNs servers::

1. generate elliptic curve key:
openssl ecparam -name secp256k1 -genkey -noout -out secp256k1-key.pem
Expand Down
112 changes: 85 additions & 27 deletions jwt_apns_client/jwt_apns_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@


class APNSEnvironments(object):
"""
Class to act as enum of APNs Environments
"""
PROD = 'prod'
DEV = 'dev'

Expand All @@ -28,6 +31,18 @@ class Alert(object):
"""
An APNs Alert. APNs Payloads can take a dict, which will be built from this object
or just a single string.
More information on the data may be found in Apple's documentation at
https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html
:ivar str title: The alert title
:ivar str body: The alert body
:ivar str title_loc_key: Localizable string for the title
:ivar [str] title_loc_args: Variable string values to appear in place for format specifiers in title_loc_key
:ivar str action_loc_key: String to get localized title for the View button in the app.
:ivar str loc_key: Key to an alert-message string in app's Localizable.strings.
:ivar [str] loc_args: Variable string values for format specifiers in loc_key
:ivar str launch_image: Filename of an image in the app bundle to be used as a launch image.
"""

def __init__(self, *args, **kwargs):
Expand All @@ -42,6 +57,10 @@ def __init__(self, *args, **kwargs):
super(Alert, self).__init__(*args, **kwargs)

def get_payload_dict(self):
"""
Returns the APNs payload data from the object instance as a dictionary suitable for encoding
as JSON for use in API requests.
"""
payload = {}
props = ['title', 'body', 'title_loc_key', 'title_loc_args', 'action_loc_key', 'loc_key', 'loc_args',
'launch_image']
Expand All @@ -54,21 +73,35 @@ def get_payload_dict(self):


class APNSConnection(object):

"""
Manages a connection to APNs
:ivar str algorithm: The algorithm to use for the jwt. Defaults to ES256.
:ivar str team_id: The app team id
:ivar str apns_key_id: The apns key id
:ivar str apns_key_path: Path to file with the apns auth key
:ivar int api_version: The API version. Default is 3
:ivar str topic: The APNs topic
:ivar str environment: development or production. Default is development.
:ivar str api_host: The host for the API. If not specified then defaults to the standard host for
the specified environment.
:ivar int api_port: The port to make the http2 connection on. Default is 443.
:ivar str provider_token: The base64 encoded jwt provider token
"""
def __init__(self, *args, **kwargs):
"""
params:
:param algorithm: (str) The algorithm to use for the jwt. Defaults to ES256.
:param team_id: (str) The app team id
:param apns_key_id: (str) The apns key id
:param apns_key_path: (str) Path to file with the apns auth key
:param api_version: (int) The API version. Default is 3
:param topic: (str) The APNs topic
:param environment: (str) development or production. Default is development.
:param api_host: (str) The host for the API. If not specified then defaults to the standard host for
:param str algorithm: The algorithm to use for the jwt. Defaults to ES256.
:param str team_id: The app team id
:param str apns_key_id: The apns key id
:param str apns_key_path: Path to file with the apns auth key
:param int api_version: The API version. Default is 3
:param str topic: The APNs topic
:param str environment: development or production. Default is development.
:param str api_host: The host for the API. If not specified then defaults to the standard host for
the specified environment.
:param api_port: (int) The port to make the http2 connection on. Default is 443.
:param provider_token: (str) The base64 encoded jwt provider token
:param int api_port: The port to make the http2 connection on. Default is 443.
:param str provider_token: The base64 encoded jwt provider token
"""
self.algorithm = kwargs.pop('algorithm', ALGORITHM)
self.topic = kwargs.pop('topic', None)
Expand Down Expand Up @@ -99,12 +132,16 @@ def get_payload_data(self, alert=None, badge=None, sound=None, content=None, cat
"""
Builds the payload dict.
More information about these values may be found in Apple's documentation at
https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html
:param alert: May be a `Alert` instance or a string
:param badge:
:param sound:
:param content:
:param category:
:param thread:
:param int badge: Include to modify the badge of the app's icon
:param str sound: The name of a sound in the app's bundle or Librar/Sounds folder.
:param int content: Set to 1 for a silent notification.
:param str category: String which represents the notification's type. This should correspond
with a value in the `identifier` property of one of the app's registered categories.
:param str thread: An app specific identifier for grouping notifications.
:returns: The payload as a dict ready for conversion to json in a request.
"""
Expand Down Expand Up @@ -161,12 +198,16 @@ def get_request_payload(self, alert=None, badge=None, sound=None, content=None,
"""
Returns the request payload as utf-8 encoded json
More information about these values may be found in Apple's documentation at
https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html
:param alert: May be a `Alert` instance or a string
:param badge:
:param sound:
:param content:
:param category:
:param thread:
:param int badge: Include to modify the badge of the app's icon
:param str sound: The name of a sound in the app's bundle or Librar/Sounds folder.
:param int content: Set to 1 for a silent notification.
:param str category: String which represents the notification's type. This should correspond
with a value in the `identifier` property of one of the app's registered categories.
:param str thread: An app specific identifier for grouping notifications.
:returns: The JSON encoded request payload
"""
data = self.get_payload_data(alert, badge, sound, content, category, thread)
Expand All @@ -179,6 +220,11 @@ def make_provider_token(self, issuer=None, issued_at=None, algorithm=None, secre
Apple returns an error if the provider token is updated too often, so we don't want to constantly build
new ones.
:param str issuer: JWT issuer. Generally the team id. Defaults to self.team_id
:param time.time issued_at: A time object specifying when the token was issued. Defaults to time.time()
:param str algorithm: The algorithm to use for the jwt. Defaults to ES256, which is required by the APNs.
:param str secret: The APNs key. If None then defaults to self.secret.
:param dict headers: The JWT token headers
:returns: JWT encoded token
"""
issuer = issuer or self.team_id
Expand All @@ -200,6 +246,9 @@ def get_token_headers(self, algorithm=None, apns_key_id=None):
"""
Build headers for the JWT token
:param str algorithm: The algorithm to use for the jwt. Defaults to ES256, which is required by the APNs.
:param str apns_key_id: The apns key id
:returns: Dict of headers for the JWT token
"""
algorithm = algorithm or self.algorithm
Expand All @@ -217,13 +266,14 @@ def send_notification(self, device_registration_id, **kwargs):
Send a push notification using http2. Creates a new connection or reuses an existing connection
if possible.
:param device_registration_id: The registration id of the device to send the notification to
:param str device_registration_id: The registration id of the device to send the notification to
:param alert: May be a `Alert` instance or a string
:param badge:
:param sound:
:param content:
:param category:
:param thread:
:param int badge: Include to modify the badge of the app's icon
:param str sound: The name of a sound in the app's bundle or Librar/Sounds folder.
:param int content: Set to 1 for a silent notification.
:param str category: String which represents the notification's type. This should correspond
with a value in the `identifier` property of one of the app's registered categories.
:param str thread: An app specific identifier for grouping notifications.
:returns: A :class:`jwt_apns_client.jwt_apns_client.NotificationResponse`
"""
# TODO: Should we accept ALL params which the various chain of methods accept too allow for full
Expand Down Expand Up @@ -267,6 +317,14 @@ def close(self, error_code=None):
class NotificationResponse(object):
"""
Encapsulate a response to sending a notification using the API.
:ivar int status: The HTTP status code of the response
:ivar str reason: Reason if specified
:ivar str payload: The JSON payload
:ivar dict headers: response headers
:ivar str host: Host the request was made to
:ivar int port: The port the request was made to
:ivar str path: Path of the HTTP request
"""

def __init__(self, status=200, reason='', host='', port=443, path='', payload=None, headers=None, *args, **kwargs):
Expand Down
2 changes: 1 addition & 1 deletion requirements_dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ watchdog==0.8.3
flake8==3.3.0
tox==2.6.0
coverage==4.3
Sphinx==1.4.8
Sphinx==1.5.2

0 comments on commit 7733fe3

Please sign in to comment.