diff options
| author | Devendra | 2014-06-18 01:02:15 +0530 |
|---|---|---|
| committer | Devendra | 2014-06-18 01:02:15 +0530 |
| commit | a1ee7f8bd90b463318bfa75f7ee4f58d458d2a24 (patch) | |
| tree | 9e260902f960f792a93fa25e3b619c42ecb5f4d4 | |
| parent | bfd5c64bdf7ed45f21207cb53c653e7220e39eff (diff) | |
| parent | 083127cde127dd78fc88ffe2b3b82144b2c07038 (diff) | |
| download | pubnub-python-a1ee7f8bd90b463318bfa75f7ee4f58d458d2a24.tar.bz2 | |
Merge branch 'master' into develop
87 files changed, 7735 insertions, 4777 deletions
diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..cf87ccd --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,4 @@ +3.5.0 - 6-16-14 +New version! Complete re-write! +. Async subscribe allows for MX, unsubscribe calls +. New method signatures -- be sure to check migration doc if upgrading diff --git a/Makefile b/Makefile deleted file mode 100644 index b82c77b..0000000 --- a/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -SUBDIRS = common python python-twisted python-tornado - -.PHONY: all test -all test: $(SUBDIRS) - -all: TARG=all -test: TARG=test - -$(SUBDIRS): force - @ $(MAKE) -C $@ $(TARG) - -.PHONY: clean -clean: - for dir in $(SUBDIRS); do \ - $(MAKE) clean -C $$dir; \ - done - -.PHONY: force -force :; diff --git a/Makefile.inc b/Makefile.inc deleted file mode 100644 index 68a78c6..0000000 --- a/Makefile.inc +++ /dev/null @@ -1,3 +0,0 @@ -REPOS_DIR=.. -VERSION=$(shell cat $(REPOS_DIR)/VERSION) -ECHO=/bin/echo diff --git a/Pubnub.py b/Pubnub.py new file mode 100644 index 0000000..e39dd06 --- /dev/null +++ b/Pubnub.py @@ -0,0 +1,1622 @@ + +## www.pubnub.com - PubNub Real-time push service in the cloud. +# coding=utf8 + +## PubNub Real-time Push APIs and Notifications Framework +## Copyright (c) 2014-15 Stephen Blum +## http://www.pubnub.com/ + +## ----------------------------------- +## PubNub 3.5.0 Real-time Push Cloud API +## ----------------------------------- + + +try: + import json +except ImportError: + import simplejson as json + +import time +import hashlib +import uuid +import sys +from base64 import urlsafe_b64encode +from base64 import encodestring, decodestring +import hmac +from Crypto.Cipher import AES +from Crypto.Hash import MD5 + + +try: + from hashlib import sha256 + digestmod = sha256 +except ImportError: + import Crypto.Hash.SHA256 as digestmod + sha256 = digestmod.new + + +##### vanilla python imports ##### +try: + from urllib.parse import quote +except ImportError: + from urllib2 import quote +try: + import urllib.request +except ImportError: + import urllib2 + +try: + import requests + from requests.adapters import HTTPAdapter +except ImportError: + pass + +import threading +from threading import current_thread + + +################################## + + +##### Tornado imports and globals ##### +try: + import tornado.httpclient + import tornado.ioloop + from tornado.stack_context import ExceptionStackContext + ioloop = tornado.ioloop.IOLoop.instance() +except ImportError: + pass + +####################################### + + +##### Twisted imports and globals ##### +try: + from twisted.web.client import getPage + from twisted.internet import reactor + from twisted.internet.defer import Deferred + from twisted.internet.protocol import Protocol + from twisted.web.client import Agent, ContentDecoderAgent + from twisted.web.client import RedirectAgent, GzipDecoder + from twisted.web.client import HTTPConnectionPool + from twisted.web.http_headers import Headers + from twisted.internet.ssl import ClientContextFactory + from twisted.internet.task import LoopingCall + import twisted + + from twisted.python.compat import ( + _PY3, unicode, intToBytes, networkString, nativeString) + + pnconn_pool = HTTPConnectionPool(reactor, persistent=True) + pnconn_pool.maxPersistentPerHost = 100000 + pnconn_pool.cachedConnectionTimeout = 15 + pnconn_pool.retryAutomatically = True + + class WebClientContextFactory(ClientContextFactory): + def getContext(self, hostname, port): + return ClientContextFactory.getContext(self) + + class PubNubPamResponse(Protocol): + def __init__(self, finished): + self.finished = finished + + def dataReceived(self, bytes): + self.finished.callback(bytes) + + class PubNubResponse(Protocol): + def __init__(self, finished): + self.finished = finished + + def dataReceived(self, bytes): + self.finished.callback(bytes) +except ImportError: + pass + + +####################################### + + +def get_data_for_user(data): + try: + if 'message' in data and 'payload' in data: + return {'message': data['message'], 'payload': data['payload']} + else: + return data + except TypeError: + return data + + +class PubnubCrypto2(): + + def pad(self, msg, block_size=16): + + padding = block_size - (len(msg) % block_size) + return msg + chr(padding) * padding + + def depad(self, msg): + + return msg[0:-ord(msg[-1])] + + def getSecret(self, key): + + return hashlib.sha256(key).hexdigest() + + def encrypt(self, key, msg): + secret = self.getSecret(key) + Initial16bytes = '0123456789012345' + cipher = AES.new(secret[0:32], AES.MODE_CBC, Initial16bytes) + enc = encodestring(cipher.encrypt(self.pad(msg))) + return enc + + def decrypt(self, key, msg): + + secret = self.getSecret(key) + Initial16bytes = '0123456789012345' + cipher = AES.new(secret[0:32], AES.MODE_CBC, Initial16bytes) + plain = self.depad(cipher.decrypt(decodestring(msg))) + try: + return eval(plain) + except SyntaxError: + return plain + +class PubnubCrypto3(): + + def pad(self, msg, block_size=16): + + padding = block_size - (len(msg) % block_size) + return msg + (chr(padding) * padding).encode('utf-8') + + def depad(self, msg): + + return msg[0:-ord(msg[-1])] + + def getSecret(self, key): + + return hashlib.sha256(key.encode("utf-8")).hexdigest() + + def encrypt(self, key, msg): + + secret = self.getSecret(key) + Initial16bytes = '0123456789012345' + cipher = AES.new(secret[0:32], AES.MODE_CBC, Initial16bytes) + return encodestring( + cipher.encrypt(self.pad(msg.encode('utf-8')))).decode('utf-8') + + def decrypt(self, key, msg): + + secret = self.getSecret(key) + Initial16bytes = '0123456789012345' + cipher = AES.new(secret[0:32], AES.MODE_CBC, Initial16bytes) + return (cipher.decrypt( + decodestring(msg.encode('utf-8')))).decode('utf-8') + + +class PubnubBase(object): + def __init__( + self, + publish_key, + subscribe_key, + secret_key=False, + cipher_key=False, + auth_key=None, + ssl_on=False, + origin='pubsub.pubnub.com', + UUID=None + ): + """Pubnub Class + + Provides methods to communicate with Pubnub cloud + + Attributes: + publish_key: Publish Key + subscribe_key: Subscribe Key + secret_key: Secret Key + cipher_key: Cipher Key + auth_key: Auth Key (used with Pubnub Access Manager i.e. PAM) + ssl: SSL enabled ? + origin: Origin + """ + + self.origin = origin + self.version = '3.5.0' + self.limit = 1800 + self.publish_key = publish_key + self.subscribe_key = subscribe_key + self.secret_key = secret_key + self.cipher_key = cipher_key + self.ssl = ssl_on + self.auth_key = auth_key + + if self.ssl: + self.origin = 'https://' + self.origin + else: + self.origin = 'http://' + self.origin + + self.uuid = UUID or str(uuid.uuid4()) + + if type(sys.version_info) is tuple: + self.python_version = 2 + self.pc = PubnubCrypto2() + else: + if sys.version_info.major == 2: + self.python_version = 2 + self.pc = PubnubCrypto2() + else: + self.python_version = 3 + self.pc = PubnubCrypto3() + + if not isinstance(self.uuid, str): + raise AttributeError("pres_uuid must be a string") + + def _pam_sign(self, msg): + + return urlsafe_b64encode(hmac.new( + self.secret_key.encode("utf-8"), + msg.encode("utf-8"), + sha256 + ).digest()) + + def _pam_auth(self, query, apicode=0, callback=None, error=None): + + if 'timestamp' not in query: + query['timestamp'] = int(time.time()) + + ## Global Grant? + if 'auth' in query and not query['auth']: + del query['auth'] + + if 'channel' in query and not query['channel']: + del query['channel'] + + params = "&".join([ + x + "=" + quote( + str(query[x]), safe="" + ) for x in sorted(query) + ]) + sign_input = "{subkey}\n{pubkey}\n{apitype}\n{params}".format( + subkey=self.subscribe_key, + pubkey=self.publish_key, + apitype="audit" if (apicode) else "grant", + params=params + ) + query['signature'] = self._pam_sign(sign_input) + + return self._request({"urlcomponents": [ + 'v1', 'auth', "audit" if (apicode) else "grant", + 'sub-key', + self.subscribe_key + ], 'urlparams': query}, + self._return_wrapped_callback(callback), + self._return_wrapped_callback(error)) + + def get_origin(self): + return self.origin + + def set_auth_key(self, auth_key): + self.auth_key = auth_key + + def get_auth_key(self): + return auth_key + + def grant(self, channel=None, auth_key=False, read=True, + write=True, ttl=5, callback=None, error=None): + """Method for granting permissions. + + This function establishes subscribe and/or write permissions for + PubNub Access Manager (PAM) by setting the read or write attribute + to true. A grant with read or write set to false (or not included) + will revoke any previous grants with read or write set to true. + + Permissions can be applied to any one of three levels: + 1. Application level privileges are based on subscribe_key applying to all associated channels. + 2. Channel level privileges are based on a combination of subscribe_key and channel name. + 3. User level privileges are based on the combination of subscribe_key, channel and auth_key. + + Args: + channel: (string) (optional) + Specifies channel name to grant permissions to. + If channel is not specified, the grant applies to all + channels associated with the subscribe_key. If auth_key + is not specified, it is possible to grant permissions to + multiple channels simultaneously by specifying the channels + as a comma separated list. + + auth_key: (string) (optional) + Specifies auth_key to grant permissions to. + It is possible to specify multiple auth_keys as comma + separated list in combination with a single channel name. + If auth_key is provided as the special-case value "null" + (or included in a comma-separated list, eg. "null,null,abc"), + a new auth_key will be generated and returned for each "null" value. + + read: (boolean) (default: True) + Read permissions are granted by setting to True. + Read permissions are removed by setting to False. + + write: (boolean) (default: True) + Write permissions are granted by setting to true. + Write permissions are removed by setting to false. + + ttl: (int) (default: 1440 i.e 24 hrs) + Time in minutes for which granted permissions are valid. + Max is 525600 , Min is 1. + Setting ttl to 0 will apply the grant indefinitely. + + callback: (function) (optional) + A callback method can be passed to the method. + If set, the api works in async mode. + Required argument when working with twisted or tornado + + error: (function) (optional) + An error method can be passed to the method. + If set, the api works in async mode. + Required argument when working with twisted or tornado . + + Returns: + Returns a dict in sync mode i.e. when callback argument is not given + The dict returned contains values with keys 'message' and 'payload' + + Sample Response: + { + "message":"Success", + "payload":{ + "ttl":5, + "auths":{ + "my_ro_authkey":{"r":1,"w":0} + }, + "subscribe_key":"my_subkey", + "level":"user", + "channel":"my_channel" + } + } + """ + + return self._pam_auth({ + "channel": channel, + "auth": auth_key, + "r": read and 1 or 0, + "w": write and 1 or 0, + "ttl": ttl + }, callback=callback, error=error) + + def revoke(self, channel=None, auth_key=None, ttl=1, callback=None, error=None): + """Method for revoking permissions. + + Args: + channel: (string) (optional) + Specifies channel name to revoke permissions to. + If channel is not specified, the revoke applies to all + channels associated with the subscribe_key. If auth_key + is not specified, it is possible to grant permissions to + multiple channels simultaneously by specifying the channels + as a comma separated list. + + auth_key: (string) (optional) + Specifies auth_key to revoke permissions to. + It is possible to specify multiple auth_keys as comma + separated list in combination with a single channel name. + If auth_key is provided as the special-case value "null" + (or included in a comma-separated list, eg. "null,null,abc"), + a new auth_key will be generated and returned for each "null" value. + + ttl: (int) (default: 1440 i.e 24 hrs) + Time in minutes for which granted permissions are valid. + Max is 525600 , Min is 1. + Setting ttl to 0 will apply the grant indefinitely. + + callback: (function) (optional) + A callback method can be passed to the method. + If set, the api works in async mode. + Required argument when working with twisted or tornado + + error: (function) (optional) + An error method can be passed to the method. + If set, the api works in async mode. + Required argument when working with twisted or tornado . + + Returns: + Returns a dict in sync mode i.e. when callback argument is not given + The dict returned contains values with keys 'message' and 'payload' + + Sample Response: + { + "message":"Success", + "payload":{ + "ttl":5, + "auths":{ + "my_authkey":{"r":0,"w":0} + }, + "subscribe_key":"my_subkey", + "level":"user", + "channel":"my_channel" + } + } + + """ + + return self._pam_auth({ + "channel": channel, + "auth": auth_key, + "r": 0, + "w": 0, + "ttl": ttl + }, callback=callback, error=error) + + def audit(self, channel=None, auth_key=None, callback=None, error=None): + """Method for fetching permissions from pubnub servers. + + This method provides a mechanism to reveal existing PubNub Access Manager attributes + for any combination of subscribe_key, channel and auth_key. + + Args: + channel: (string) (optional) + Specifies channel name to return PAM + attributes optionally in combination with auth_key. + If channel is not specified, results for all channels + associated with subscribe_key are returned. + If auth_key is not specified, it is possible to return + results for a comma separated list of channels. + + auth_key: (string) (optional) + Specifies the auth_key to return PAM attributes for. + If only a single channel is specified, it is possible to return + results for a comma separated list of auth_keys. + + callback: (function) (optional) + A callback method can be passed to the method. + If set, the api works in async mode. + Required argument when working with twisted or tornado + + error: (function) (optional) + An error method can be passed to the method. + If set, the api works in async mode. + Required argument when working with twisted or tornado . + + Returns: + Returns a dict in sync mode i.e. when callback argument is not given + The dict returned contains values with keys 'message' and 'payload' + + Sample Response + { + "message":"Success", + "payload":{ + "channels":{ + "my_channel":{ + "auths":{"my_ro_authkey":{"r":1,"w":0}, + "my_rw_authkey":{"r":0,"w":1}, + "my_admin_authkey":{"r":1,"w":1} + } + } + }, + } + + Usage: + + pubnub.audit ('my_channel'); # Sync Mode + + """ + + return self._pam_auth({ + "channel": channel, + "auth": auth_key + }, 1, callback=callback, error=error) + + def encrypt(self, message): + """Method for encrypting data. + + This method takes plaintext as input and returns encrypted data. + This need not be called directly as enncryption/decryption is + taken care of transparently by Pubnub class if cipher key is + provided at time of initializing pubnub object + + Args: + message: Message to be encrypted. + + Returns: + Returns encrypted message if cipher key is set + """ + if self.cipher_key: + message = json.dumps(self.pc.encrypt( + self.cipher_key, json.dumps(message)).replace('\n', '')) + else: + message = json.dumps(message) + + return message + + def decrypt(self, message): + """Method for decrypting data. + + This method takes ciphertext as input and returns decrypted data. + This need not be called directly as enncryption/decryption is + taken care of transparently by Pubnub class if cipher key is + provided at time of initializing pubnub object + + Args: + message: Message to be decrypted. + + Returns: + Returns decrypted message if cipher key is set + """ + if self.cipher_key: + message = self.pc.decrypt(self.cipher_key, message) + + return message + + def _return_wrapped_callback(self, callback=None): + def _new_format_callback(response): + if 'payload' in response: + if (callback is not None): + callback({'message': response['message'], + 'payload': response['payload']}) + else: + if (callback is not None): + callback(response) + if (callback is not None): + return _new_format_callback + else: + return None + + def publish(self, channel, message, callback=None, error=None): + """Publishes data on a channel. + + The publish() method is used to send a message to all subscribers of a channel. + To publish a message you must first specify a valid publish_key at initialization. + A successfully published message is replicated across the PubNub Real-Time Network + and sent simultaneously to all subscribed clients on a channel. + Messages in transit can be secured from potential eavesdroppers with SSL/TLS by + setting ssl to True during initialization. + + Published messages can also be encrypted with AES-256 simply by specifying a cipher_key + during initialization. + + Args: + channel: (string) + Specifies channel name to publish messages to. + message: (string/int/double/dict/list) + Message to be published + callback: (optional) + A callback method can be passed to the method. + If set, the api works in async mode. + Required argument when working with twisted or tornado + error: (optional) + An error method can be passed to the method. + If set, the api works in async mode. + Required argument when working with twisted or tornado + + Returns: + Sync Mode : list + Async Mode : None + + The function returns the following formatted response: + + [ Number, "Status", "Time Token"] + + The output below demonstrates the response to a successful call: + + [1,"Sent","13769558699541401"] + + """ + + message = self.encrypt(message) + + ## Send Message + return self._request({"urlcomponents": [ + 'publish', + self.publish_key, + self.subscribe_key, + '0', + channel, + '0', + message + ], 'urlparams': {'auth': self.auth_key}}, + callback=self._return_wrapped_callback(callback), + error=self._return_wrapped_callback(error)) + + def presence(self, channel, callback, error=None): + """Subscribe to presence data on a channel. + + Only works in async mode + + Args: + channel: Channel name ( string ) on which to publish message + callback: A callback method should be passed to the method. + If set, the api works in async mode. + Required argument when working with twisted or tornado . + error: Optional variable. An error method can be passed to the method. + If set, the api works in async mode. + Required argument when working with twisted or tornado . + + Returns: + None + """ + return self.subscribe({ + 'channel': channel + '-pnpres', + 'subscribe_key': self.subscribe_key, + 'callback': self._return_wrapped_callback(callback)}) + + def here_now(self, channel, callback=None, error=None): + """Get here now data. + + You can obtain information about the current state of a channel including + a list of unique user-ids currently subscribed to the channel and the total + occupancy count of the channel by calling the here_now() function in your + application. + + + Args: + channel: (string) (optional) + Specifies the channel name to return occupancy results. + If channel is not provided, here_now will return data for all channels. + + callback: (optional) + A callback method should be passed to the method. + If set, the api works in async mode. + Required argument when working with twisted or tornado . + + error: (optional) + Optional variable. An error method can be passed to the method. + If set, the api works in async mode. + Required argument when working with twisted or tornado . + + Returns: + Sync Mode: list + Async Mode: None + + Response Format: + + The here_now() method returns a list of uuid s currently subscribed to the channel. + + uuids:["String","String", ... ,"String"] - List of UUIDs currently subscribed to the channel. + + occupancy: Number - Total current occupancy of the channel. + + Example Response: + { + occupancy: 4, + uuids: [ + '123123234t234f34fq3dq', + '143r34f34t34fq34q34q3', + '23f34d3f4rq34r34rq23q', + 'w34tcw45t45tcw435tww3', + ] + } + """ + + ## Get Presence Here Now + return self._request({"urlcomponents": [ + 'v2', 'presence', + 'sub_key', self.subscribe_key, + 'channel', channel + ], 'urlparams': {'auth': self.auth_key}}, + callback=self._return_wrapped_callback(callback), + error=self._return_wrapped_callback(error)) + + + def history(self, channel, count=100, reverse=False, + start=None, end=None, callback=None, error=None): + """This method fetches historical messages of a channel. + + PubNub Storage/Playback Service provides real-time access to an unlimited + history for all messages published to PubNub. Stored messages are replicated + across multiple availability zones in several geographical data center + locations. Stored messages can be encrypted with AES-256 message encryption + ensuring that they are not readable while stored on PubNub's network. + + It is possible to control how messages are returned and in what order, + for example you can: + + Return messages in the order newest to oldest (default behavior). + + Return messages in the order oldest to newest by setting reverse to true. + + Page through results by providing a start or end time token. + + Retrieve a "slice" of the time line by providing both a start and end time token. + + Limit the number of messages to a specific quantity using the count parameter. + + + + Args: + channel: (string) + Specifies channel to return history messages from + + count: (int) (default: 100) + Specifies the number of historical messages to return + + callback: (optional) + A callback method should be passed to the method. + If set, the api works in async mode. + Required argument when working with twisted or tornado . + + error: (optional) + An error method can be passed to the method. + If set, the api works in async mode. + Required argument when working with twisted or tornado . + + Returns: + Returns a list in sync mode i.e. when callback argument is not given + + Sample Response: + [["Pub1","Pub2","Pub3","Pub4","Pub5"],13406746729185766,13406746845892666] + """ + + params = dict() + + params['count'] = count + params['reverse'] = reverse + params['start'] = start + params['end'] = end + params['auth_key'] = self.auth_key + + ## Get History + return self._request({'urlcomponents': [ + 'v2', + 'history', + 'sub-key', + self.subscribe_key, + 'channel', + channel, + ], 'urlparams': params}, + callback=self._return_wrapped_callback(callback), + error=self._return_wrapped_callback(error)) + + def time(self, callback=None): + """This function will return a 17 digit precision Unix epoch. + + Args: + + callback: (optional) + A callback method should be passed to the method. + If set, the api works in async mode. + Required argument when working with twisted or tornado . + + Returns: + Returns a 17 digit number in sync mode i.e. when callback argument is not given + + Sample: + 13769501243685161 + """ + + time = self._request({'urlcomponents': [ + 'time', + '0' + ]}, callback) + if time is not None: + return time[0] + + def _encode(self, request): + return [ + "".join([' ~`!@#$%^&*()+=[]\\{}|;\':",./<>?'.find(ch) > -1 and + hex(ord(ch)).replace('0x', '%').upper() or + ch for ch in list(bit) + ]) for bit in request] + + def getUrl(self, request): + ## Build URL + url = self.origin + '/' + "/".join([ + "".join([' ~`!@#$%^&*()+=[]\\{}|;\':",./<>?'.find(ch) > -1 and + hex(ord(ch)).replace('0x', '%').upper() or + ch for ch in list(bit) + ]) for bit in request["urlcomponents"]]) + if ("urlparams" in request): + url = url + '?' + "&".join([x + "=" + str(y) for x, y in request[ + "urlparams"].items() if y is not None]) + return url + + +class EmptyLock(): + def __enter__(self): + pass + + def __exit__(self, a, b, c): + pass + +empty_lock = EmptyLock() + + +class PubnubCoreAsync(PubnubBase): + + def start(self): + pass + + def stop(self): + pass + + def __init__( + self, + publish_key, + subscribe_key, + secret_key=None, + cipher_key=None, + auth_key=None, + ssl_on=False, + origin='pubsub.pubnub.com', + uuid=None, + _tt_lock=empty_lock, + _channel_list_lock=empty_lock + ): + + super(PubnubCoreAsync, self).__init__( + publish_key=publish_key, + subscribe_key=subscribe_key, + secret_key=secret_key, + cipher_key=cipher_key, + auth_key=auth_key, + ssl_on=ssl_on, + origin=origin, + UUID=uuid + ) + + self.subscriptions = {} + self.timetoken = 0 + self.last_timetoken = 0 + self.accept_encoding = 'gzip' + self.SUB_RECEIVER = None + self._connect = None + self._tt_lock = _tt_lock + self._channel_list_lock = _channel_list_lock + self._connect = lambda: None + + def get_channel_list(self, channels): + channel = '' + first = True + with self._channel_list_lock: + for ch in channels: + if not channels[ch]['subscribed']: + continue + if not first: + channel += ',' + else: + first = False + channel += ch + return channel + + def get_channel_array(self): + """Get List of currently subscribed channels + + Returns: + Returns a list containing names of channels subscribed + + Sample return value: + ["a","b","c] + """ + channels = self.subscriptions + channel = [] + with self._channel_list_lock: + for ch in channels: + if not channels[ch]['subscribed']: + continue + channel.append(ch) + return channel + + def each(l, func): + if func is None: + return + for i in l: + func(i) + + def subscribe(self, channels, callback, error=None, + connect=None, disconnect=None, reconnect=None, sync=False): + """Subscribe to data on a channel. + + This function causes the client to create an open TCP socket to the + PubNub Real-Time Network and begin listening for messages on a specified channel. + To subscribe to a channel the client must send the appropriate subscribe_key at + initialization. + + Only works in async mode + + Args: + channel: (string/list) + Specifies the channel to subscribe to. It is possible to specify + multiple channels as a comma separated list or andarray. + + callback: (function) + This callback is called on receiving a message from the channel. + + error: (function) (optional) + This callback is called on an error event + + connect: (function) (optional) + This callback is called on a successful connection to the PubNub cloud + + disconnect: (function) (optional) + This callback is called on client disconnect from the PubNub cloud + + reconnect: (function) (optional) + This callback is called on successfully re-connecting to the PubNub cloud + + Returns: + None + """ + + with self._tt_lock: + self.last_timetoken = self.timetoken if self.timetoken != 0 \ + else self.last_timetoken + self.timetoken = 0 + + if sync is True and self.susbcribe_sync is not None: + self.susbcribe_sync(args) + return + + def _invoke(func, msg=None, channel=None): + if func is not None: + if msg is not None and channel is not None: + func(get_data_for_user(msg), channel) + elif msg is not None: + func(get_data_for_user(msg)) + else: + func() + + def _invoke_connect(): + if self._channel_list_lock: + with self._channel_list_lock: + for ch in self.subscriptions: + chobj = self.subscriptions[ch] + if chobj['connected'] is False: + chobj['connected'] = True + chobj['disconnected'] = False + _invoke(chobj['connect'], chobj['name']) + else: + if chobj['disconnected'] is True: + chobj['disconnected'] = False + _invoke(chobj['reconnect'], chobj['name']) + + def _invoke_disconnect(): + if self._channel_list_lock: + with self._channel_list_lock: + for ch in self.subscriptions: + chobj = self.subscriptions[ch] + if chobj['connected'] is True: + if chobj['disconnected'] is False: + chobj['disconnected'] = True + _invoke(chobj['disconnect'], chobj['name']) + + def _invoke_error(channel_list=None, err=None): + if channel_list is None: + for ch in self.subscriptions: + chobj = self.subscriptions[ch] + _invoke(chobj['error'], err) + else: + for ch in channel_list: + chobj = self.subscriptions[ch] + _invoke(chobj['error'], err) + + def _get_channel(): + for ch in self.subscriptions: + chobj = self.subscriptions[ch] + if chobj['subscribed'] is True: + return chobj + channels = channels if isinstance( + channels, list) else channels.split(",") + for channel in channels: + ## New Channel? + if len(channel) > 0 and \ + (not channel in self.subscriptions or + self.subscriptions[channel]['subscribed'] is False): + with self._channel_list_lock: + self.subscriptions[channel] = { + 'name': channel, + 'first': False, + 'connected': False, + 'disconnected': True, + 'subscribed': True, + 'callback': callback, + 'connect': connect, + 'disconnect': disconnect, + 'reconnect': reconnect, + 'error': error + } + ''' + ## return if already connected to channel + if channel in self.subscriptions and \ + 'connected' in self.subscriptions[channel] and \ + self.subscriptions[channel]['connected'] is True: + _invoke(error, "Already Connected") + return + ''' + ## SUBSCRIPTION RECURSION + def _connect(): + + self._reset_offline() + + def error_callback(response): + ## ERROR ? + if not response or \ + ('message' in response and + response['message'] == 'Forbidden'): + _invoke_error(response['payload'][ + 'channels'], response['message']) + self.timeout(1, _connect) + return + if 'message' in response: + _invoke_error(err=response['message']) + else: + _invoke_disconnect() + self.timetoken = 0 + self.timeout(1, _connect) + + def sub_callback(response): + ## ERROR ? + if not response or \ + ('message' in response and + response['message'] == 'Forbidden'): + _invoke_error(response['payload'][ + 'channels'], response['message']) + _connect() + return + + _invoke_connect() + + with self._tt_lock: + self.timetoken = \ + self.last_timetoken if self.timetoken == 0 and \ + self.last_timetoken != 0 else response[1] + if len(response) > 2: + channel_list = response[2].split(',') + response_list = response[0] + for ch in enumerate(channel_list): + if ch[1] in self.subscriptions: + chobj = self.subscriptions[ch[1]] + _invoke(chobj['callback'], + self.decrypt(response_list[ch[0]]), + chobj['name']) + else: + response_list = response[0] + chobj = _get_channel() + for r in response_list: + if chobj: + _invoke(chobj['callback'], self.decrypt(r), + chobj['name']) + + _connect() + + channel_list = self.get_channel_list(self.subscriptions) + if len(channel_list) <= 0: + return + + ## CONNECT TO PUBNUB SUBSCRIBE SERVERS + #try: + self.SUB_RECEIVER = self._request({"urlcomponents": [ + 'subscribe', + self.subscribe_key, + channel_list, + '0', + str(self.timetoken) + ], "urlparams": {"uuid": self.uuid, "auth": self.auth_key}}, + sub_callback, + error_callback, + single=True, timeout=320) + ''' + except Exception as e: + print(e) + self.timeout(1, _connect) + return + ''' + + self._connect = _connect + + ## BEGIN SUBSCRIPTION (LISTEN FOR MESSAGES) + _connect() + + def _reset_offline(self): + if self.SUB_RECEIVER is not None: + self.SUB_RECEIVER() + self.SUB_RECEIVER = None + + def CONNECT(self): + self._reset_offline() + self._connect() + + def unsubscribe(self, channel): + """Subscribe to presence data on a channel. + Only works in async mode + + Args: + channel: Channel name ( string ) on which to publish message + message: Message to be published ( String / int / double / dict / list ). + callback: A callback method should be passed to the method. + If set, the api works in async mode. + Required argument when working with twisted or tornado . + error: Optional variable. An error method can be passed to the method. + If set, the api works in async mode. + Required argument when working with twisted or tornado . + + Returns: + Returns a list in sync mode i.e. when callback argument is not given + """ + if channel in self.subscriptions is False: + return False + + ## DISCONNECT + with self._channel_list_lock: + if channel in self.subscriptions: + self.subscriptions[channel]['connected'] = 0 + self.subscriptions[channel]['subscribed'] = False + self.subscriptions[channel]['timetoken'] = 0 + self.subscriptions[channel]['first'] = False + self.CONNECT() + + +class PubnubCore(PubnubCoreAsync): + def __init__( + self, + publish_key, + subscribe_key, + secret_key=None, + cipher_key=None, + auth_key=None, + ssl_on=False, + origin='pubsub.pubnub.com', + uuid=None + ): + super(PubnubCore, self).__init__( + publish_key=publish_key, + subscribe_key=subscribe_key, + secret_key=secret_key, + cipher_key=cipher_key, + auth_key=auth_key, + ssl_on=ssl_on, + origin=origin, + UUID=uuid + ) + + self.subscriptions = {} + self.timetoken = 0 + self.accept_encoding = 'gzip' + + def subscribe_sync(self, channel, callback, timetoken=0): + """ + #** + #* Subscribe + #* + #* This is BLOCKING. + #* Listen for a message on a channel. + #* + #* @param array args with channel and callback. + #* @return false on fail, array on success. + #** + + ## Subscribe Example + def receive(message) : + print(message) + return True + + pubnub.subscribe({ + 'channel' : 'hello_world', + 'callback' : receive + }) + + """ + + subscribe_key = self.subscribe_key + + ## Begin Subscribe + while True: + + try: + ## Wait for Message + response = self._request({"urlcomponents": [ + 'subscribe', + subscribe_key, + channel, + '0', + str(timetoken) + ], "urlparams": {"uuid": self.uuid}}) + + messages = response[0] + timetoken = response[1] + + ## If it was a timeout + if not len(messages): + continue + + ## Run user Callback and Reconnect if user permits. + for message in messages: + if not callback(self.decrypt(message)): + return + + except Exception: + time.sleep(1) + + return True + + +class HTTPClient: + def __init__(self, pubnub, url, urllib_func=None, + callback=None, error=None, id=None, timeout=5): + self.url = url + self.id = id + self.callback = callback + self.error = error + self.stop = False + self._urllib_func = urllib_func + self.timeout = timeout + self.pubnub = pubnub + + def cancel(self): + self.stop = True + self.callback = None + self.error = None + + def run(self): + + def _invoke(func, data): + if func is not None: + func(get_data_for_user(data)) + + if self._urllib_func is None: + return + + resp = self._urllib_func(self.url, timeout=self.timeout) + data = resp[0] + code = resp[1] + + if self.stop is True: + return + if self.callback is None: + with self.pubnub.latest_sub_callback_lock: + if self.pubnub.latest_sub_callback['id'] != self.id: + return + else: + if self.pubnub.latest_sub_callback['callback'] is not None: + self.pubnub.latest_sub_callback['id'] = 0 + try: + data = json.loads(data) + except ValueError as e: + _invoke(self.pubnub.latest_sub_callback['error'], + {'error': 'json decoding error'}) + return + if code != 200: + _invoke(self.pubnub.latest_sub_callback['error'], data) + else: + _invoke(self.pubnub.latest_sub_callback['callback'], data) + else: + try: + data = json.loads(data) + except ValueError: + _invoke(self.error, {'error': 'json decoding error'}) + return + + if code != 200: + _invoke(self.error, data) + else: + _invoke(self.callback, data) + + +def _urllib_request_2(url, timeout=5): + try: + resp = urllib2.urlopen(url, timeout=timeout) + except urllib2.HTTPError as http_error: + resp = http_error + except urllib2.URLError as error: + msg = {"message": str(error.reason)} + return (json.dumps(msg), 0) + + return (resp.read(), resp.code) + +s = requests.Session() +s.mount('http://pubsub.pubnub.com', HTTPAdapter(max_retries=1)) +s.mount('https://pubsub.pubnub.com', HTTPAdapter(max_retries=1)) + +def _requests_request(url, timeout=5): + try: + resp = s.get(url, timeout=timeout) + except requests.exceptions.HTTPError as http_error: + resp = http_error + except requests.exceptions.ConnectionError as error: + msg = str(error) + return (json.dumps(msg), 0) + except requests.exceptions.Timeout as error: + msg = str(error) + return (json.dumps(msg), 0) + return (resp.text, resp.status_code) + + +def _urllib_request_3(url, timeout=5): + try: + resp = urllib.request.urlopen(url, timeout=timeout) + except (urllib.request.HTTPError, urllib.request.URLError) as http_error: + resp = http_error + r = resp.read().decode("utf-8") + return (r, resp.code) + +_urllib_request = None + + +# PubnubAsync + +class Pubnub(PubnubCoreAsync): + def __init__( + self, + publish_key, + subscribe_key, + secret_key=None, + cipher_key=None, + auth_key=None, + ssl_on=False, + origin='pubsub.pubnub.com', + pres_uuid=None, + pooling=True + ): + super(Pubnub, self).__init__( + publish_key=publish_key, + subscribe_key=subscribe_key, + secret_key=secret_key, + cipher_key=cipher_key, + auth_key=auth_key, + ssl_on=ssl_on, + origin=origin, + uuid=pres_uuid, + _tt_lock=threading.RLock(), + _channel_list_lock=threading.RLock() + ) + global _urllib_request + if self.python_version == 2: + _urllib_request = _urllib_request_2 + else: + _urllib_request = _urllib_request_3 + + if pooling is True: + _urllib_request = _requests_request + + self.latest_sub_callback_lock = threading.RLock() + self.latest_sub_callback = {'id': None, 'callback': None} + + def timeout(self, interval, func): + def cb(): + time.sleep(interval) + func() + thread = threading.Thread(target=cb) + thread.start() + + def _request_async(self, request, callback=None, error=None, single=False, timeout=5): + global _urllib_request + ## Build URL + url = self.getUrl(request) + if single is True: + id = time.time() + client = HTTPClient(self, url=url, urllib_func=_urllib_request, + callback=None, error=None, id=id, timeout=timeout) + with self.latest_sub_callback_lock: + self.latest_sub_callback['id'] = id + self.latest_sub_callback['callback'] = callback + self.latest_sub_callback['error'] = error + else: + client = HTTPClient(self, url=url, urllib_func=_urllib_request, + callback=callback, error=error, timeout=timeout) + + thread = threading.Thread(target=client.run) + thread.start() + + def abort(): + client.cancel() + return abort + + def _request_sync(self, request, timeout=5): + global _urllib_request + ## Build URL + url = self.getUrl(request) + ## Send Request Expecting JSONP Response + response = _urllib_request(url, timeout=timeout) + try: + resp_json = json.loads(response[0]) + except ValueError: + return [0, "JSON Error"] + + if response[1] != 200 and 'message' in resp_json and 'payload' in resp_json: + return {'message': resp_json['message'], + 'payload': resp_json['payload']} + + if response[1] == 0: + return [0, resp_json] + + return resp_json + + def _request(self, request, callback=None, error=None, single=False, timeout=5): + if callback is None: + return get_data_for_user(self._request_sync(request, timeout=timeout)) + else: + self._request_async(request, callback, error, single=single, timeout=timeout) + +# Pubnub Twisted + +class PubnubTwisted(PubnubCoreAsync): + + def start(self): + reactor.run() + + def stop(self): + reactor.stop() + + def timeout(self, delay, callback): + reactor.callLater(delay, callback) + + def __init__( + self, + publish_key, + subscribe_key, + secret_key=None, + cipher_key=None, + auth_key=None, + ssl_on=False, + origin='pubsub.pubnub.com' + ): + super(PubnubTwisted, self).__init__( + publish_key=publish_key, + subscribe_key=subscribe_key, + secret_key=secret_key, + cipher_key=cipher_key, + auth_key=auth_key, + ssl_on=ssl_on, + origin=origin, + ) + self.headers = {} + self.headers['User-Agent'] = ['Python-Twisted'] + self.headers['V'] = [self.version] + + def _request(self, request, callback=None, error=None, single=False): + global pnconn_pool + + def _invoke(func, data): + if func is not None: + func(get_data_for_user(data)) + + ## Build URL + + url = self.getUrl(request) + + agent = ContentDecoderAgent(RedirectAgent(Agent( + reactor, + contextFactory=WebClientContextFactory(), + pool=self.ssl and None or pnconn_pool + )), [('gzip', GzipDecoder)]) + + try: + request = agent.request( + 'GET', url, Headers(self.headers), None) + except TypeError as te: + request = agent.request( + 'GET', url.encode(), Headers(self.headers), None) + + if single is True: + id = time.time() + self.id = id + + def received(response): + if not isinstance(response, twisted.web._newclient.Response): + _invoke(error, {"message": "Not Found"}) + return + + finished = Deferred() + if response.code in [401, 403]: + response.deliverBody(PubNubPamResponse(finished)) + else: + response.deliverBody(PubNubResponse(finished)) + + return finished + + def complete(data): + if single is True: + if id != self.id: + return None + try: + data = json.loads(data) + except ValueError as e: + try: + data = json.loads(data.decode("utf-8")) + except ValueError as e: + _invoke(error, {'error': 'json decode error'}) + + if 'error' in data and 'status' in data and 'status' != 200: + _invoke(error, data) + else: + _invoke(callback, data) + + def abort(): + pass + + request.addCallback(received) + request.addCallback(complete) + + return abort + + +# PubnubTornado +class PubnubTornado(PubnubCoreAsync): + + def stop(self): + ioloop.stop() + + def start(self): + ioloop.start() + + def timeout(self, delay, callback): + ioloop.add_timeout(time.time() + float(delay), callback) + + def __init__( + self, + publish_key, + subscribe_key, + secret_key=False, + cipher_key=False, + auth_key=False, + ssl_on=False, + origin='pubsub.pubnub.com' + ): + super(PubnubTornado, self).__init__( + publish_key=publish_key, + subscribe_key=subscribe_key, + secret_key=secret_key, + cipher_key=cipher_key, + auth_key=auth_key, + ssl_on=ssl_on, + origin=origin, + ) + self.headers = {} + self.headers['User-Agent'] = 'Python-Tornado' + self.headers['Accept-Encoding'] = self.accept_encoding + self.headers['V'] = self.version + self.http = tornado.httpclient.AsyncHTTPClient(max_clients=1000) + self.id = None + + def _request(self, request, callback=None, error=None, + single=False, timeout=5, connect_timeout=5): + + def _invoke(func, data): + if func is not None: + func(get_data_for_user(data)) + + url = self.getUrl(request) + request = tornado.httpclient.HTTPRequest( + url, 'GET', + self.headers, + connect_timeout=connect_timeout, + request_timeout=timeout) + if single is True: + id = time.time() + self.id = id + + def responseCallback(response): + if single is True: + if not id == self.id: + return None + + body = response._get_body() + + if body is None: + return + + def handle_exc(*args): + return True + if response.error is not None: + with ExceptionStackContext(handle_exc): + if response.code in [403, 401]: + response.rethrow() + else: + _invoke(error, {"message": response.reason}) + return + + try: + data = json.loads(body) + except TypeError as e: + try: + data = json.loads(body.decode("utf-8")) + except ValueError as ve: + _invoke(error, {'error': 'json decode error'}) + + if 'error' in data and 'status' in data and 'status' != 200: + _invoke(error, data) + else: + _invoke(callback, data) + + self.http.fetch( + request=request, + callback=responseCallback + ) + + def abort(): + pass + + return abort @@ -1,100 +1,42 @@ -## PubNub 3.3 Web Data Push Cloud-hosted API - PYTHON -#### www.pubnub.com - PubNub Web Data Push Service in the Cloud. -#### http://github.com/pubnub/python +## Contact support@pubnub.com for all questions -## Major Upgrade to 3.6 underway! In the meantime, we've provided Python 3 beta support in the python3 branch. - -Contact us at support@pubnub.com if you have any questions in the meantime. - -#### Init +#### [PubNub](http://www.pubnub.com) Real-time Data Network +##### Clients for Python, including Twisted and Tornado +## Installation ``` -pubnub = Pubnub( - "demo", ## PUBLISH_KEY - "demo", ## SUBSCRIBE_KEY - None, ## SECRET_KEY - False ## SSL_ON? -) +pip install pubnub==3.5.0 ``` +Examples and instructions for the SDK are available in their acompanying README.md, migration.md and examples directories under their specific platform directories: -#### PUBLISH - -``` -info = pubnub.publish({ - 'channel' : 'hello_world', - 'message' : { - 'some_text' : 'Hello my World' - } -}) -print(info) -``` - - -#### SUBSCRIBE - -``` -# Listen for Messages *BLOCKING* -def receive(message) : - print(message) - return True +[Standalone Python - Everyday python for your scripts and apps](python) -pubnub.subscribe({ - 'channel' : 'hello_world', - 'callback' : receive -}) -``` +[Tornado - For use with the Python Tornado Framework](python-tornado) +[Twisted - For use with the Python Twisted Framework](python-twisted) -#### PRESENCE +## Migration and Reversion +If you need to revert to the previous version of PubNub, run this commandline: ``` -# Listen for Presence Event Messages *BLOCKING* - -def pres_event(message) : - print(message) - return True - -pubnub.presence({ - 'channel' : 'hello_world', - 'callback' : receive -}) +pip install pubnub==3.3.5 ``` -#### HERE_NOW +Migration information for the SDK are available in their migration.md under their specific platform directories: -``` -# Get info on who is here right now! +Migration docs for Python Standalone are [found here.](python/migration.md) -here_now = pubnub.here_now({ - 'channel' : 'hello_world', -}) +Migration docs for Tornado are [found here.](python-tornado/migration.md) -print(here_now['occupancy']) -print(here_now['uuids']) -``` +Migration docs for Twisted [found here.](python-twisted/migration.md) -#### Channel Analytics +## Pubnub Console +Pubnub console is a command line app which allows you to do various +pubnub operations like publish, subscribe, getting history, here now, +presence etc from command line ``` -analytics = pubnub.analytics({ - 'channel' : 'channel-name-here', ## Leave blank for all channels - 'limit' : 100, ## aggregation range - 'ago' : 0, ## minutes ago to look backward - 'duration' : 100 ## minutes offset -}) -print(analytics) - +pip install pubnub-console ``` -#### HISTORY - -``` -# Load Previously Published Messages -history = pubnub.detailedHistory({ - 'channel' : 'my_channel', - 'end' : my_end_time_token, # Optional - 'start' : my_start_time_token, # Optional - 'count' : num_of_msgs_to_return # Optional, default is 100 -}) -print(history) -``` +## Contact support@pubnub.com for all questions @@ -1 +1 @@ -3.3.5 +3.5.0 diff --git a/change_version.sh b/change_version.sh deleted file mode 100644 index 5ea7a63..0000000 --- a/change_version.sh +++ /dev/null @@ -1 +0,0 @@ -find -name "Pubnub*py" | xargs sed -i "s/PubNub\ [0-9]\.[0-9]\.[0-9]/PubNub\ `cat VERSION`/g" diff --git a/common/LICENSE_HEADER b/common/LICENSE_HEADER deleted file mode 100644 index a83793d..0000000 --- a/common/LICENSE_HEADER +++ /dev/null @@ -1,10 +0,0 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. -# coding=utf8 - -## PubNub Real-time Push APIs and Notifications Framework -## Copyright (c) 2010 Stephen Blum -## http://www.pubnub.com/ - -## ----------------------------------- -## PubNub 3.3.4 Real-time Push Cloud API -## ----------------------------------- diff --git a/common/Makefile b/common/Makefile deleted file mode 100644 index 1be6f8c..0000000 --- a/common/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -include ../Makefile.inc - - -.PHONY: all -all: build - -.PHONY: build -build: - find -name "Pubnub*py" | xargs sed -i "s/PubNub\ [0-9]\.[0-9]\.[0-9]/PubNub\ $(VERSION)/g" - - -.PHONY: clean -clean: - -.PHONY: test -test: diff --git a/common/PubnubBase.py b/common/PubnubBase.py deleted file mode 100644 index 5856921..0000000 --- a/common/PubnubBase.py +++ /dev/null @@ -1,364 +0,0 @@ -try: import json -except ImportError: import simplejson as json - -import time -import hashlib -import urllib2 -import uuid - -class PubnubBase(object): - def __init__( - self, - publish_key, - subscribe_key, - secret_key = False, - cipher_key = False, - ssl_on = False, - origin = 'pubsub.pubnub.com', - UUID = None - ) : - """ - #** - #* Pubnub - #* - #* Init the Pubnub Client API - #* - #* @param string publish_key required key to send messages. - #* @param string subscribe_key required key to receive messages. - #* @param string secret_key optional key to sign messages. - #* @param boolean ssl required for 2048 bit encrypted messages. - #* @param string origin PUBNUB Server Origin. - #* @param string pres_uuid optional identifier for presence (auto-generated if not supplied) - #** - - ## Initiat Class - pubnub = Pubnub( 'PUBLISH-KEY', 'SUBSCRIBE-KEY', 'SECRET-KEY', False ) - - """ - self.origin = origin - self.limit = 1800 - self.publish_key = publish_key - self.subscribe_key = subscribe_key - self.secret_key = secret_key - self.cipher_key = cipher_key - self.ssl = ssl_on - self.pc = PubnubCrypto() - - if self.ssl : - self.origin = 'https://' + self.origin - else : - self.origin = 'http://' + self.origin - - self.uuid = UUID or str(uuid.uuid4()) - - if not isinstance(self.uuid, basestring): - raise AttributeError("pres_uuid must be a string") - - def sign(self, channel, message): - ## Sign Message - if self.secret_key: - signature = hashlib.md5('/'.join([ - self.publish_key, - self.subscribe_key, - self.secret_key, - channel, - message - ])).hexdigest() - else: - signature = '0' - return signature - - def encrypt(self, message): - if self.cipher_key: - message = json.dumps(self.pc.encrypt(self.cipher_key, json.dumps(message)).replace('\n','')) - else : - message = json.dumps(message) - - return message; - - def decrypt(self, message): - if self.cipher_key: - message = self.pc.decrypt(self.cipher_key, message) - - return message - - - def publish( self, args ) : - """ - #** - #* Publish - #* - #* Send a message to a channel. - #* - #* @param array args with channel and message. - #* @return array success information. - #** - - ## Publish Example - info = pubnub.publish({ - 'channel' : 'hello_world', - 'message' : { - 'some_text' : 'Hello my World' - } - }) - print(info) - - """ - ## Fail if bad input. - if not (args['channel'] and args['message']) : - return [ 0, 'Missing Channel or Message' ] - - ## Capture User Input - channel = str(args['channel']) - - ## Capture Callback - if args.has_key('callback') : - callback = args['callback'] - else : - callback = None - - #message = json.dumps(args['message'], separators=(',',':')) - message = self.encrypt(args['message']) - - signature = self.sign(channel, message) - - ## Send Message - return self._request({"urlcomponents": [ - 'publish', - self.publish_key, - self.subscribe_key, - signature, - channel, - '0', - message - ]}, callback) - - def presence( self, args ) : - """ - #** - #* presence - #* - #* This is BLOCKING. - #* Listen for presence events on a channel. - #* - #* @param array args with channel and callback. - #* @return false on fail, array on success. - #** - - ## Presence Example - def pres_event(message) : - print(message) - return True - - pubnub.presence({ - 'channel' : 'hello_world', - 'callback' : receive - }) - """ - - ## Fail if missing channel - if not 'channel' in args : - raise Exception('Missing Channel.') - return False - - ## Fail if missing callback - if not 'callback' in args : - raise Exception('Missing Callback.') - return False - - ## Capture User Input - channel = str(args['channel']) - callback = args['callback'] - subscribe_key = args.get('subscribe_key') or self.subscribe_key - - return self.subscribe({'channel': channel+'-pnpres', 'subscribe_key':subscribe_key, 'callback': callback}) - - - def here_now( self, args ) : - """ - #** - #* Here Now - #* - #* Load current occupancy from a channel. - #* - #* @param array args with 'channel'. - #* @return mixed false on fail, array on success. - #* - - ## Presence Example - here_now = pubnub.here_now({ - 'channel' : 'hello_world', - }) - print(here_now['occupancy']) - print(here_now['uuids']) - - """ - channel = str(args['channel']) - - ## Capture Callback - if args.has_key('callback') : - callback = args['callback'] - else : - callback = None - - ## Fail if bad input. - if not channel : - raise Exception('Missing Channel') - return False - - ## Get Presence Here Now - return self._request({"urlcomponents": [ - 'v2','presence', - 'sub_key', self.subscribe_key, - 'channel', channel - ]}, callback); - - - def history( self, args ) : - """ - #** - #* History - #* - #* Load history from a channel. - #* - #* @param array args with 'channel' and 'limit'. - #* @return mixed false on fail, array on success. - #* - - ## History Example - history = pubnub.history({ - 'channel' : 'hello_world', - 'limit' : 1 - }) - print(history) - - """ - ## Capture User Input - limit = args.has_key('limit') and int(args['limit']) or 10 - channel = str(args['channel']) - - ## Fail if bad input. - if not channel : - raise Exception('Missing Channel') - return False - - ## Capture Callback - if args.has_key('callback') : - callback = args['callback'] - else : - callback = None - - ## Get History - return self._request({ "urlcomponents" : [ - 'history', - self.subscribe_key, - channel, - '0', - str(limit) - ] }, callback); - - def detailedHistory(self, args) : - """ - #** - #* Detailed History - #* - #* Load Detailed history from a channel. - #* - #* @param array args with 'channel', optional: 'start', 'end', 'reverse', 'count' - #* @return mixed false on fail, array on success. - #* - - ## History Example - history = pubnub.detailedHistory({ - 'channel' : 'hello_world', - 'count' : 5 - }) - print(history) - - """ - ## Capture User Input - channel = str(args['channel']) - - params = dict() - count = 100 - - if args.has_key('count'): - count = int(args['count']) - - params['count'] = str(count) - - if args.has_key('reverse'): - params['reverse'] = str(args['reverse']).lower() - - if args.has_key('start'): - params['start'] = str(args['start']) - - if args.has_key('end'): - params['end'] = str(args['end']) - - ## Fail if bad input. - if not channel : - raise Exception('Missing Channel') - return False - - ## Capture Callback - if args.has_key('callback') : - callback = args['callback'] - else : - callback = None - - ## Get History - return self._request({ 'urlcomponents' : [ - 'v2', - 'history', - 'sub-key', - self.subscribe_key, - 'channel', - channel, - ],'urlparams' : params }, callback=callback); - - def time(self, args = None) : - """ - #** - #* Time - #* - #* Timestamp from PubNub Cloud. - #* - #* @return int timestamp. - #* - - ## PubNub Server Time Example - timestamp = pubnub.time() - print(timestamp) - - """ - ## Capture Callback - if args and args.has_key('callback') : - callback = args['callback'] - else : - callback = None - time = self._request({'urlcomponents' : [ - 'time', - '0' - ]}, callback) - if time != None: - return time[0] - - - def _encode( self, request ) : - return [ - "".join([ ' ~`!@#$%^&*()+=[]\\{}|;\':",./<>?'.find(ch) > -1 and - hex(ord(ch)).replace( '0x', '%' ).upper() or - ch for ch in list(bit) - ]) for bit in request] - - def getUrl(self,request): - ## Build URL - url = self.origin + '/' + "/".join([ - "".join([ ' ~`!@#$%^&*()+=[]\\{}|;\':",./<>?'.find(ch) > -1 and - hex(ord(ch)).replace( '0x', '%' ).upper() or - ch for ch in list(bit) - ]) for bit in request["urlcomponents"]]) - if (request.has_key("urlparams")): - url = url + '?' + "&".join([ x + "=" + y for x,y in request["urlparams"].iteritems()]) - return url diff --git a/common/PubnubCore.py b/common/PubnubCore.py deleted file mode 100644 index dcfd319..0000000 --- a/common/PubnubCore.py +++ /dev/null @@ -1,115 +0,0 @@ -class PubnubCore(PubnubBase): - def __init__( - self, - publish_key, - subscribe_key, - secret_key = False, - cipher_key = False, - ssl_on = False, - origin = 'pubsub.pubnub.com', - uuid = None - ) : - """ - #** - #* Pubnub - #* - #* Init the Pubnub Client API - #* - #* @param string publish_key required key to send messages. - #* @param string subscribe_key required key to receive messages. - #* @param string secret_key optional key to sign messages. - #* @param boolean ssl required for 2048 bit encrypted messages. - #* @param string origin PUBNUB Server Origin. - #* @param string pres_uuid optional identifier for presence (auto-generated if not supplied) - #** - - ## Initiat Class - pubnub = Pubnub( 'PUBLISH-KEY', 'SUBSCRIBE-KEY', 'SECRET-KEY', False ) - - """ - super(PubnubCore, self).__init__( - publish_key=publish_key, - subscribe_key=subscribe_key, - secret_key=secret_key, - cipher_key=cipher_key, - ssl_on=ssl_on, - origin=origin, - UUID=uuid - ) - - self.subscriptions = {} - self.timetoken = 0 - self.version = '3.4' - self.accept_encoding = 'gzip' - - - - def subscribe( self, args ) : - """ - #** - #* Subscribe - #* - #* This is BLOCKING. - #* Listen for a message on a channel. - #* - #* @param array args with channel and callback. - #* @return false on fail, array on success. - #** - - ## Subscribe Example - def receive(message) : - print(message) - return True - - pubnub.subscribe({ - 'channel' : 'hello_world', - 'callback' : receive - }) - - """ - - ## Fail if missing channel - if not 'channel' in args : - raise Exception('Missing Channel.') - return False - - ## Fail if missing callback - if not 'callback' in args : - raise Exception('Missing Callback.') - return False - - ## Capture User Input - channel = str(args['channel']) - callback = args['callback'] - subscribe_key = args.get('subscribe_key') or self.subscribe_key - - ## Begin Subscribe - while True : - - timetoken = 'timetoken' in args and args['timetoken'] or 0 - try : - ## Wait for Message - response = self._request({"urlcomponents" : [ - 'subscribe', - subscribe_key, - channel, - '0', - str(timetoken) - ],"urlparams" : {"uuid" : self.uuid }}) - - messages = response[0] - args['timetoken'] = response[1] - - ## If it was a timeout - if not len(messages) : - continue - - ## Run user Callback and Reconnect if user permits. - for message in messages : - if not callback(self.decrypt(message)) : - return - - except Exception: - time.sleep(1) - - return True diff --git a/common/PubnubCoreAsync.py b/common/PubnubCoreAsync.py deleted file mode 100644 index a7fbb7d..0000000 --- a/common/PubnubCoreAsync.py +++ /dev/null @@ -1,180 +0,0 @@ -try: - from hashlib import sha256 - digestmod = sha256 -except ImportError: - import Crypto.Hash.SHA256 as digestmod - sha256 = digestmod.new -import hmac - -class PubnubCoreAsync(PubnubBase): - - def start(self): pass - def stop(self): pass - def timeout( self, delay, callback ): - pass - - def __init__( - self, - publish_key, - subscribe_key, - secret_key = False, - cipher_key = False, - ssl_on = False, - origin = 'pubsub.pubnub.com', - uuid = None - ) : - """ - #** - #* Pubnub - #* - #* Init the Pubnub Client API - #* - #* @param string publish_key required key to send messages. - #* @param string subscribe_key required key to receive messages. - #* @param string secret_key required key to sign messages. - #* @param boolean ssl required for 2048 bit encrypted messages. - #* @param string origin PUBNUB Server Origin. - #** - - ## Initiat Class - pubnub = Pubnub( 'PUBLISH-KEY', 'SUBSCRIBE-KEY', 'SECRET-KEY', False ) - - """ - super(PubnubCoreAsync, self).__init__( - publish_key=publish_key, - subscribe_key=subscribe_key, - secret_key=secret_key, - cipher_key=cipher_key, - ssl_on=ssl_on, - origin=origin, - UUID=uuid - ) - - self.subscriptions = {} - self.timetoken = 0 - self.version = '3.3.4' - self.accept_encoding = 'gzip' - - def subscribe( self, args ) : - """ - #** - #* Subscribe - #* - #* This is NON-BLOCKING. - #* Listen for a message on a channel. - #* - #* @param array args with channel and message. - #* @return false on fail, array on success. - #** - - ## Subscribe Example - def receive(message) : - print(message) - return True - - ## On Connect Callback - def connected() : - pubnub.publish({ - 'channel' : 'hello_world', - 'message' : { 'some_var' : 'text' } - }) - - ## Subscribe - pubnub.subscribe({ - 'channel' : 'hello_world', - 'connect' : connected, - 'callback' : receive - }) - - """ - ## Fail if missing channel - if not 'channel' in args : - return 'Missing Channel.' - - ## Fail if missing callback - if not 'callback' in args : - return 'Missing Callback.' - - ## Capture User Input - channel = str(args['channel']) - callback = args['callback'] - connectcb = args['connect'] - - if 'errorback' in args: - errorback = args['errorback'] - else: - errorback = lambda x: x - - ## New Channel? - if not (channel in self.subscriptions) : - self.subscriptions[channel] = { - 'first' : False, - 'connected' : False, - } - - ## Ensure Single Connection - if self.subscriptions[channel]['connected'] : - return "Already Connected" - - self.subscriptions[channel]['connected'] = 1 - ## SUBSCRIPTION RECURSION - def _subscribe(): - ## STOP CONNECTION? - if not self.subscriptions[channel]['connected']: - return - - def sub_callback(response): - if not self.subscriptions[channel]['first'] : - self.subscriptions[channel]['first'] = True - connectcb() - - ## STOP CONNECTION? - if not self.subscriptions[channel]['connected']: - return - - - - ## PROBLEM? - if not response: - def time_callback(_time): - if not _time: - self.timeout( 1, _subscribe ) - return errorback("Lost Network Connection") - else: - self.timeout( 1, _subscribe) - - ## ENSURE CONNECTED (Call Time Function) - return self.time({ 'callback' : time_callback }) - - self.timetoken = response[1] - _subscribe() - - pc = PubnubCrypto() - out = [] - for message in response[0]: - callback(self.decrypt(message)) - - ## CONNECT TO PUBNUB SUBSCRIBE SERVERS - try: - self._request( { "urlcomponents" : [ - 'subscribe', - self.subscribe_key, - channel, - '0', - str(self.timetoken) - ], "urlparams" : {"uuid":self.uuid} }, sub_callback ) - except : - self.timeout( 1, _subscribe) - return - - ## BEGIN SUBSCRIPTION (LISTEN FOR MESSAGES) - _subscribe() - def unsubscribe( self, args ): - channel = str(args['channel']) - if not (channel in self.subscriptions): - return False - - ## DISCONNECT - self.subscriptions[channel]['connected'] = 0 - self.subscriptions[channel]['timetoken'] = 0 - self.subscriptions[channel]['first'] = False diff --git a/common/PubnubCrypto.py b/common/PubnubCrypto.py deleted file mode 100644 index df7cb8d..0000000 --- a/common/PubnubCrypto.py +++ /dev/null @@ -1,81 +0,0 @@ -from Crypto.Cipher import AES -from Crypto.Hash import MD5 -from base64 import encodestring, decodestring -import hashlib -import hmac - -class PubnubCrypto() : - """ - #** - #* PubnubCrypto - #* - #** - - ## Initiate Class - pc = PubnubCrypto - - """ - - def pad( self, msg, block_size=16 ): - """ - #** - #* pad - #* - #* pad the text to be encrypted - #* appends a padding character to the end of the String - #* until the string has block_size length - #* @return msg with padding. - #** - """ - padding = block_size - (len(msg) % block_size) - return msg + chr(padding)*padding - - def depad( self, msg ): - """ - #** - #* depad - #* - #* depad the decryptet message" - #* @return msg without padding. - #** - """ - return msg[0:-ord(msg[-1])] - - def getSecret( self, key ): - """ - #** - #* getSecret - #* - #* hases the key to MD5 - #* @return key in MD5 format - #** - """ - return hashlib.sha256(key).hexdigest() - - def encrypt( self, key, msg ): - """ - #** - #* encrypt - #* - #* encrypts the message - #* @return message in encrypted format - #** - """ - secret = self.getSecret(key) - Initial16bytes='0123456789012345' - cipher = AES.new(secret[0:32],AES.MODE_CBC,Initial16bytes) - enc = encodestring(cipher.encrypt(self.pad(msg))) - return enc - def decrypt( self, key, msg ): - """ - #** - #* decrypt - #* - #* decrypts the message - #* @return message in decryped format - #** - """ - secret = self.getSecret(key) - Initial16bytes='0123456789012345' - cipher = AES.new(secret[0:32],AES.MODE_CBC,Initial16bytes) - return self.depad((cipher.decrypt(decodestring(msg)))) diff --git a/common/PubnubUnitTest.py b/common/PubnubUnitTest.py index 2f9d28c..518d226 100644 --- a/common/PubnubUnitTest.py +++ b/common/PubnubUnitTest.py @@ -1,36 +1,37 @@ import time + class Suite(): - def __init__(self, pubnub, expected): - self.pubnub = pubnub - self.total = expected - self.passed = 0 - self.failed = 0 - self.started = False + def __init__(self, pubnub, expected): + self.pubnub = pubnub + self.total = expected + self.passed = 0 + self.failed = 0 + self.started = False - def test(self, condition , name, message = None, response = None): + def test(self, condition, name, message=None, response=None): - if condition: - self.passed += 1 - msg = "PASS : " + name - if message: - msg += ", " + message - if response: - msg += ", " + response - print msg - else: - self.failed += 1 - msg = "FAIL : " + name - if message: - msg += ", " + message - if response: - msg += ", " + response - print msg + if condition: + self.passed += 1 + msg = "PASS : " + name + if message: + msg += ", " + message + if response: + msg += ", " + response + print msg + else: + self.failed += 1 + msg = "FAIL : " + name + if message: + msg += ", " + message + if response: + msg += ", " + response + print msg - if self.total == self.failed + self.passed: - print "\n======== RESULT ========" - print "Total\t:\t", self.total - print "Passed\t:\t", self.passed - print "Failed\t:\t", self.failed - self.pubnub.stop() + if self.total == self.failed + self.passed: + print "\n======== RESULT ========" + print "Total\t:\t", self.total + print "Passed\t:\t", self.passed + print "Failed\t:\t", self.failed + self.pubnub.stop() diff --git a/common/unit-test-async.py b/common/unit-test-async.py index f95c759..c4dfb65 100644 --- a/common/unit-test-async.py +++ b/common/unit-test-async.py @@ -1,4 +1,4 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. +## www.pubnub.com - PubNub Real-time push service in the cloud. # coding=utf8 ## PubNub Real-time Push APIs and Notifications Framework @@ -12,47 +12,47 @@ import sys import time import random -sys.path.append('../') -sys.path.append('./') -sys.path.append('../common/') from Pubnub import Pubnub -publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' +publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' -secret_key = len(sys.argv) > 3 and sys.argv[3] or None -cipher_key = len(sys.argv) > 4 and sys.argv[4] or None -ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False +secret_key = len(sys.argv) > 3 and sys.argv[3] or None +cipher_key = len(sys.argv) > 4 and sys.argv[4] or None +ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False ## ----------------------------------------------------------------------- ## Initiat Class ## ----------------------------------------------------------------------- -pubnub = Pubnub( publish_key, subscribe_key, secret_key, cipher_key, ssl_on ) +pubnub = Pubnub(publish_key, subscribe_key, secret_key, cipher_key, ssl_on) ch = 'python-async-test-channel-' expect = 0 done = 0 failures = 0 passes = 0 + def stop(): global done global count pubnub.stop() print "============================" - print 'Total\t:\t' , failures + passes - print 'PASS\t:\t' , passes + print 'Total\t:\t', failures + passes + print 'PASS\t:\t', passes print 'FAIL\t:\t', failures print "============================" ## --------------------------------------------------------------------------- ## Unit Test Function ## --------------------------------------------------------------------------- -def test( trial, name ) : + + +def test(trial, name): global failures global passes global done done += 1 #print trial - if trial == False: + if trial is False: print 'FAIL : ', name failures += 1 else: @@ -61,77 +61,87 @@ def test( trial, name ) : if done == expect: stop() + def test_publish(): channel = ch + str(random.random()) + def publish_cb(messages): test(messages[0] == 1, "Publish Test") pubnub.publish({ - 'channel' : channel, - 'message' : {'one': 'Hello World! --> ɂ顶@#$%^&*()!', 'two': 'hello2'}, - 'callback' : publish_cb - }) + 'channel': channel, + 'message': {'one': 'Hello World! --> ɂ顶@#$%^&*()!', 'two': 'hello2'}, + 'callback': publish_cb + }) def test_history(): channel = ch + str(random.random()) + def history_cb(messages): - test(len(messages) <= 1, "History Test") + test(len(messages) <= 1, "History Test") pubnub.history({ - 'channel' : channel, - 'limit' : 1, - 'callback' : history_cb + 'channel': channel, + 'limit': 1, + 'callback': history_cb }) - def test_subscribe(): message = "Testing Subscribe " + str(random.random()) channel = ch + str(random.random()) + def subscribe_connect_cb(): def publish_cb(response): - test(response[0] == 1, 'Publish Test in subscribe Connect Callback') + test(response[0] == 1, + 'Publish Test in subscribe Connect Callback') pubnub.publish({ - 'channel' : channel, - 'message' : message, - 'callback' : publish_cb + 'channel': channel, + 'message': message, + 'callback': publish_cb }) + def subscribe_cb(response): - test(response == message , 'Subscribe Receive Test in subscribe Callback') + test(response == message, + 'Subscribe Receive Test in subscribe Callback') pubnub.subscribe({ - 'channel' : channel, - 'connect' : subscribe_connect_cb, + 'channel': channel, + 'connect': subscribe_connect_cb, 'callback': subscribe_cb - }) - + }) + def test_here_now(): - channel = ch + str(random.random()) + channel = ch + str(random.random()) message = "Testing Subscribe" + def subscribe_connect_cb(): def here_now_cb(response): test(response["occupancy"] > 0, 'Here Now Test') + def publish_cb(response): - test(response[0] == 1, 'Here Now Test: Publish Test in subscribe Connect Callback') + test(response[0] == 1, + 'Here Now Test: Publish Test in \ + subscribe Connect Callback') pubnub.publish({ - 'channel' : channel, - 'message' : message, - 'callback' : publish_cb + 'channel': channel, + 'message': message, + 'callback': publish_cb }) time.sleep(5) pubnub.here_now({ - 'channel' : channel, - 'callback' : here_now_cb + 'channel': channel, + 'callback': here_now_cb }) - def subscribe_cb(response): - test(response == message , 'Here Now Test: Subscribe Receive Test in subscribe Callback') + test(response == message, + 'Here Now Test: Subscribe Receive Test in subscribe Callback') pubnub.subscribe({ - 'channel' : channel, - 'connect' : subscribe_connect_cb, + 'channel': channel, + 'connect': subscribe_connect_cb, 'callback': subscribe_cb - }) + }) expect = 7 test_publish() @@ -140,7 +150,6 @@ test_subscribe() test_here_now() - pubnub.start() if failures > 0: raise Exception('Fail', failures) diff --git a/python-tornado/Makefile b/python-tornado/Makefile deleted file mode 100644 index bf23137..0000000 --- a/python-tornado/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -include ../Makefile.inc - - -.PHONY: all -all: build - -.PHONY: build -build: - cat ../common/LICENSE_HEADER > ./Pubnub.py - echo "\n" >> ./Pubnub.py - cat ../common/PubnubCrypto.py >> ./Pubnub.py - echo "\n" >> ./Pubnub.py - cat ../common/PubnubBase.py >> ./Pubnub.py - echo "\n" >> ./Pubnub.py - cat ../common/PubnubCoreAsync.py >> ./Pubnub.py - echo "\n" >> ./Pubnub.py - cat ./unassembled/Platform.py >> ./Pubnub.py - find -name "Pubnub*py" | xargs sed -i "s/PubNub\ [0-9]\.[0-9]\.[0-9]/PubNub\ $(VERSION)/g" - - -.PHONY: clean -clean: - rm -f Pubnub.py* - -.PHONY: test -test: - python tests/unit-tests.py - diff --git a/python-tornado/Pubnub.py b/python-tornado/Pubnub.py deleted file mode 100644 index 89c0d97..0000000 --- a/python-tornado/Pubnub.py +++ /dev/null @@ -1,709 +0,0 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. -# coding=utf8 - -## PubNub Real-time Push APIs and Notifications Framework -## Copyright (c) 2010 Stephen Blum -## http://www.pubnub.com/ - -## ----------------------------------- -## PubNub 3.3.5 Real-time Push Cloud API -## ----------------------------------- - - -from Crypto.Cipher import AES -from Crypto.Hash import MD5 -from base64 import encodestring, decodestring -import hashlib -import hmac - -class PubnubCrypto() : - """ - #** - #* PubnubCrypto - #* - #** - - ## Initiate Class - pc = PubnubCrypto - - """ - - def pad( self, msg, block_size=16 ): - """ - #** - #* pad - #* - #* pad the text to be encrypted - #* appends a padding character to the end of the String - #* until the string has block_size length - #* @return msg with padding. - #** - """ - padding = block_size - (len(msg) % block_size) - return msg + chr(padding)*padding - - def depad( self, msg ): - """ - #** - #* depad - #* - #* depad the decryptet message" - #* @return msg without padding. - #** - """ - return msg[0:-ord(msg[-1])] - - def getSecret( self, key ): - """ - #** - #* getSecret - #* - #* hases the key to MD5 - #* @return key in MD5 format - #** - """ - return hashlib.sha256(key).hexdigest() - - def encrypt( self, key, msg ): - """ - #** - #* encrypt - #* - #* encrypts the message - #* @return message in encrypted format - #** - """ - secret = self.getSecret(key) - Initial16bytes='0123456789012345' - cipher = AES.new(secret[0:32],AES.MODE_CBC,Initial16bytes) - enc = encodestring(cipher.encrypt(self.pad(msg))) - return enc - def decrypt( self, key, msg ): - """ - #** - #* decrypt - #* - #* decrypts the message - #* @return message in decryped format - #** - """ - secret = self.getSecret(key) - Initial16bytes='0123456789012345' - cipher = AES.new(secret[0:32],AES.MODE_CBC,Initial16bytes) - return self.depad((cipher.decrypt(decodestring(msg)))) - - -try: import json -except ImportError: import simplejson as json - -import time -import hashlib -import urllib2 -import uuid - -class PubnubBase(object): - def __init__( - self, - publish_key, - subscribe_key, - secret_key = False, - cipher_key = False, - ssl_on = False, - origin = 'pubsub.pubnub.com', - UUID = None - ) : - """ - #** - #* Pubnub - #* - #* Init the Pubnub Client API - #* - #* @param string publish_key required key to send messages. - #* @param string subscribe_key required key to receive messages. - #* @param string secret_key optional key to sign messages. - #* @param boolean ssl required for 2048 bit encrypted messages. - #* @param string origin PUBNUB Server Origin. - #* @param string pres_uuid optional identifier for presence (auto-generated if not supplied) - #** - - ## Initiat Class - pubnub = Pubnub( 'PUBLISH-KEY', 'SUBSCRIBE-KEY', 'SECRET-KEY', False ) - - """ - self.origin = origin - self.limit = 1800 - self.publish_key = publish_key - self.subscribe_key = subscribe_key - self.secret_key = secret_key - self.cipher_key = cipher_key - self.ssl = ssl_on - self.pc = PubnubCrypto() - - if self.ssl : - self.origin = 'https://' + self.origin - else : - self.origin = 'http://' + self.origin - - self.uuid = UUID or str(uuid.uuid4()) - - if not isinstance(self.uuid, basestring): - raise AttributeError("pres_uuid must be a string") - - def sign(self, channel, message): - ## Sign Message - if self.secret_key: - signature = hashlib.md5('/'.join([ - self.publish_key, - self.subscribe_key, - self.secret_key, - channel, - message - ])).hexdigest() - else: - signature = '0' - return signature - - def encrypt(self, message): - if self.cipher_key: - message = json.dumps(self.pc.encrypt(self.cipher_key, json.dumps(message)).replace('\n','')) - else : - message = json.dumps(message) - - return message; - - def decrypt(self, message): - if self.cipher_key: - message = self.pc.decrypt(self.cipher_key, message) - - return message - - - def publish( self, args ) : - """ - #** - #* Publish - #* - #* Send a message to a channel. - #* - #* @param array args with channel and message. - #* @return array success information. - #** - - ## Publish Example - info = pubnub.publish({ - 'channel' : 'hello_world', - 'message' : { - 'some_text' : 'Hello my World' - } - }) - print(info) - - """ - ## Fail if bad input. - if not (args['channel'] and args['message']) : - return [ 0, 'Missing Channel or Message' ] - - ## Capture User Input - channel = str(args['channel']) - - ## Capture Callback - if args.has_key('callback') : - callback = args['callback'] - else : - callback = None - - #message = json.dumps(args['message'], separators=(',',':')) - message = self.encrypt(args['message']) - - signature = self.sign(channel, message) - - ## Send Message - return self._request({"urlcomponents": [ - 'publish', - self.publish_key, - self.subscribe_key, - signature, - channel, - '0', - message - ]}, callback) - - def presence( self, args ) : - """ - #** - #* presence - #* - #* This is BLOCKING. - #* Listen for presence events on a channel. - #* - #* @param array args with channel and callback. - #* @return false on fail, array on success. - #** - - ## Presence Example - def pres_event(message) : - print(message) - return True - - pubnub.presence({ - 'channel' : 'hello_world', - 'callback' : receive - }) - """ - - ## Fail if missing channel - if not 'channel' in args : - raise Exception('Missing Channel.') - return False - - ## Fail if missing callback - if not 'callback' in args : - raise Exception('Missing Callback.') - return False - - ## Capture User Input - channel = str(args['channel']) - callback = args['callback'] - subscribe_key = args.get('subscribe_key') or self.subscribe_key - - return self.subscribe({'channel': channel+'-pnpres', 'subscribe_key':subscribe_key, 'callback': callback}) - - - def here_now( self, args ) : - """ - #** - #* Here Now - #* - #* Load current occupancy from a channel. - #* - #* @param array args with 'channel'. - #* @return mixed false on fail, array on success. - #* - - ## Presence Example - here_now = pubnub.here_now({ - 'channel' : 'hello_world', - }) - print(here_now['occupancy']) - print(here_now['uuids']) - - """ - channel = str(args['channel']) - - ## Capture Callback - if args.has_key('callback') : - callback = args['callback'] - else : - callback = None - - ## Fail if bad input. - if not channel : - raise Exception('Missing Channel') - return False - - ## Get Presence Here Now - return self._request({"urlcomponents": [ - 'v2','presence', - 'sub_key', self.subscribe_key, - 'channel', channel - ]}, callback); - - - def history( self, args ) : - """ - #** - #* History - #* - #* Load history from a channel. - #* - #* @param array args with 'channel' and 'limit'. - #* @return mixed false on fail, array on success. - #* - - ## History Example - history = pubnub.history({ - 'channel' : 'hello_world', - 'limit' : 1 - }) - print(history) - - """ - ## Capture User Input - limit = args.has_key('limit') and int(args['limit']) or 10 - channel = str(args['channel']) - - ## Fail if bad input. - if not channel : - raise Exception('Missing Channel') - return False - - ## Capture Callback - if args.has_key('callback') : - callback = args['callback'] - else : - callback = None - - ## Get History - return self._request({ "urlcomponents" : [ - 'history', - self.subscribe_key, - channel, - '0', - str(limit) - ] }, callback); - - def detailedHistory(self, args) : - """ - #** - #* Detailed History - #* - #* Load Detailed history from a channel. - #* - #* @param array args with 'channel', optional: 'start', 'end', 'reverse', 'count' - #* @return mixed false on fail, array on success. - #* - - ## History Example - history = pubnub.detailedHistory({ - 'channel' : 'hello_world', - 'count' : 5 - }) - print(history) - - """ - ## Capture User Input - channel = str(args['channel']) - - params = dict() - count = 100 - - if args.has_key('count'): - count = int(args['count']) - - params['count'] = str(count) - - if args.has_key('reverse'): - params['reverse'] = str(args['reverse']).lower() - - if args.has_key('start'): - params['start'] = str(args['start']) - - if args.has_key('end'): - params['end'] = str(args['end']) - - ## Fail if bad input. - if not channel : - raise Exception('Missing Channel') - return False - - ## Capture Callback - if args.has_key('callback') : - callback = args['callback'] - else : - callback = None - - ## Get History - return self._request({ 'urlcomponents' : [ - 'v2', - 'history', - 'sub-key', - self.subscribe_key, - 'channel', - channel, - ],'urlparams' : params }, callback=callback); - - def time(self, args = None) : - """ - #** - #* Time - #* - #* Timestamp from PubNub Cloud. - #* - #* @return int timestamp. - #* - - ## PubNub Server Time Example - timestamp = pubnub.time() - print(timestamp) - - """ - ## Capture Callback - if args and args.has_key('callback') : - callback = args['callback'] - else : - callback = None - time = self._request({'urlcomponents' : [ - 'time', - '0' - ]}, callback) - if time != None: - return time[0] - - - def _encode( self, request ) : - return [ - "".join([ ' ~`!@#$%^&*()+=[]\\{}|;\':",./<>?'.find(ch) > -1 and - hex(ord(ch)).replace( '0x', '%' ).upper() or - ch for ch in list(bit) - ]) for bit in request] - - def getUrl(self,request): - ## Build URL - url = self.origin + '/' + "/".join([ - "".join([ ' ~`!@#$%^&*()+=[]\\{}|;\':",./<>?'.find(ch) > -1 and - hex(ord(ch)).replace( '0x', '%' ).upper() or - ch for ch in list(bit) - ]) for bit in request["urlcomponents"]]) - if (request.has_key("urlparams")): - url = url + '?' + "&".join([ x + "=" + y for x,y in request["urlparams"].iteritems()]) - return url - - -try: - from hashlib import sha256 - digestmod = sha256 -except ImportError: - import Crypto.Hash.SHA256 as digestmod - sha256 = digestmod.new -import hmac - -class PubnubCoreAsync(PubnubBase): - - def start(self): pass - def stop(self): pass - def timeout( self, delay, callback ): - pass - - def __init__( - self, - publish_key, - subscribe_key, - secret_key = False, - cipher_key = False, - ssl_on = False, - origin = 'pubsub.pubnub.com', - uuid = None - ) : - """ - #** - #* Pubnub - #* - #* Init the Pubnub Client API - #* - #* @param string publish_key required key to send messages. - #* @param string subscribe_key required key to receive messages. - #* @param string secret_key required key to sign messages. - #* @param boolean ssl required for 2048 bit encrypted messages. - #* @param string origin PUBNUB Server Origin. - #** - - ## Initiat Class - pubnub = Pubnub( 'PUBLISH-KEY', 'SUBSCRIBE-KEY', 'SECRET-KEY', False ) - - """ - super(PubnubCoreAsync, self).__init__( - publish_key=publish_key, - subscribe_key=subscribe_key, - secret_key=secret_key, - cipher_key=cipher_key, - ssl_on=ssl_on, - origin=origin, - UUID=uuid - ) - - self.subscriptions = {} - self.timetoken = 0 - self.version = '3.3.4' - self.accept_encoding = 'gzip' - - def subscribe( self, args ) : - """ - #** - #* Subscribe - #* - #* This is NON-BLOCKING. - #* Listen for a message on a channel. - #* - #* @param array args with channel and message. - #* @return false on fail, array on success. - #** - - ## Subscribe Example - def receive(message) : - print(message) - return True - - ## On Connect Callback - def connected() : - pubnub.publish({ - 'channel' : 'hello_world', - 'message' : { 'some_var' : 'text' } - }) - - ## Subscribe - pubnub.subscribe({ - 'channel' : 'hello_world', - 'connect' : connected, - 'callback' : receive - }) - - """ - ## Fail if missing channel - if not 'channel' in args : - return 'Missing Channel.' - - ## Fail if missing callback - if not 'callback' in args : - return 'Missing Callback.' - - ## Capture User Input - channel = str(args['channel']) - callback = args['callback'] - connectcb = args['connect'] - - if 'errorback' in args: - errorback = args['errorback'] - else: - errorback = lambda x: x - - ## New Channel? - if not (channel in self.subscriptions) : - self.subscriptions[channel] = { - 'first' : False, - 'connected' : False, - } - - ## Ensure Single Connection - if self.subscriptions[channel]['connected'] : - return "Already Connected" - - self.subscriptions[channel]['connected'] = 1 - ## SUBSCRIPTION RECURSION - def _subscribe(): - ## STOP CONNECTION? - if not self.subscriptions[channel]['connected']: - return - - def sub_callback(response): - if not self.subscriptions[channel]['first'] : - self.subscriptions[channel]['first'] = True - connectcb() - - ## STOP CONNECTION? - if not self.subscriptions[channel]['connected']: - return - - - - ## PROBLEM? - if not response: - def time_callback(_time): - if not _time: - self.timeout( 1, _subscribe ) - return errorback("Lost Network Connection") - else: - self.timeout( 1, _subscribe) - - ## ENSURE CONNECTED (Call Time Function) - return self.time({ 'callback' : time_callback }) - - self.timetoken = response[1] - _subscribe() - - pc = PubnubCrypto() - out = [] - for message in response[0]: - callback(self.decrypt(message)) - - ## CONNECT TO PUBNUB SUBSCRIBE SERVERS - try: - self._request( { "urlcomponents" : [ - 'subscribe', - self.subscribe_key, - channel, - '0', - str(self.timetoken) - ], "urlparams" : {"uuid":self.uuid} }, sub_callback ) - except : - self.timeout( 1, _subscribe) - return - - ## BEGIN SUBSCRIPTION (LISTEN FOR MESSAGES) - _subscribe() - def unsubscribe( self, args ): - channel = str(args['channel']) - if not (channel in self.subscriptions): - return False - - ## DISCONNECT - self.subscriptions[channel]['connected'] = 0 - self.subscriptions[channel]['timetoken'] = 0 - self.subscriptions[channel]['first'] = False - - -import tornado.httpclient - -try: - from hashlib import sha256 - digestmod = sha256 -except ImportError: - import Crypto.Hash.SHA256 as digestmod - sha256 = digestmod.new - -import hmac -import tornado.ioloop -from tornado.stack_context import ExceptionStackContext - -ioloop = tornado.ioloop.IOLoop.instance() - -class Pubnub(PubnubCoreAsync): - - def stop(self): ioloop.stop() - def start(self): ioloop.start() - def timeout( self, delay, callback): - ioloop.add_timeout( time.time()+float(delay), callback ) - - def __init__( - self, - publish_key, - subscribe_key, - secret_key = False, - cipher_key = False, - ssl_on = False, - origin = 'pubsub.pubnub.com' - ) : - super(Pubnub, self).__init__( - publish_key=publish_key, - subscribe_key=subscribe_key, - secret_key=secret_key, - cipher_key=cipher_key, - ssl_on=ssl_on, - origin=origin, - ) - self.headers = {} - self.headers['User-Agent'] = 'Python-Tornado' - self.headers['Accept-Encoding'] = self.accept_encoding - self.headers['V'] = self.version - self.http = tornado.httpclient.AsyncHTTPClient(max_clients=1000) - - def _request( self, request, callback ) : - url = self.getUrl(request) - ## Send Request Expecting JSON Response - #print self.headers - - request = tornado.httpclient.HTTPRequest( url, 'GET', self.headers, connect_timeout=10, request_timeout=310 ) - - def responseCallback(response): - def handle_exc(*args): - return True - if response.error is not None: - with ExceptionStackContext(handle_exc): - response.rethrow() - elif callback: - callback(eval(response._get_body())) - - self.http.fetch( - request, - callback=responseCallback, - ) - diff --git a/python-tornado/README b/python-tornado/README deleted file mode 100644 index d6eeebe..0000000 --- a/python-tornado/README +++ /dev/null @@ -1,108 +0,0 @@ -## --------------------------------------------------- -## -## YOU MUST HAVE A PUBNUB ACCOUNT TO USE THE API. -## http://www.pubnub.com/account -## -## ---------------------------------------------------- - -## ---------------------------------------------------- -## PubNub 3.1 Real-time Cloud Push API - PYTHON TORNADO -## ---------------------------------------------------- -## -## www.pubnub.com - PubNub Real-time Push Service in the Cloud. -## http://github.com/pubnub/pubnub-api/tree/master/python-tornado/ -## -## PubNub is a Massively Scalable Real-time Service for Web and Mobile Games. -## This is a cloud-based service for broadcasting Real-time messages -## to thousands of web and mobile clients simultaneously. - -## ---------------------------------------------------- -## Third Party Libraries Dependency -## ---------------------------------------------------- -## You must download and install, -## -## 1. pyopenssl -## Download from https://launchpad.net/pyopenssl -## -## 2. pycrypto -## Download from https://github.com/dlitz/pycrypto OR -## from http://code.google.com/p/uploadprj/downloads/detail?name=pycrypto-2.3.win32-py2.7.zip&can=2&q - -## --------------- -## Python Push API -## --------------- -pubnub = Pubnub( - "demo", ## PUBLISH_KEY - "demo", ## SUBSCRIBE_KEY - "demo", ## SECRET_KEY - "", ## CIPHER_KEY (Cipher key is Optional) - False ## SSL_ON? -) - -## ----------------------------------------------------------------------- -## IO Event Loop -## ----------------------------------------------------------------------- -## VERY IMPORTANT TO ADD THIS LINE AT THE VERY BOTTOM! -## -## tornado.ioloop.IOLoop.instance().start() ## IMPORTANT! -## - -## ----------------------------------------------------------------------- -## Subscribe Example -## ----------------------------------------------------------------------- - -def connected() : - ## ----------------------------------------------------------------------- - ## Publish Example - ## ----------------------------------------------------------------------- - def publish_complete(info): - print(info) - - pubnub.publish({ - 'channel' : "my-tornado-channel", - 'message' : { - 'some_text' : 'Hello World!' - }, - 'callback' : publish_complete - }) - -def message_received(message): - print(message) - -pubnub.subscribe({ - 'channel' : "my-tornado-channel", - 'connect' : connected, - 'callback' : message_received -}) - -## ----------------------------------------------------------------------- -## Time Example -## ----------------------------------------------------------------------- -def time_complete(timestamp): - print(timestamp) - -pubnub.time({ 'callback' : time_complete }) - -## ----------------------------------------------------------------------- -## History Example -## ----------------------------------------------------------------------- -def history_complete(messages): - print(messages) - -pubnub.history( { - 'channel' : "my-tornado-channel", - 'limit' : 10, - 'callback' : history_complete -}) - -## ----------------------------------------------------------------------- -## UUID Example -## ----------------------------------------------------------------------- -uuid = pubnub.uuid() -print "UUID" -print uuid - -## ----------------------------------------------------------------------- -## IO Event Loop -## ----------------------------------------------------------------------- -tornado.ioloop.IOLoop.instance().start() diff --git a/python-tornado/README.md b/python-tornado/README.md new file mode 100644 index 0000000..53aad32 --- /dev/null +++ b/python-tornado/README.md @@ -0,0 +1,105 @@ +## Contact support@pubnub.com for all questions + +#### [PubNub](http://www.pubnub.com) Real-time Data Network +##### Tornado Client + +## IO Event Loop +Be sure to eventually start the event loop or PubNub won't run! + +``` +pubnub.start() +``` + +#### Import +``` +from Pubnub import PubnubTornado as Pubnub +``` + +#### Init +``` +pubnub = Pubnub(publish_key="demo", subscribe_key="demo", ssl_on=False) +``` + +#### Publish Example +``` +channel = 'hello_world' +message = 'Hello World !!!' + +# Asynchronous usage + + +def callback(message): + print(message) + +pubnub.publish(channel, message, callback=callback, error=callback) +``` + +#### Subscribe Example +``` +channel = 'hello_world' + +def callback(message, channel): + print(message) + + +def error(message): + print("ERROR : " + str(message)) + + +def connect(message): + print("CONNECTED") + + +def reconnect(message): + print("RECONNECTED") + + +def disconnect(message): + print("DISCONNECTED") + + +pubnub.subscribe(channel, callback=callback, error=callback, + connect=connect, reconnect=reconnect, disconnect=disconnect) +``` + +#### History Example +``` +def callback(message): + print(message) + +pubnub.history(channel, count=2, callback=callback, error=callback) +``` + +#### Here Now Example +``` +def callback(message): + print(message) + +pubnub.here_now(channel, callback=callback, error=callback) +``` + +#### Presence Example +``` +channel = 'hello_world' + +def callback(message, channel): + print(message) + + +def error(message): + print("ERROR : " + str(message)) + +pubnub.presence(channel, callback=callback, error=callback) +``` + +#### Unsubscribe Example +``` +pubnub.unsubscribe(channel='hello_world') +``` + +#### IO Event Loop start +``` +pubnub.start() +``` + +## Contact support@pubnub.com for all questions diff --git a/python-tornado/examples/here-now-example.py b/python-tornado/examples/here-now-example.py deleted file mode 100644 index 85e3432..0000000 --- a/python-tornado/examples/here-now-example.py +++ /dev/null @@ -1,45 +0,0 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. -# coding=utf8 - -## PubNub Real-time Push APIs and Notifications Framework -## Copyright (c) 2010 Stephen Blum -## http://www.pubnub.com/ - -## ----------------------------------- -## PubNub 3.1 Real-time Push Cloud API -## ----------------------------------- - -import sys -import tornado -sys.path.append('..') -sys.path.append('../../common') -from Pubnub import Pubnub - -publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' -subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' -secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' -cipher_key = len(sys.argv) > 4 and sys.argv[4] or '' -ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False - -## ----------------------------------------------------------------------- -## Initiate Pubnub State -## ----------------------------------------------------------------------- -pubnub = Pubnub( publish_key, subscribe_key, secret_key, cipher_key, ssl_on ) -crazy = 'hello_world' - -## ----------------------------------------------------------------------- -## History Example -## ----------------------------------------------------------------------- -def here_now_complete(messages): - print(messages) - pubnub.stop() - -pubnub.here_now( { - 'channel' : crazy, - 'callback' : here_now_complete -}) - -## ----------------------------------------------------------------------- -## IO Event Loop -## ----------------------------------------------------------------------- -pubnub.start() diff --git a/python-tornado/examples/here-now.py b/python-tornado/examples/here-now.py new file mode 100644 index 0000000..5c195f1 --- /dev/null +++ b/python-tornado/examples/here-now.py @@ -0,0 +1,33 @@ +## www.pubnub.com - PubNub Real-time push service in the cloud. +# coding=utf8 + +## PubNub Real-time Push APIs and Notifications Framework +## Copyright (c) 2010 Stephen Blum +## http://www.pubnub.com/ + + +import sys +from Pubnub import PubnubTornado as Pubnub + +publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' +subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' +secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' +cipher_key = len(sys.argv) > 4 and sys.argv[4] or '' +ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False + +## ----------------------------------------------------------------------- +## Initiate Pubnub State +## ----------------------------------------------------------------------- +pubnub = Pubnub(publish_key=publish_key, subscribe_key=subscribe_key, + secret_key=secret_key, cipher_key=cipher_key, ssl_on=ssl_on) +channel = 'hello_world' + + +# Asynchronous usage + +def callback(message): + print(message) + +pubnub.here_now(channel, callback=callback, error=callback) + +pubnub.start() diff --git a/python-tornado/examples/history-example.py b/python-tornado/examples/history-example.py deleted file mode 100644 index c1619f4..0000000 --- a/python-tornado/examples/history-example.py +++ /dev/null @@ -1,44 +0,0 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. -# coding=utf8 - -## PubNub Real-time Push APIs and Notifications Framework -## Copyright (c) 2010 Stephen Blum -## http://www.pubnub.com/ - -## ----------------------------------- -## PubNub 3.0 Real-time Push Cloud API -## ----------------------------------- - -import sys -import tornado -from Pubnub import Pubnub - -publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' -subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' -secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' -cipher_key = len(sys.argv) > 4 and sys.argv[4] or '' -ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False - -## ----------------------------------------------------------------------- -## Initiate Pubnub State -## ----------------------------------------------------------------------- -pubnub = Pubnub( publish_key, subscribe_key, secret_key,cipher_key, ssl_on ) -crazy = 'hello_world' - -## ----------------------------------------------------------------------- -## History Example -## ----------------------------------------------------------------------- -def history_complete(messages): - print(messages) - tornado.ioloop.IOLoop.instance().stop() - -pubnub.history( { - 'channel' : crazy, - 'limit' : 10, - 'callback' : history_complete -}) - -## ----------------------------------------------------------------------- -## IO Event Loop -## ----------------------------------------------------------------------- -tornado.ioloop.IOLoop.instance().start() diff --git a/python-tornado/examples/history.py b/python-tornado/examples/history.py new file mode 100644 index 0000000..daf1c6e --- /dev/null +++ b/python-tornado/examples/history.py @@ -0,0 +1,33 @@ +## www.pubnub.com - PubNub Real-time push service in the cloud. +# coding=utf8 + +## PubNub Real-time Push APIs and Notifications Framework +## Copyright (c) 2010 Stephen Blum +## http://www.pubnub.com/ + + +import sys +from Pubnub import PubnubTornado as Pubnub + +publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' +subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' +secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' +cipher_key = len(sys.argv) > 4 and sys.argv[4] or '' +ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False + +## ----------------------------------------------------------------------- +## Initiate Pubnub State +## ----------------------------------------------------------------------- +pubnub = Pubnub(publish_key=publish_key, subscribe_key=subscribe_key, + secret_key=secret_key, cipher_key=cipher_key, ssl_on=ssl_on) +channel = 'a' + +# Asynchronous usage + + +def callback(message): + print(message) + +pubnub.history(channel, count=2, callback=callback, error=callback) + +pubnub.start() diff --git a/python-tornado/examples/publish-example.py b/python-tornado/examples/publish-example.py deleted file mode 100644 index b9eaa15..0000000 --- a/python-tornado/examples/publish-example.py +++ /dev/null @@ -1,63 +0,0 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. -# coding=utf8 - -## PubNub Real-time Push APIs and Notifications Framework -## Copyright (c) 2010 Stephen Blum -## http://www.pubnub.com/ - -## ----------------------------------- -## PubNub 3.1 Real-time Push Cloud API -## ----------------------------------- - -import sys -import tornado -sys.path.append('../') -sys.path.append('../..') -sys.path.append('../../common') -from Pubnub import Pubnub - -publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' -subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' -secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' -cipher_key = len(sys.argv) > 4 and sys.argv[4] or 'demo' ##(Cipher key is Optional) -ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False - -## ----------------------------------------------------------------------- -## Initiate Pubnub State -## ----------------------------------------------------------------------- -pubnub = Pubnub( publish_key=publish_key, subscribe_key=subscribe_key, secret_key=secret_key,cipher_key=cipher_key, ssl_on=ssl_on ) -#pubnub = Pubnub( publish_key, subscribe_key, secret_key, ssl_on ) -crazy = 'hello_world' - -def publish_complete(info): - print(info) - -## Publish string -pubnub.publish({ - 'channel' : crazy, - 'message' : 'Hello World!', - 'callback' : publish_complete -}) - -## Publish list -li = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] -pubnub.publish({ - 'channel' : crazy, - 'message' : li, - 'callback' : publish_complete -}) - -def done_cb(info): - publish_complete(info) - tornado.ioloop.IOLoop.instance().stop() - -## Publish Dictionary Object -pubnub.publish({ - 'channel' : crazy, - 'message' : { 'some_key' : 'some_val' }, - 'callback' : done_cb -}) -## ----------------------------------------------------------------------- -## IO Event Loop -## ----------------------------------------------------------------------- -tornado.ioloop.IOLoop.instance().start() diff --git a/python-tornado/examples/publish.py b/python-tornado/examples/publish.py new file mode 100644 index 0000000..04e88fd --- /dev/null +++ b/python-tornado/examples/publish.py @@ -0,0 +1,34 @@ +## www.pubnub.com - PubNub Real-time push service in the cloud. +# coding=utf8 + +## PubNub Real-time Push APIs and Notifications Framework +## Copyright (c) 2010 Stephen Blum +## http://www.pubnub.com/ + + +import sys +from Pubnub import PubnubTornado as Pubnub + +publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' +subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' +secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' +cipher_key = len(sys.argv) > 4 and sys.argv[4] or '' +ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False + +## ----------------------------------------------------------------------- +## Initiate Pubnub State +## ----------------------------------------------------------------------- +pubnub = Pubnub(publish_key=publish_key, subscribe_key=subscribe_key, + secret_key=secret_key, cipher_key=cipher_key, ssl_on=ssl_on) +channel = 'hello_world' +message = 'Hello World !!!' + +# Asynchronous usage + + +def callback(message): + print(message) + +pubnub.publish(channel, message, callback=callback, error=callback) + +pubnub.start() diff --git a/python-tornado/examples/subscribe-example.py b/python-tornado/examples/subscribe-example.py deleted file mode 100644 index dfe8010..0000000 --- a/python-tornado/examples/subscribe-example.py +++ /dev/null @@ -1,74 +0,0 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. -# coding=utf8 - -## PubNub Real-time Push APIs and Notifications Framework -## Copyright (c) 2010 Stephen Blum -## http://www.pubnub.com/ - -## ----------------------------------- -## PubNub 3.1 Real-time Push Cloud API -## ----------------------------------- - -import sys -import tornado -sys.path.append('../') -sys.path.append('../..') -from Pubnub import Pubnub - -publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' -subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' -secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' -cipher_key = len(sys.argv) > 4 and sys.argv[4] or 'demo' ##(Cipher key is Optional) -ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False - -## ----------------------------------------------------------------------- -## Initiate Pubnub State -## ----------------------------------------------------------------------- -pubnub = Pubnub( publish_key=publish_key, subscribe_key=subscribe_key, secret_key=secret_key,cipher_key=cipher_key, ssl_on=ssl_on ) -#pubnub = Pubnub( publish_key, subscribe_key, secret_key, ssl_on ) -crazy = 'hello_world' - -def connect_cb(): - print 'Connect' - -def subscribe_result(response): - print response - -pubnub.subscribe({ - 'channel' : crazy, - 'callback' : subscribe_result, - 'connect' : connect_cb -}) -## ----------------------------------------------------------------------- -## Publish Example -## ----------------------------------------------------------------------- -''' -def publish_complete(info): - print(info) - -## Publish string -pubnub.publish({ - 'channel' : crazy, - 'message' : 'Hello World!', - 'callback' : publish_complete -}) - -## Publish list -li = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] -pubnub.publish({ - 'channel' : crazy, - 'message' : li, - 'callback' : publish_complete -}) - -## Publish Dictionary Object -pubnub.publish({ - 'channel' : crazy, - 'message' : { 'some_key' : 'some_val' }, - 'callback' : publish_complete -}) -''' -## ----------------------------------------------------------------------- -## IO Event Loop -## ----------------------------------------------------------------------- -tornado.ioloop.IOLoop.instance().start() diff --git a/python-tornado/examples/subscribe.py b/python-tornado/examples/subscribe.py new file mode 100644 index 0000000..72f0fc1 --- /dev/null +++ b/python-tornado/examples/subscribe.py @@ -0,0 +1,51 @@ +## www.pubnub.com - PubNub Real-time push service in the cloud. +# coding=utf8 + +## PubNub Real-time Push APIs and Notifications Framework +## Copyright (c) 2010 Stephen Blum +## http://www.pubnub.com/ + + +import sys +from Pubnub import PubnubTornado as Pubnub + +publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' +subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' +secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' +cipher_key = len(sys.argv) > 4 and sys.argv[4] or '' +ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False + +## ----------------------------------------------------------------------- +## Initiate Pubnub State +## ----------------------------------------------------------------------- +pubnub = Pubnub(publish_key=publish_key, subscribe_key=subscribe_key, + secret_key=secret_key, cipher_key=cipher_key, ssl_on=ssl_on) + +channel = 'a' + + +# Asynchronous usage +def callback(message, channel): + print(message) + + +def error(message): + print("ERROR : " + str(message)) + + +def connect(message): + print("CONNECTED") + + +def reconnect(message): + print("RECONNECTED") + + +def disconnect(message): + print("DISCONNECTED") + + +pubnub.subscribe(channel, callback=callback, error=callback, + connect=connect, reconnect=reconnect, disconnect=disconnect) + +pubnub.start() diff --git a/python-tornado/examples/uuid-example.py b/python-tornado/examples/uuid-example.py deleted file mode 100644 index f24671b..0000000 --- a/python-tornado/examples/uuid-example.py +++ /dev/null @@ -1,28 +0,0 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. -# coding=utf8 - -## PubNub Real-time Push APIs and Notifications Framework -## Copyright (c) 2010 Stephen Blum -## http://www.pubnub.com/ - -## ----------------------------------- -## PubNub 3.1 Real-time Push Cloud API -## ----------------------------------- - -import sys -import tornado -sys.path.append('../') -from Pubnub import Pubnub - -## ----------------------------------------------------------------------- -## Initiate Pubnub State -## ----------------------------------------------------------------------- -pubnub = Pubnub( "", "", "", False ) - -## ----------------------------------------------------------------------- -## UUID Example -## ----------------------------------------------------------------------- -uuid = pubnub.uuid() -print "UUID: " -print uuid - diff --git a/python-tornado/migration.md b/python-tornado/migration.md new file mode 100644 index 0000000..d5fd8f0 --- /dev/null +++ b/python-tornado/migration.md @@ -0,0 +1,205 @@ +## Contact support@pubnub.com for all questions + +#### [PubNub](http://www.pubnub.com) Real-time Data Network +##### Tornado Migration + +#### Import + +``` +# Pre 3.5: +from Pubnub import Pubnub + +# New in 3.5+ +from Pubnub import PubnubTornado as Pubnub + +``` + + +#### Init + +``` + +# Pre 3.5: +pubnub = Pubnub( + "demo", ## PUBLISH_KEY + "demo", ## SUBSCRIBE_KEY + False ## SSL_ON? +) + +# New in 3.5+ +pubnub = Pubnub(publish_key="demo", subscribe_key="demo", ssl_on=False) + +``` + +#### PUBLISH + +``` +channel = 'hello_world' +message = 'Hello World !!!' + +# Pre 3.5: +def callback(messages): + print(messages) + +pubnub.publish( { + 'channel' : channel, + 'message' : message, + 'callback' : callback +}) + +# New in 3.5+ + +def callback(message): + print(message) + +pubnub.publish(channel, message, callback=callback, error=callback) + +``` + + +#### SUBSCRIBE + +``` + +# Listen for Messages + +channel = 'hello_world' + +# Pre 3.5: +def connected() : + print('CONNECTED') + +def message_received(message): + print(message) + +pubnub.subscribe({ + 'channel' : channel, + 'connect' : connected, + 'callback' : message_received +}) + +# New in 3.5+ + +def callback(message, channel): + print(message) + + +def error(message): + print("ERROR : " + str(message)) + + +def connect(message): + print("CONNECTED") + + +def reconnect(message): + print("RECONNECTED") + + +def disconnect(message): + print("DISCONNECTED") + + +pubnub.subscribe(channel, callback=callback, error=callback, + connect=connect, reconnect=reconnect, disconnect=disconnect) +``` + +#### Unsubscribe +Once subscribed, you can easily, gracefully, unsubscribe: + +``` +# Pre 3.5: +pubnub.unsubscribe({ + 'channel' : 'hello_world' +}) + +# New in 3.5+ + +pubnub.unsubscribe(channel='hello_world') +``` + +#### PRESENCE + +``` + +# Pre 3.5: +# + +# New in 3.5+ + +# Listen for Presence Event Messages + +channel = 'hello_world' + +def callback(message, channel): + print(message) + + +def error(message): + print("ERROR : " + str(message)) + +pubnub.presence(channel, callback=callback, error=callback) +``` + +#### HERE_NOW + +``` + +channel = 'hello_world' + +# Pre 3.5: +def callback(messages): + print(messages) + +pubnub.here_now( { + 'channel' : channel, + 'callback' : callback +}) + + +# New in 3.5+ + +# Get info on who is here right now! + + +def callback(message): + print(message) + +pubnub.here_now(channel, callback=callback, error=callback) +``` + +#### HISTORY + +``` +channel = 'hello_world' + +# Pre 3.5: +def history_complete(messages): + print(messages) + +pubnub.history( { + 'channel' : channel, + 'limit' : 2, + 'callback' : history_complete +}) + + +# New in 3.5+ + +def callback(message): + print(message) + +pubnub.history(channel, count=2, callback=callback, error=callback) +``` + +#### IO Event Loop + +``` + +# Pre 3.5: +tornado.ioloop.IOLoop.instance().start() + +# New in 3.5+ +pubnub.start() +``` +## Contact support@pubnub.com for all questions diff --git a/python-tornado/tests/benchmark.py b/python-tornado/tests/benchmark.py index 9d1840e..748fe3b 100644 --- a/python-tornado/tests/benchmark.py +++ b/python-tornado/tests/benchmark.py @@ -12,10 +12,7 @@ import sys import datetime import tornado -sys.path.append('./') -sys.path.append('../') -sys.path.append('../common') -from Pubnub import Pubnub +from Pubnub import PubnubTwisted as Pubnub publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' diff --git a/python-tornado/tests/delivery.py b/python-tornado/tests/delivery.py index f3633e6..0181403 100644 --- a/python-tornado/tests/delivery.py +++ b/python-tornado/tests/delivery.py @@ -1,4 +1,4 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. +## www.pubnub.com - PubNub Real-time push service in the cloud. # coding=utf8 ## PubNub Real-time Push APIs and Notifications Framework @@ -14,98 +14,104 @@ import datetime import time import math -sys.path.append('../') -from Pubnub import Pubnub +from Pubnub import PubnubTwisted as Pubnub ## ----------------------------------------------------------------------- ## Configuration ## ----------------------------------------------------------------------- -publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' +publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' -secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' -cipher_key = len(sys.argv) > 4 and sys.argv[4] or 'demo' -ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False -origin = len(sys.argv) > 6 and sys.argv[6] or 'pubsub.pubnub.com' +secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' +cipher_key = len(sys.argv) > 4 and sys.argv[4] or 'demo' +ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False +origin = len(sys.argv) > 6 and sys.argv[6] or 'pubsub.pubnub.com' ## ----------------------------------------------------------------------- ## Analytics ## ----------------------------------------------------------------------- analytics = { - 'publishes' : 0, ## Total Send Requests - 'received' : 0, ## Total Received Messages (Deliveries) - 'queued' : 0, ## Total Unreceived Queue (UnDeliveries) - 'successful_publishes' : 0, ## Confirmed Successful Publish Request - 'failed_publishes' : 0, ## Confirmed UNSuccessful Publish Request - 'failed_deliveries' : 0, ## (successful_publishes - received) - 'deliverability' : 0 ## Percentage Delivery + 'publishes': 0, # Total Send Requests + 'received': 0, # Total Received Messages (Deliveries) + 'queued': 0, # Total Unreceived Queue (UnDeliveries) + 'successful_publishes': 0, # Confirmed Successful Publish Request + 'failed_publishes': 0, # Confirmed UNSuccessful Publish Request + 'failed_deliveries': 0, # (successful_publishes - received) + 'deliverability': 0 # Percentage Delivery } trips = { - 'last' : None, - 'current' : None, - 'max' : 0, - 'avg' : 0 + 'last': None, + 'current': None, + 'max': 0, + 'avg': 0 } ## ----------------------------------------------------------------------- ## Initiat Class ## ----------------------------------------------------------------------- channel = 'deliverability-' + str(time.time()) -pubnub = Pubnub( +pubnub = Pubnub( publish_key, subscribe_key, - secret_key = secret_key, - cipher_key = cipher_key, - ssl_on = ssl_on, - origin = origin + secret_key=secret_key, + cipher_key=cipher_key, + ssl_on=ssl_on, + origin=origin ) ## ----------------------------------------------------------------------- ## BENCHMARK ## ----------------------------------------------------------------------- -def publish_sent(info = None): - if info and info[0]: analytics['successful_publishes'] += 1 - else: analytics['failed_publishes'] += 1 + + +def publish_sent(info=None): + if info and info[0]: + analytics['successful_publishes'] += 1 + else: + analytics['failed_publishes'] += 1 analytics['publishes'] += 1 - analytics['queued'] += 1 + analytics['queued'] += 1 + + pubnub.timeout(send, 0.1) - pubnub.timeout( send, 0.1 ) def send(): if analytics['queued'] > 100: analytics['queued'] -= 10 - return pubnub.timeout( send, 10 ) + return pubnub.timeout(send, 10) pubnub.publish({ - 'channel' : channel, - 'callback' : publish_sent, - 'message' : "1234567890" + 'channel': channel, + 'callback': publish_sent, + 'message': "1234567890" }) + def received(message): - analytics['queued'] -= 1 + analytics['queued'] -= 1 analytics['received'] += 1 current_trip = trips['current'] = str(datetime.datetime.now())[0:19] - last_trip = trips['last'] = str( + last_trip = trips['last'] = str( datetime.datetime.now() - datetime.timedelta(seconds=1) )[0:19] ## New Trip Span (1 Second) - if not trips.has_key(current_trip) : + if current_trip not in trips: trips[current_trip] = 0 ## Average - if trips.has_key(last_trip): + if last_trip in trips: trips['avg'] = (trips['avg'] + trips[last_trip]) / 2 ## Increment Trip Counter trips[current_trip] = trips[current_trip] + 1 ## Update Max - if trips[current_trip] > trips['max'] : + if trips[current_trip] > trips['max']: trips['max'] = trips[current_trip] + def show_status(): ## Update Failed Deliveries analytics['failed_deliveries'] = \ @@ -114,45 +120,46 @@ def show_status(): ## Update Deliverability analytics['deliverability'] = ( - float(analytics['received']) / \ + float(analytics['received']) / float(analytics['successful_publishes'] or 1.0) ) * 100.0 ## Print Display - print( ( - "max:%(max)03d/sec " + \ - "avg:%(avg)03d/sec " + \ - "pubs:%(publishes)05d " + \ - "received:%(received)05d " + \ - "spub:%(successful_publishes)05d " + \ - "fpub:%(failed_publishes)05d " + \ - "failed:%(failed_deliveries)05d " + \ - "queued:%(queued)03d " + \ - "delivery:%(deliverability)03f%% " + \ - "" - ) % { - 'max' : trips['max'], - 'avg' : trips['avg'], - 'publishes' : analytics['publishes'], - 'received' : analytics['received'], - 'successful_publishes' : analytics['successful_publishes'], - 'failed_publishes' : analytics['failed_publishes'], - 'failed_deliveries' : analytics['failed_deliveries'], - 'publishes' : analytics['publishes'], - 'deliverability' : analytics['deliverability'], - 'queued' : analytics['queued'] - } ) - pubnub.timeout( show_status, 1 ) + print(( + "max:%(max)03d/sec " + + "avg:%(avg)03d/sec " + + "pubs:%(publishes)05d " + + "received:%(received)05d " + + "spub:%(successful_publishes)05d " + + "fpub:%(failed_publishes)05d " + + "failed:%(failed_deliveries)05d " + + "queued:%(queued)03d " + + "delivery:%(deliverability)03f%% " + + "" + ) % { + 'max': trips['max'], + 'avg': trips['avg'], + 'publishes': analytics['publishes'], + 'received': analytics['received'], + 'successful_publishes': analytics['successful_publishes'], + 'failed_publishes': analytics['failed_publishes'], + 'failed_deliveries': analytics['failed_deliveries'], + 'publishes': analytics['publishes'], + 'deliverability': analytics['deliverability'], + 'queued': analytics['queued'] + }) + pubnub.timeout(show_status, 1) + def connected(): show_status() - pubnub.timeout( send, 1 ) + pubnub.timeout(send, 1) -print( "Connected: %s\n" % origin ) +print("Connected: %s\n" % origin) pubnub.subscribe({ - 'channel' : channel, - 'connect' : connected, - 'callback' : received + 'channel': channel, + 'connect': connected, + 'callback': received }) ## ----------------------------------------------------------------------- diff --git a/python-tornado/tests/subscribe-test.py b/python-tornado/tests/subscribe-test.py new file mode 100755 index 0000000..bcbbc7e --- /dev/null +++ b/python-tornado/tests/subscribe-test.py @@ -0,0 +1,154 @@ +## www.pubnub.com - PubNub Real-time push service in the cloud. +# coding=utf8 + +## PubNub Real-time Push APIs and Notifications Framework +## Copyright (c) 2010 Stephen Blum +## http://www.pubnub.com/ + +## ----------------------------------- +## PubNub 3.1 Real-time Push Cloud API +## ----------------------------------- + +import sys +import datetime +from Pubnub import PubnubTwisted as Pubnub +from functools import partial +from threading import current_thread +import threading +publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' +subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' +secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' +cipher_key = len(sys.argv) > 4 and sys.argv[4] or None +ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False + +## ----------------------------------------------------------------------- +## Initiate Pubnub State +## ----------------------------------------------------------------------- +#pubnub = Pubnub( publish_key, subscribe_key, secret_key, cipher_key, ssl_on ) +pubnub = Pubnub(publish_key, subscribe_key, secret_key, ssl_on) +crazy = 'hello_world' + +current = -1 + +errors = 0 +received = 0 + +## ----------------------------------------------------------------------- +## Subscribe Example +## ----------------------------------------------------------------------- + + +def message_received(message): + print(message) + + +def check_received(message): + global current + global errors + global received + print(message) + print(current) + if message <= current: + print('ERROR') + #sys.exit() + errors += 1 + else: + received += 1 + print('active thread count : ' + str(threading.activeCount())) + print('errors = ' + str(errors)) + print(current_thread().getName() + ' , ' + 'received = ' + str(received)) + + if received != message: + print('********** MISSED **************** ' + str(message - received)) + current = message + + +def connected_test(ch): + print('Connected ' + ch) + + +def connected(ch): + pass + + +''' +pubnub.subscribe({ + 'channel' : 'abcd1', + 'connect' : connected, + 'callback' : message_received +}) +''' + + +def cb1(): + pubnub.subscribe({ + 'channel': 'efgh1', + 'connect': connected, + 'callback': message_received + }) + + +def cb2(): + pubnub.subscribe({ + 'channel': 'dsm-test', + 'connect': connected_test, + 'callback': check_received + }) + + +def cb3(): + pubnub.unsubscribe({'channel': 'efgh1'}) + + +def cb4(): + pubnub.unsubscribe({'channel': 'abcd1'}) + + +def subscribe(channel): + pubnub.subscribe({ + 'channel': channel, + 'connect': connected, + 'callback': message_received + }) + + +pubnub.timeout(15, cb1) + +pubnub.timeout(30, cb2) + + +pubnub.timeout(45, cb3) + +pubnub.timeout(60, cb4) + +#''' +for x in range(1, 1000): + #print x + def y(t): + subscribe('channel-' + str(t)) + + def z(t): + pubnub.unsubscribe({'channel': 'channel-' + str(t)}) + + pubnub.timeout(x + 5, partial(y, x)) + pubnub.timeout(x + 25, partial(z, x)) + x += 10 +#''' + +''' +for x in range(1,1000): + def cb(r): print r , ' : ', threading.activeCount() + def y(t): + pubnub.publish({ + 'message' : t, + 'callback' : cb, + 'channel' : 'dsm-test' + }) + + + pubnub.timeout(x + 1, partial(y,x)) + x += 1 +''' + + +pubnub.start() diff --git a/python-tornado/tests/test_grant_async.py b/python-tornado/tests/test_grant_async.py new file mode 100644 index 0000000..b51b275 --- /dev/null +++ b/python-tornado/tests/test_grant_async.py @@ -0,0 +1,359 @@ + + +from Pubnub import PubnubTornado as Pubnub +import time + +pubnub = Pubnub("demo","demo") +pubnub_pam = Pubnub("pub-c-c077418d-f83c-4860-b213-2f6c77bde29a", + "sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe", "sec-c-OGU3Y2Q4ZWUtNDQwMC00NTI1LThjNWYtNWJmY2M4OGIwNjEy") + + + +# Grant permission read true, write true, on channel ( Async Mode ) +def test_1(): + + def _callback(resp, ch= None): + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {u'abcd': {u'r': 1, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': u'abcd', u'ttl': 1} + } + + def _error(response): + assert False + + pubnub_pam.grant(channel="abcd", auth_key="abcd", read=True, write=True, ttl=1, callback=_callback, error=_error) + + +# Grant permission read false, write false, on channel ( Async Mode ) +def test_2(): + + def _callback(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {u'abcd': {u'r': 0, u'w': 0}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': u'abcd', u'ttl': 1} + } + + def _error(response): + assert False + + pubnub_pam.grant(channel="abcd", auth_key="abcd", read=False, write=False, ttl=1, callback=_callback, error=_error) + + +# Grant permission read True, write false, on channel ( Async Mode ) +def test_3(): + + def _callback(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {u'abcd': {u'r': 1, u'w': 0}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': u'abcd', u'ttl': 1} + } + + def _error(response): + assert False + + pubnub_pam.grant(channel="abcd", auth_key="abcd", read=True, write=False, ttl=1, callback=_callback, error=_error) + + +# Grant permission read False, write True, on channel ( Async Mode ) +def test_4(): + + def _callback(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {u'abcd': {u'r': 0, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': u'abcd', u'ttl': 1} + } + + def _error(response): + assert False + + pubnub_pam.grant(channel="abcd", auth_key="abcd", read=False, write=True, ttl=1, callback=_callback, error=_error) + + +# Grant permission read False, write True, on channel ( Async Mode ), TTL 10 +def test_5(): + + def _callback(resp,ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {u'abcd': {u'r': 0, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': u'abcd', u'ttl': 10} + } + + + def _error(response): + assert False + + pubnub_pam.grant(channel="abcd", auth_key="abcd", read=False, write=True, ttl=10, callback=_callback, error=_error) + + +# Grant permission read False, write True, without channel ( Async Mode ), TTL 10 +def test_6(): + def _callback(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': { u'r': 0, u'w': 1, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'subkey', u'ttl': 10} + } + + def _error(response): + assert False + + pubnub_pam.grant(auth_key="abcd", read=False, write=True, ttl=10, callback=_callback, error=_error) + + + +# Grant permission read False, write False, without channel ( Async Mode ) +def test_7(): + + def _callback(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': { u'r': 0, u'w': 0, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'subkey', u'ttl': 1} + } + + def _error(response): + resp['response'] = response + + pubnub_pam.grant(auth_key="abcd", read=False, write=False, callback=_callback, error=_error) + + +# Complete flow , try publish on forbidden channel, grant permission to subkey and try again. ( Sync Mode) + +def test_8(): + channel = "test_8-" + str(time.time()) + message = "Hello World" + auth_key = "auth-" + channel + pubnub_pam.set_auth_key(auth_key) + + def _cb1(resp, ch=None): + assert False + def _err1(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + def _cb2(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {auth_key : {u'r': 1, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': channel, u'ttl': 10} + } + def _cb3(resp, ch=None): + assert resp[0] == 1 + def _err3(resp): + assert False + + pubnub_pam.publish(channel=channel,message=message, callback=_cb3, error=_err3) + def _err2(resp): + assert False + + + pubnub_pam.grant(channel=channel, read=True, write=True, auth_key=auth_key, ttl=10, callback=_cb2, error=_err2) + + pubnub_pam.publish(channel=channel,message=message, callback=_cb1, error=_err1) + + +# Complete flow , try publish on forbidden channel, grant permission to authkey and try again. +# then revoke and try again +def test_9(): + channel = "test_9-" + str(time.time()) + message = "Hello World" + auth_key = "auth-" + channel + pubnub_pam.set_auth_key(auth_key) + + def _cb1(resp, ch=None): + assert False + def _err1(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + def _cb2(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {auth_key : {u'r': 1, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': channel, u'ttl': 10} + } + def _cb3(resp, ch=None): + assert resp[0] == 1 + def _cb4(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {auth_key : {u'r': 0, u'w': 0}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': channel, u'ttl': 1} + } + + def _cb5(resp, ch=None): + assert False + def _err5(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + + pubnub_pam.publish(channel=channel,message=message, callback=_cb5, error=_err5) + def _err4(resp): + assert False + pubnub_pam.revoke(channel=channel, auth_key=auth_key, callback=_cb4, error=_err4) + def _err3(resp): + assert False + + pubnub_pam.publish(channel=channel,message=message, callback=_cb3, error=_err3) + def _err2(resp): + assert False + + + pubnub_pam.grant(channel=channel, read=True, write=True, auth_key=auth_key, ttl=10, callback=_cb2, error=_err2) + + pubnub_pam.publish(channel=channel,message=message, callback=_cb1, error=_err1) + + +# Complete flow , try publish on forbidden channel, grant permission channel level for subkey and try again. +# then revoke and try again +def test_10(): + channel = "test_10-" + str(time.time()) + message = "Hello World" + auth_key = "auth-" + channel + pubnub_pam.set_auth_key(auth_key) + + def _cb1(resp, ch=None): + assert False + def _err1(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + def _cb2(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': { u'channels': {channel: {u'r': 1, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'channel', u'ttl': 10} + } + def _cb3(resp, ch=None): + assert resp[0] == 1 + def _cb4(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': { u'channels': {channel : {u'r': 0, u'w': 0}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'channel', u'ttl': 1} + } + + def _cb5(resp, ch=None): + assert False + def _err5(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + + pubnub_pam.publish(channel=channel,message=message, callback=_cb5, error=_err5) + def _err4(resp): + assert False + pubnub_pam.revoke(channel=channel, callback=_cb4, error=_err4) + def _err3(resp): + assert False + + pubnub_pam.publish(channel=channel,message=message, callback=_cb3, error=_err3) + def _err2(resp): + assert False + + + pubnub_pam.grant(channel=channel, read=True, write=True, ttl=10, callback=_cb2, error=_err2) + + pubnub_pam.publish(channel=channel,message=message, callback=_cb1, error=_err1) + + + + + + +# Complete flow , try publish on forbidden channel, grant permission subkey level for subkey and try again. +# then revoke and try again +def test_11(): + channel = "test_11-" + str(time.time()) + message = "Hello World" + auth_key = "auth-" + channel + pubnub_pam.set_auth_key(auth_key) + + def _cb1(resp, ch=None): + assert False + def _err1(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + def _cb2(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': { u'r': 1, u'w': 1, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'subkey', u'ttl': 10} + } + def _cb3(resp, ch=None): + assert resp[0] == 1 + def _cb4(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'r': 0, u'w': 0, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'subkey', u'ttl': 1} + } + + def _cb5(resp, ch=None): + assert False + def _err5(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + + pubnub_pam.publish(channel=channel,message=message, callback=_cb5, error=_err5) + def _err4(resp): + assert False + pubnub_pam.revoke(callback=_cb4, error=_err4) + def _err3(resp): + assert False + + pubnub_pam.publish(channel=channel,message=message, callback=_cb3, error=_err3) + def _err2(resp): + assert False + + + pubnub_pam.grant(read=True, write=True, ttl=10, callback=_cb2, error=_err2) + + pubnub_pam.publish(channel=channel,message=message, callback=_cb1, error=_err1) + + +x = 5 +def run_test(t): + global x + x += 5 + i = (x / 5) - 1 + def _print(): + print('Running test ' + str(i)) + pubnub.timeout(x, _print) + pubnub.timeout(x + 1,t) + +def stop(): + pubnub.stop() + +run_test(test_1) +run_test(test_2) +run_test(test_3) +run_test(test_4) +run_test(test_5) +run_test(test_6) +run_test(test_7) +run_test(test_8) +run_test(test_9) +run_test(test_10) +run_test(test_11) +run_test(stop) + + +pubnub_pam.start() + + diff --git a/python-tornado/tests/test_publish_async.py b/python-tornado/tests/test_publish_async.py new file mode 100644 index 0000000..391297d --- /dev/null +++ b/python-tornado/tests/test_publish_async.py @@ -0,0 +1,304 @@ + + +from Pubnub import PubnubTwisted as Pubnub +import time + +pubnub = Pubnub("demo","demo") +pubnub_enc = Pubnub("demo", "demo", cipher_key="enigma") +pubnub_pam = Pubnub("pub-c-c077418d-f83c-4860-b213-2f6c77bde29a", + "sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe", "sec-c-OGU3Y2Q4ZWUtNDQwMC00NTI1LThjNWYtNWJmY2M4OGIwNjEy") + + + +# Publish and receive string +def test_1(): + + channel = "test_1-" + str(time.time()) + message = "I am a string" + + def _cb(resp, ch=None): + assert resp == message + pubnub.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive array +def test_2(): + + channel = "test_2-" + str(time.time()) + message = [1,2] + + def _cb(resp, ch=None): + assert resp == message + pubnub.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive json object +def test_3(): + + channel = "test_2-" + str(time.time()) + message = { "a" : "b" } + + def _cb(resp, ch=None): + assert resp == message + pubnub.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive number +def test_4(): + + channel = "test_2-" + str(time.time()) + message = 100 + + def _cb(resp, ch=None): + assert resp == message + pubnub.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive number string +def test_5(): + + channel = "test_5-" + str(time.time()) + message = "100" + + def _cb(resp, ch=None): + assert resp == message + pubnub.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub.subscribe(channel, callback=_cb, connect=_connect, error=_error) + + +# Publish and receive string (Encryption enabled) +def test_6(): + + channel = "test_6-" + str(time.time()) + message = "I am a string" + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub_enc.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive array (Encryption enabled) +def test_7(): + + channel = "test_7-" + str(time.time()) + message = [1,2] + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub_enc.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive json object (Encryption enabled) +def test_8(): + + channel = "test_8-" + str(time.time()) + message = { "a" : "b" } + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub_enc.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive number (Encryption enabled) +def test_9(): + + channel = "test_9-" + str(time.time()) + message = 100 + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub_enc.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive number string (Encryption enabled) +def test_10(): + + channel = "test_10-" + str(time.time()) + message = "100" + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub_enc.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive object string (Encryption enabled) +def test_11(): + + channel = "test_11-" + str(time.time()) + message = '{"a" : "b"}' + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub_enc.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive array string (Encryption enabled) +def test_12(): + + channel = "test_12-" + str(time.time()) + message = '[1,2]' + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub_enc.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +x = 5 +def run_test(t): + global x + x += 5 + i = (x / 5) - 1 + def _print(): + print('Running test ' + str(i)) + pubnub.timeout(x, _print) + pubnub.timeout(x + 1,t) + +def stop(): + pubnub.stop() + +run_test(test_1) +run_test(test_2) +run_test(test_3) +run_test(test_4) +run_test(test_5) +run_test(test_6) +run_test(test_7) +run_test(test_8) +run_test(test_9) +run_test(test_10) +run_test(test_11) +run_test(stop) + +pubnub_enc.start() diff --git a/python-tornado/tests/unit-tests.py b/python-tornado/tests/unit-tests.py deleted file mode 100644 index fdaa194..0000000 --- a/python-tornado/tests/unit-tests.py +++ /dev/null @@ -1,73 +0,0 @@ - -import sys - -sys.path.append('../../common') -sys.path.append('..') -sys.path.append('../common') -sys.path.append('.') - -from PubnubUnitTest import Suite -from Pubnub import Pubnub - -pubnub = Pubnub("demo","demo") - -tests_count = 1 + 2 -test_suite = Suite(pubnub,tests_count) - -tests = [] - - -def test_publish(): - name = "Publish Test" - def success(r): - test_suite.test(r[0] == 1, name) - - def fail(e): - test_suite.test(False, msg , e) - - - pubnub.publish({ - 'channel' : 'hello', - 'message' : 'hi', - 'callback' : success, - 'error' : fail - }) -tests.append(test_publish) - - -def test_subscribe_publish(): - channel = "hello" - name = "Subscribe Publish Test" - publish_msg = "This is Pubnub Python-Twisted" - def connect(): - def success(r): - test_suite.test(r[0] == 1, name, "publish success") - - def fail(e): - test_suite.test(False, name , "Publish Failed", e) - - pubnub.publish({ - 'channel' : channel, - 'message' : publish_msg, - 'callback' : success, - 'error' : fail - }) - - def callback(r): - test_suite.test(r == publish_msg, name, "message received") - - pubnub.subscribe({ - 'channel' : channel, - 'callback' : callback, - 'connect' : connect - }) -tests.append(test_subscribe_publish) - - - - - -for t in tests: - t() - -pubnub.start() diff --git a/python-tornado/unassembled/Platform.py b/python-tornado/unassembled/Platform.py deleted file mode 100644 index 62d3a26..0000000 --- a/python-tornado/unassembled/Platform.py +++ /dev/null @@ -1,66 +0,0 @@ -import tornado.httpclient - -try: - from hashlib import sha256 - digestmod = sha256 -except ImportError: - import Crypto.Hash.SHA256 as digestmod - sha256 = digestmod.new - -import hmac -import tornado.ioloop -from tornado.stack_context import ExceptionStackContext - -ioloop = tornado.ioloop.IOLoop.instance() - -class Pubnub(PubnubCoreAsync): - - def stop(self): ioloop.stop() - def start(self): ioloop.start() - def timeout( self, delay, callback): - ioloop.add_timeout( time.time()+float(delay), callback ) - - def __init__( - self, - publish_key, - subscribe_key, - secret_key = False, - cipher_key = False, - ssl_on = False, - origin = 'pubsub.pubnub.com' - ) : - super(Pubnub, self).__init__( - publish_key=publish_key, - subscribe_key=subscribe_key, - secret_key=secret_key, - cipher_key=cipher_key, - ssl_on=ssl_on, - origin=origin, - ) - self.headers = {} - self.headers['User-Agent'] = 'Python-Tornado' - self.headers['Accept-Encoding'] = self.accept_encoding - self.headers['V'] = self.version - self.http = tornado.httpclient.AsyncHTTPClient(max_clients=1000) - - def _request( self, request, callback ) : - url = self.getUrl(request) - ## Send Request Expecting JSON Response - #print self.headers - - request = tornado.httpclient.HTTPRequest( url, 'GET', self.headers, connect_timeout=10, request_timeout=310 ) - - def responseCallback(response): - def handle_exc(*args): - return True - if response.error is not None: - with ExceptionStackContext(handle_exc): - response.rethrow() - elif callback: - callback(eval(response._get_body())) - - self.http.fetch( - request, - callback=responseCallback, - ) - diff --git a/python-twisted/Makefile b/python-twisted/Makefile deleted file mode 100644 index bf23137..0000000 --- a/python-twisted/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -include ../Makefile.inc - - -.PHONY: all -all: build - -.PHONY: build -build: - cat ../common/LICENSE_HEADER > ./Pubnub.py - echo "\n" >> ./Pubnub.py - cat ../common/PubnubCrypto.py >> ./Pubnub.py - echo "\n" >> ./Pubnub.py - cat ../common/PubnubBase.py >> ./Pubnub.py - echo "\n" >> ./Pubnub.py - cat ../common/PubnubCoreAsync.py >> ./Pubnub.py - echo "\n" >> ./Pubnub.py - cat ./unassembled/Platform.py >> ./Pubnub.py - find -name "Pubnub*py" | xargs sed -i "s/PubNub\ [0-9]\.[0-9]\.[0-9]/PubNub\ $(VERSION)/g" - - -.PHONY: clean -clean: - rm -f Pubnub.py* - -.PHONY: test -test: - python tests/unit-tests.py - diff --git a/python-twisted/Pubnub.py b/python-twisted/Pubnub.py deleted file mode 100644 index 66534b5..0000000 --- a/python-twisted/Pubnub.py +++ /dev/null @@ -1,727 +0,0 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. -# coding=utf8 - -## PubNub Real-time Push APIs and Notifications Framework -## Copyright (c) 2010 Stephen Blum -## http://www.pubnub.com/ - -## ----------------------------------- -## PubNub 3.3.5 Real-time Push Cloud API -## ----------------------------------- - - -from Crypto.Cipher import AES -from Crypto.Hash import MD5 -from base64 import encodestring, decodestring -import hashlib -import hmac - -class PubnubCrypto() : - """ - #** - #* PubnubCrypto - #* - #** - - ## Initiate Class - pc = PubnubCrypto - - """ - - def pad( self, msg, block_size=16 ): - """ - #** - #* pad - #* - #* pad the text to be encrypted - #* appends a padding character to the end of the String - #* until the string has block_size length - #* @return msg with padding. - #** - """ - padding = block_size - (len(msg) % block_size) - return msg + chr(padding)*padding - - def depad( self, msg ): - """ - #** - #* depad - #* - #* depad the decryptet message" - #* @return msg without padding. - #** - """ - return msg[0:-ord(msg[-1])] - - def getSecret( self, key ): - """ - #** - #* getSecret - #* - #* hases the key to MD5 - #* @return key in MD5 format - #** - """ - return hashlib.sha256(key).hexdigest() - - def encrypt( self, key, msg ): - """ - #** - #* encrypt - #* - #* encrypts the message - #* @return message in encrypted format - #** - """ - secret = self.getSecret(key) - Initial16bytes='0123456789012345' - cipher = AES.new(secret[0:32],AES.MODE_CBC,Initial16bytes) - enc = encodestring(cipher.encrypt(self.pad(msg))) - return enc - def decrypt( self, key, msg ): - """ - #** - #* decrypt - #* - #* decrypts the message - #* @return message in decryped format - #** - """ - secret = self.getSecret(key) - Initial16bytes='0123456789012345' - cipher = AES.new(secret[0:32],AES.MODE_CBC,Initial16bytes) - return self.depad((cipher.decrypt(decodestring(msg)))) - - -try: import json -except ImportError: import simplejson as json - -import time -import hashlib -import urllib2 -import uuid - -class PubnubBase(object): - def __init__( - self, - publish_key, - subscribe_key, - secret_key = False, - cipher_key = False, - ssl_on = False, - origin = 'pubsub.pubnub.com', - UUID = None - ) : - """ - #** - #* Pubnub - #* - #* Init the Pubnub Client API - #* - #* @param string publish_key required key to send messages. - #* @param string subscribe_key required key to receive messages. - #* @param string secret_key optional key to sign messages. - #* @param boolean ssl required for 2048 bit encrypted messages. - #* @param string origin PUBNUB Server Origin. - #* @param string pres_uuid optional identifier for presence (auto-generated if not supplied) - #** - - ## Initiat Class - pubnub = Pubnub( 'PUBLISH-KEY', 'SUBSCRIBE-KEY', 'SECRET-KEY', False ) - - """ - self.origin = origin - self.limit = 1800 - self.publish_key = publish_key - self.subscribe_key = subscribe_key - self.secret_key = secret_key - self.cipher_key = cipher_key - self.ssl = ssl_on - self.pc = PubnubCrypto() - - if self.ssl : - self.origin = 'https://' + self.origin - else : - self.origin = 'http://' + self.origin - - self.uuid = UUID or str(uuid.uuid4()) - - if not isinstance(self.uuid, basestring): - raise AttributeError("pres_uuid must be a string") - - def sign(self, channel, message): - ## Sign Message - if self.secret_key: - signature = hashlib.md5('/'.join([ - self.publish_key, - self.subscribe_key, - self.secret_key, - channel, - message - ])).hexdigest() - else: - signature = '0' - return signature - - def encrypt(self, message): - if self.cipher_key: - message = json.dumps(self.pc.encrypt(self.cipher_key, json.dumps(message)).replace('\n','')) - else : - message = json.dumps(message) - - return message; - - def decrypt(self, message): - if self.cipher_key: - message = self.pc.decrypt(self.cipher_key, message) - - return message - - - def publish( self, args ) : - """ - #** - #* Publish - #* - #* Send a message to a channel. - #* - #* @param array args with channel and message. - #* @return array success information. - #** - - ## Publish Example - info = pubnub.publish({ - 'channel' : 'hello_world', - 'message' : { - 'some_text' : 'Hello my World' - } - }) - print(info) - - """ - ## Fail if bad input. - if not (args['channel'] and args['message']) : - return [ 0, 'Missing Channel or Message' ] - - ## Capture User Input - channel = str(args['channel']) - - ## Capture Callback - if args.has_key('callback') : - callback = args['callback'] - else : - callback = None - - #message = json.dumps(args['message'], separators=(',',':')) - message = self.encrypt(args['message']) - - signature = self.sign(channel, message) - - ## Send Message - return self._request({"urlcomponents": [ - 'publish', - self.publish_key, - self.subscribe_key, - signature, - channel, - '0', - message - ]}, callback) - - def presence( self, args ) : - """ - #** - #* presence - #* - #* This is BLOCKING. - #* Listen for presence events on a channel. - #* - #* @param array args with channel and callback. - #* @return false on fail, array on success. - #** - - ## Presence Example - def pres_event(message) : - print(message) - return True - - pubnub.presence({ - 'channel' : 'hello_world', - 'callback' : receive - }) - """ - - ## Fail if missing channel - if not 'channel' in args : - raise Exception('Missing Channel.') - return False - - ## Fail if missing callback - if not 'callback' in args : - raise Exception('Missing Callback.') - return False - - ## Capture User Input - channel = str(args['channel']) - callback = args['callback'] - subscribe_key = args.get('subscribe_key') or self.subscribe_key - - return self.subscribe({'channel': channel+'-pnpres', 'subscribe_key':subscribe_key, 'callback': callback}) - - - def here_now( self, args ) : - """ - #** - #* Here Now - #* - #* Load current occupancy from a channel. - #* - #* @param array args with 'channel'. - #* @return mixed false on fail, array on success. - #* - - ## Presence Example - here_now = pubnub.here_now({ - 'channel' : 'hello_world', - }) - print(here_now['occupancy']) - print(here_now['uuids']) - - """ - channel = str(args['channel']) - - ## Capture Callback - if args.has_key('callback') : - callback = args['callback'] - else : - callback = None - - ## Fail if bad input. - if not channel : - raise Exception('Missing Channel') - return False - - ## Get Presence Here Now - return self._request({"urlcomponents": [ - 'v2','presence', - 'sub_key', self.subscribe_key, - 'channel', channel - ]}, callback); - - - def history( self, args ) : - """ - #** - #* History - #* - #* Load history from a channel. - #* - #* @param array args with 'channel' and 'limit'. - #* @return mixed false on fail, array on success. - #* - - ## History Example - history = pubnub.history({ - 'channel' : 'hello_world', - 'limit' : 1 - }) - print(history) - - """ - ## Capture User Input - limit = args.has_key('limit') and int(args['limit']) or 10 - channel = str(args['channel']) - - ## Fail if bad input. - if not channel : - raise Exception('Missing Channel') - return False - - ## Capture Callback - if args.has_key('callback') : - callback = args['callback'] - else : - callback = None - - ## Get History - return self._request({ "urlcomponents" : [ - 'history', - self.subscribe_key, - channel, - '0', - str(limit) - ] }, callback); - - def detailedHistory(self, args) : - """ - #** - #* Detailed History - #* - #* Load Detailed history from a channel. - #* - #* @param array args with 'channel', optional: 'start', 'end', 'reverse', 'count' - #* @return mixed false on fail, array on success. - #* - - ## History Example - history = pubnub.detailedHistory({ - 'channel' : 'hello_world', - 'count' : 5 - }) - print(history) - - """ - ## Capture User Input - channel = str(args['channel']) - - params = dict() - count = 100 - - if args.has_key('count'): - count = int(args['count']) - - params['count'] = str(count) - - if args.has_key('reverse'): - params['reverse'] = str(args['reverse']).lower() - - if args.has_key('start'): - params['start'] = str(args['start']) - - if args.has_key('end'): - params['end'] = str(args['end']) - - ## Fail if bad input. - if not channel : - raise Exception('Missing Channel') - return False - - ## Capture Callback - if args.has_key('callback') : - callback = args['callback'] - else : - callback = None - - ## Get History - return self._request({ 'urlcomponents' : [ - 'v2', - 'history', - 'sub-key', - self.subscribe_key, - 'channel', - channel, - ],'urlparams' : params }, callback=callback); - - def time(self, args = None) : - """ - #** - #* Time - #* - #* Timestamp from PubNub Cloud. - #* - #* @return int timestamp. - #* - - ## PubNub Server Time Example - timestamp = pubnub.time() - print(timestamp) - - """ - ## Capture Callback - if args and args.has_key('callback') : - callback = args['callback'] - else : - callback = None - time = self._request({'urlcomponents' : [ - 'time', - '0' - ]}, callback) - if time != None: - return time[0] - - - def _encode( self, request ) : - return [ - "".join([ ' ~`!@#$%^&*()+=[]\\{}|;\':",./<>?'.find(ch) > -1 and - hex(ord(ch)).replace( '0x', '%' ).upper() or - ch for ch in list(bit) - ]) for bit in request] - - def getUrl(self,request): - ## Build URL - url = self.origin + '/' + "/".join([ - "".join([ ' ~`!@#$%^&*()+=[]\\{}|;\':",./<>?'.find(ch) > -1 and - hex(ord(ch)).replace( '0x', '%' ).upper() or - ch for ch in list(bit) - ]) for bit in request["urlcomponents"]]) - if (request.has_key("urlparams")): - url = url + '?' + "&".join([ x + "=" + y for x,y in request["urlparams"].iteritems()]) - return url - - -try: - from hashlib import sha256 - digestmod = sha256 -except ImportError: - import Crypto.Hash.SHA256 as digestmod - sha256 = digestmod.new -import hmac - -class PubnubCoreAsync(PubnubBase): - - def start(self): pass - def stop(self): pass - def timeout( self, delay, callback ): - pass - - def __init__( - self, - publish_key, - subscribe_key, - secret_key = False, - cipher_key = False, - ssl_on = False, - origin = 'pubsub.pubnub.com', - uuid = None - ) : - """ - #** - #* Pubnub - #* - #* Init the Pubnub Client API - #* - #* @param string publish_key required key to send messages. - #* @param string subscribe_key required key to receive messages. - #* @param string secret_key required key to sign messages. - #* @param boolean ssl required for 2048 bit encrypted messages. - #* @param string origin PUBNUB Server Origin. - #** - - ## Initiat Class - pubnub = Pubnub( 'PUBLISH-KEY', 'SUBSCRIBE-KEY', 'SECRET-KEY', False ) - - """ - super(PubnubCoreAsync, self).__init__( - publish_key=publish_key, - subscribe_key=subscribe_key, - secret_key=secret_key, - cipher_key=cipher_key, - ssl_on=ssl_on, - origin=origin, - UUID=uuid - ) - - self.subscriptions = {} - self.timetoken = 0 - self.version = '3.3.4' - self.accept_encoding = 'gzip' - - def subscribe( self, args ) : - """ - #** - #* Subscribe - #* - #* This is NON-BLOCKING. - #* Listen for a message on a channel. - #* - #* @param array args with channel and message. - #* @return false on fail, array on success. - #** - - ## Subscribe Example - def receive(message) : - print(message) - return True - - ## On Connect Callback - def connected() : - pubnub.publish({ - 'channel' : 'hello_world', - 'message' : { 'some_var' : 'text' } - }) - - ## Subscribe - pubnub.subscribe({ - 'channel' : 'hello_world', - 'connect' : connected, - 'callback' : receive - }) - - """ - ## Fail if missing channel - if not 'channel' in args : - return 'Missing Channel.' - - ## Fail if missing callback - if not 'callback' in args : - return 'Missing Callback.' - - ## Capture User Input - channel = str(args['channel']) - callback = args['callback'] - connectcb = args['connect'] - - if 'errorback' in args: - errorback = args['errorback'] - else: - errorback = lambda x: x - - ## New Channel? - if not (channel in self.subscriptions) : - self.subscriptions[channel] = { - 'first' : False, - 'connected' : False, - } - - ## Ensure Single Connection - if self.subscriptions[channel]['connected'] : - return "Already Connected" - - self.subscriptions[channel]['connected'] = 1 - ## SUBSCRIPTION RECURSION - def _subscribe(): - ## STOP CONNECTION? - if not self.subscriptions[channel]['connected']: - return - - def sub_callback(response): - if not self.subscriptions[channel]['first'] : - self.subscriptions[channel]['first'] = True - connectcb() - - ## STOP CONNECTION? - if not self.subscriptions[channel]['connected']: - return - - - - ## PROBLEM? - if not response: - def time_callback(_time): - if not _time: - self.timeout( 1, _subscribe ) - return errorback("Lost Network Connection") - else: - self.timeout( 1, _subscribe) - - ## ENSURE CONNECTED (Call Time Function) - return self.time({ 'callback' : time_callback }) - - self.timetoken = response[1] - _subscribe() - - pc = PubnubCrypto() - out = [] - for message in response[0]: - callback(self.decrypt(message)) - - ## CONNECT TO PUBNUB SUBSCRIBE SERVERS - try: - self._request( { "urlcomponents" : [ - 'subscribe', - self.subscribe_key, - channel, - '0', - str(self.timetoken) - ], "urlparams" : {"uuid":self.uuid} }, sub_callback ) - except : - self.timeout( 1, _subscribe) - return - - ## BEGIN SUBSCRIPTION (LISTEN FOR MESSAGES) - _subscribe() - def unsubscribe( self, args ): - channel = str(args['channel']) - if not (channel in self.subscriptions): - return False - - ## DISCONNECT - self.subscriptions[channel]['connected'] = 0 - self.subscriptions[channel]['timetoken'] = 0 - self.subscriptions[channel]['first'] = False - - -from twisted.web.client import getPage -from twisted.internet import reactor -from twisted.internet.defer import Deferred -from twisted.internet.protocol import Protocol -from twisted.web.client import Agent, ContentDecoderAgent, RedirectAgent, GzipDecoder -from twisted.web.client import HTTPConnectionPool -from twisted.web.http_headers import Headers -from twisted.internet.ssl import ClientContextFactory -from twisted.internet.task import LoopingCall - -pnconn_pool = HTTPConnectionPool(reactor, persistent=True) -pnconn_pool.maxPersistentPerHost = 100 -pnconn_pool.cachedConnectionTimeout = 310 - -class Pubnub(PubnubCoreAsync): - - def start(self): reactor.run() - def stop(self): reactor.stop() - def timeout( self, delay, callback ): - reactor.callLater( delay, callback ) - - def __init__( - self, - publish_key, - subscribe_key, - secret_key = False, - cipher_key = False, - ssl_on = False, - origin = 'pubsub.pubnub.com' - ) : - super(Pubnub, self).__init__( - publish_key=publish_key, - subscribe_key=subscribe_key, - secret_key=secret_key, - cipher_key=cipher_key, - ssl_on=ssl_on, - origin=origin, - ) - self.headers = {} - self.headers['User-Agent'] = ['Python-Twisted'] - #self.headers['Accept-Encoding'] = [self.accept_encoding] - self.headers['V'] = [self.version] - - def _request( self, request, callback ) : - global pnconn_pool - - ## Build URL - ''' - url = self.origin + '/' + "/".join([ - "".join([ ' ~`!@#$%^&*()+=[]\\{}|;\':",./<>?'.find(ch) > -1 and - hex(ord(ch)).replace( '0x', '%' ).upper() or - ch for ch in list(bit) - ]) for bit in request]) - ''' - url = self.getUrl(request) - agent = ContentDecoderAgent(RedirectAgent(Agent( - reactor, - contextFactory = WebClientContextFactory(), - pool = self.ssl and None or pnconn_pool - )), [('gzip', GzipDecoder)]) - request = agent.request( 'GET', url, Headers(self.headers), None ) - - def received(response): - finished = Deferred() - response.deliverBody(PubNubResponse(finished)) - return finished - - def complete(data): - callback(eval(data)) - - request.addCallback(received) - request.addBoth(complete) - -class WebClientContextFactory(ClientContextFactory): - def getContext(self, hostname, port): - return ClientContextFactory.getContext(self) - -class PubNubResponse(Protocol): - def __init__( self, finished ): - self.finished = finished - - def dataReceived( self, bytes ): - self.finished.callback(bytes) - diff --git a/python-twisted/README b/python-twisted/README deleted file mode 100644 index 5f9b350..0000000 --- a/python-twisted/README +++ /dev/null @@ -1,118 +0,0 @@ -## --------------------------------------------------- -## -## YOU MUST HAVE A PUBNUB ACCOUNT TO USE THE API. -## http://www.pubnub.com/account -## -## ---------------------------------------------------- - -## ---------------------------------------------------- -## PubNub 3.1 Real-time Cloud Push API - PYTHON TWISTED -## ---------------------------------------------------- -## -## www.pubnub.com - PubNub Real-time Push Service in the Cloud. -## http://github.com/pubnub/pubnub-api/tree/master/python-twisted/ -## -## PubNub is a Massively Scalable Real-time Service for Web and Mobile Games. -## This is a cloud-based service for broadcasting Real-time messages -## to thousands of web and mobile clients simultaneously. - -## ---------------------------------------------------- -## Python Twisted Setup -## ---------------------------------------------------- -## Download BZ2 archive from http://twistedmatrix.com/ -## -## > tar xvfj Twisted-12.1.0.tar.bz2 -## > cd Twisted-12.1.0 -## > sudo python setup.py install -## - -## ---------------------------------------------------- -## Third Party Libraries Dependency -## ---------------------------------------------------- -## You must download and install, -## -## 1. pyopenssl -## Download from https://launchpad.net/pyopenssl -## -## 2. pycrypto -## Download from https://github.com/dlitz/pycrypto OR -## from http://code.google.com/p/uploadprj/downloads/detail?name=pycrypto-2.3.win32-py2.7.zip&can=2&q - -## --------------- -## Python Push API -## --------------- -pubnub = Pubnub( - "demo", ## PUBLISH_KEY - "demo", ## SUBSCRIBE_KEY - "demo", ## SECRET_KEY - "", ## CIPHER_KEY (Cipher key is Optional) - False ## SSL_ON? -) - -## ----------------------------------------------------------------------- -## IO Event Loop -## ----------------------------------------------------------------------- -## VERY IMPORTANT TO ADD THIS LINE AT THE VERY BOTTOM! -## -## reactor.run() ## IMPORTANT! -## - -## ----------------------------------------------------------------------- -## Subscribe Example -## ----------------------------------------------------------------------- - -def connected() : - ## ----------------------------------------------------------------------- - ## Publish Example - ## ----------------------------------------------------------------------- - def publish_complete(info): - print(info) - - pubnub.publish({ - 'channel' : "my-twisted-channel", - 'message' : { - 'some_text' : 'Hello World!' - }, - 'callback' : publish_complete - }) - -def message_received(message): - print(message) - -pubnub.subscribe({ - 'channel' : "my-twisted-channel", - 'connect' : connected, - 'callback' : message_received -}) - -## ----------------------------------------------------------------------- -## Time Example -## ----------------------------------------------------------------------- -def time_complete(timestamp): - print(timestamp) - -pubnub.time({ 'callback' : time_complete }) - -## ----------------------------------------------------------------------- -## History Example -## ----------------------------------------------------------------------- -def history_complete(messages): - print(messages) - -pubnub.history( { - 'channel' : "my-twisted-channel", - 'limit' : 10, - 'callback' : history_complete -}) - -## ----------------------------------------------------------------------- -## UUID Example -## ----------------------------------------------------------------------- -uuid = pubnub.uuid() -print "UUID" -print uuid - -## ----------------------------------------------------------------------- -## IO Event Loop -## ----------------------------------------------------------------------- -reactor.run() diff --git a/python-twisted/README.md b/python-twisted/README.md new file mode 100644 index 0000000..ea4173c --- /dev/null +++ b/python-twisted/README.md @@ -0,0 +1,105 @@ +## Contact support@pubnub.com for all questions + +#### [PubNub](http://www.pubnub.com) Real-time Data Network +##### Twisted Client + +## IO Event Loop +Be sure to eventually start the event loop or PubNub won't run! + +``` +pubnub.start() +``` + +#### Import +``` +from Pubnub import PubnubTwisted as Pubnub +``` + +#### Init +``` +pubnub = Pubnub(publish_key="demo", subscribe_key="demo", ssl_on=False) +``` + +#### Publish Example +``` +channel = 'hello_world' +message = 'Hello World !!!' + +# Asynchronous usage + + +def callback(message): + print(message) + +pubnub.publish(channel, message, callback=callback, error=callback) +``` + +#### Subscribe Example +``` +channel = 'hello_world' + +def callback(message, channel): + print(message) + + +def error(message): + print("ERROR : " + str(message)) + + +def connect(message): + print("CONNECTED") + + +def reconnect(message): + print("RECONNECTED") + + +def disconnect(message): + print("DISCONNECTED") + + +pubnub.subscribe(channel, callback=callback, error=callback, + connect=connect, reconnect=reconnect, disconnect=disconnect) +``` + +#### History Example +``` +def callback(message): + print(message) + +pubnub.history(channel, count=2, callback=callback, error=callback) +``` + +#### Here Now Example +``` +def callback(message): + print(message) + +pubnub.here_now(channel, callback=callback, error=callback) +``` + +#### Presence Example +``` +channel = 'hello_world' + +def callback(message, channel): + print(message) + + +def error(message): + print("ERROR : " + str(message)) + +pubnub.presence(channel, callback=callback, error=callback) +``` + +#### Unsubscribe Example +``` +pubnub.unsubscribe(channel='hello_world') +``` + +#### IO Event Loop start +``` +pubnub.start() +``` + +## Contact support@pubnub.com for all questions diff --git a/python-twisted/examples/here-now-example.py b/python-twisted/examples/here-now-example.py deleted file mode 100644 index b3c9dc0..0000000 --- a/python-twisted/examples/here-now-example.py +++ /dev/null @@ -1,43 +0,0 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. -# coding=utf8 - -## PubNub Real-time Push APIs and Notifications Framework -## Copyright (c) 2010 Stephen Blum -## http://www.pubnub.com/ - -## ----------------------------------- -## PubNub 3.1 Real-time Push Cloud API -## ----------------------------------- - -import sys -from twisted.internet import reactor -from Pubnub import Pubnub - -publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' -subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' -secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' -cipher_key = len(sys.argv) > 4 and sys.argv[4] or '' -ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False - -## ----------------------------------------------------------------------- -## Initiate Pubnub State -## ----------------------------------------------------------------------- -pubnub = Pubnub( publish_key, subscribe_key, secret_key, cipher_key, ssl_on ) -crazy = 'hello_world' - -## ----------------------------------------------------------------------- -## History Example -## ----------------------------------------------------------------------- -def here_now_complete(messages): - print(messages) - reactor.stop() - -pubnub.here_now( { - 'channel' : crazy, - 'callback' : here_now_complete -}) - -## ----------------------------------------------------------------------- -## IO Event Loop -## ----------------------------------------------------------------------- -reactor.run() diff --git a/python-twisted/examples/here-now.py b/python-twisted/examples/here-now.py new file mode 100644 index 0000000..38b79f8 --- /dev/null +++ b/python-twisted/examples/here-now.py @@ -0,0 +1,33 @@ +## www.pubnub.com - PubNub Real-time push service in the cloud. +# coding=utf8 + +## PubNub Real-time Push APIs and Notifications Framework +## Copyright (c) 2010 Stephen Blum +## http://www.pubnub.com/ + + +import sys +from Pubnub import PubnubTwisted as Pubnub + +publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' +subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' +secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' +cipher_key = len(sys.argv) > 4 and sys.argv[4] or '' +ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False + +## ----------------------------------------------------------------------- +## Initiate Pubnub State +## ----------------------------------------------------------------------- +pubnub = Pubnub(publish_key=publish_key, subscribe_key=subscribe_key, + secret_key=secret_key, cipher_key=cipher_key, ssl_on=ssl_on) +channel = 'hello_world' + + +# Asynchronous usage + +def callback(message): + print(message) + +pubnub.here_now(channel, callback=callback, error=callback) + +pubnub.start() diff --git a/python-twisted/examples/history-example.py b/python-twisted/examples/history-example.py deleted file mode 100644 index 5f352ef..0000000 --- a/python-twisted/examples/history-example.py +++ /dev/null @@ -1,45 +0,0 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. -# coding=utf8 - -## PubNub Real-time Push APIs and Notifications Framework -## Copyright (c) 2010 Stephen Blum -## http://www.pubnub.com/ - -## ----------------------------------- -## PubNub 3.1 Real-time Push Cloud API -## ----------------------------------- - -import sys -from twisted.internet import reactor -sys.path.append('../') -from Pubnub import Pubnub - -publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' -subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' -secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' -cipher_key = len(sys.argv) > 4 and sys.argv[4] or '' -ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False - -## ----------------------------------------------------------------------- -## Initiate Pubnub State -## ----------------------------------------------------------------------- -pubnub = Pubnub( publish_key, subscribe_key, secret_key, cipher_key, ssl_on ) -crazy = 'hello_world' - -## ----------------------------------------------------------------------- -## History Example -## ----------------------------------------------------------------------- -def history_complete(messages): - print(messages) - reactor.stop() - -pubnub.history( { - 'channel' : crazy, - 'limit' : 10, - 'callback' : history_complete -}) - -## ----------------------------------------------------------------------- -## IO Event Loop -## ----------------------------------------------------------------------- -reactor.run() diff --git a/python-twisted/examples/history.py b/python-twisted/examples/history.py new file mode 100644 index 0000000..81974ec --- /dev/null +++ b/python-twisted/examples/history.py @@ -0,0 +1,33 @@ +## www.pubnub.com - PubNub Real-time push service in the cloud. +# coding=utf8 + +## PubNub Real-time Push APIs and Notifications Framework +## Copyright (c) 2010 Stephen Blum +## http://www.pubnub.com/ + + +import sys +from Pubnub import PubnubTwisted as Pubnub + +publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' +subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' +secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' +cipher_key = len(sys.argv) > 4 and sys.argv[4] or '' +ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False + +## ----------------------------------------------------------------------- +## Initiate Pubnub State +## ----------------------------------------------------------------------- +pubnub = Pubnub(publish_key=publish_key, subscribe_key=subscribe_key, + secret_key=secret_key, cipher_key=cipher_key, ssl_on=ssl_on) +channel = 'a' + +# Asynchronous usage + + +def callback(message): + print(message) + +pubnub.history(channel, count=2, callback=callback, error=callback) + +pubnub.start() diff --git a/python-twisted/examples/publish-example.py b/python-twisted/examples/publish-example.py deleted file mode 100644 index d09ad8d..0000000 --- a/python-twisted/examples/publish-example.py +++ /dev/null @@ -1,64 +0,0 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. -# coding=utf8 - -## PubNub Real-time Push APIs and Notifications Framework -## Copyright (c) 2010 Stephen Blum -## http://www.pubnub.com/ - -## ----------------------------------- -## PubNub 3.1 Real-time Push Cloud API -## ----------------------------------- - -import sys -from twisted.internet import reactor -sys.path.append('../') -sys.path.append('../../') -from Pubnub import Pubnub - -publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' -subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' -secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' -cipher_key = len(sys.argv) > 4 and sys.argv[4] or '' ##(Cipher key is Optional) -ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False - -## ----------------------------------------------------------------------- -## Initiate Pubnub State -## ----------------------------------------------------------------------- -pubnub = Pubnub( publish_key, subscribe_key, secret_key, cipher_key, ssl_on ) -crazy = 'hello_world' - -## ----------------------------------------------------------------------- -## Publish Example -## ----------------------------------------------------------------------- -def publish_complete(info): - print(info) - -## Publish string -pubnub.publish({ - 'channel' : crazy, - 'message' : 'Hello World!', - 'callback' : publish_complete -}) - -## Publish list -li = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] -pubnub.publish({ - 'channel' : crazy, - 'message' : li, - 'callback' : publish_complete -}) - -def done_cb(info): - publish_complete(info) - reactor.stop() -## Publish Dictionary Object -pubnub.publish({ - 'channel' : crazy, - 'message' : { 'some_key' : 'some_val' }, - 'callback' : done_cb -}) - -## ----------------------------------------------------------------------- -## IO Event Loop -## ----------------------------------------------------------------------- -reactor.run() diff --git a/python-twisted/examples/publish.py b/python-twisted/examples/publish.py new file mode 100644 index 0000000..13b5357 --- /dev/null +++ b/python-twisted/examples/publish.py @@ -0,0 +1,34 @@ +## www.pubnub.com - PubNub Real-time push service in the cloud. +# coding=utf8 + +## PubNub Real-time Push APIs and Notifications Framework +## Copyright (c) 2010 Stephen Blum +## http://www.pubnub.com/ + + +import sys +from Pubnub import PubnubTwisted as Pubnub + +publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' +subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' +secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' +cipher_key = len(sys.argv) > 4 and sys.argv[4] or '' +ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False + +## ----------------------------------------------------------------------- +## Initiate Pubnub State +## ----------------------------------------------------------------------- +pubnub = Pubnub(publish_key=publish_key, subscribe_key=subscribe_key, + secret_key=secret_key, cipher_key=cipher_key, ssl_on=ssl_on) +channel = 'hello_world' +message = 'Hello World !!!' + +# Asynchronous usage + + +def callback(message): + print(message) + +pubnub.publish(channel, message, callback=callback, error=callback) + +pubnub.start() diff --git a/python-twisted/examples/subscribe-example.py b/python-twisted/examples/subscribe-example.py deleted file mode 100644 index cf4a919..0000000 --- a/python-twisted/examples/subscribe-example.py +++ /dev/null @@ -1,48 +0,0 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. -# coding=utf8 - -## PubNub Real-time Push APIs and Notifications Framework -## Copyright (c) 2010 Stephen Blum -## http://www.pubnub.com/ - -## ----------------------------------- -## PubNub 3.1 Real-time Push Cloud API -## ----------------------------------- - -import sys -from twisted.internet import reactor -sys.path.append('../') -from Pubnub import Pubnub - -publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' -subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' -secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' -cipher_key = len(sys.argv) > 4 and sys.argv[4] or None -ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False - -## ----------------------------------------------------------------------- -## Initiate Pubnub State -## ----------------------------------------------------------------------- -#pubnub = Pubnub( publish_key, subscribe_key, secret_key, cipher_key, ssl_on ) -pubnub = Pubnub( publish_key, subscribe_key, secret_key, ssl_on ) -crazy = 'hello_world' - -## ----------------------------------------------------------------------- -## Subscribe Example -## ----------------------------------------------------------------------- -def message_received(message): - print(message) - -def connected() : - print 'Connected' - -pubnub.subscribe({ - 'channel' : crazy, - 'connect' : connected, - 'callback' : message_received -}) - -## ----------------------------------------------------------------------- -## IO Event Loop -## ----------------------------------------------------------------------- -reactor.run() diff --git a/python-twisted/examples/subscribe.py b/python-twisted/examples/subscribe.py new file mode 100644 index 0000000..9c73439 --- /dev/null +++ b/python-twisted/examples/subscribe.py @@ -0,0 +1,51 @@ +## www.pubnub.com - PubNub Real-time push service in the cloud. +# coding=utf8 + +## PubNub Real-time Push APIs and Notifications Framework +## Copyright (c) 2010 Stephen Blum +## http://www.pubnub.com/ + + +import sys +from Pubnub import PubnubTwisted as Pubnub + +publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' +subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' +secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' +cipher_key = len(sys.argv) > 4 and sys.argv[4] or '' +ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False + +## ----------------------------------------------------------------------- +## Initiate Pubnub State +## ----------------------------------------------------------------------- +pubnub = Pubnub(publish_key=publish_key, subscribe_key=subscribe_key, + secret_key=secret_key, cipher_key=cipher_key, ssl_on=ssl_on) + +channel = 'a' + + +# Asynchronous usage +def callback(message, channel): + print(message) + + +def error(message): + print("ERROR : " + str(message)) + + +def connect(message): + print("CONNECTED") + + +def reconnect(message): + print("RECONNECTED") + + +def disconnect(message): + print("DISCONNECTED") + + +pubnub.subscribe(channel, callback=callback, error=callback, + connect=connect, reconnect=reconnect, disconnect=disconnect) + +pubnub.start() diff --git a/python-twisted/examples/uuid-example.py b/python-twisted/examples/uuid-example.py deleted file mode 100644 index 94840e0..0000000 --- a/python-twisted/examples/uuid-example.py +++ /dev/null @@ -1,28 +0,0 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. -# coding=utf8 - -## PubNub Real-time Push APIs and Notifications Framework -## Copyright (c) 2010 Stephen Blum -## http://www.pubnub.com/ - -## ----------------------------------- -## PubNub 3.1 Real-time Push Cloud API -## ----------------------------------- - -import sys -from twisted.internet import reactor -sys.path.append('../') -from Pubnub import Pubnub - -## ----------------------------------------------------------------------- -## Initiate Pubnub State -## ----------------------------------------------------------------------- -pubnub = Pubnub( "", "", "", False ) - -## ----------------------------------------------------------------------- -## UUID Example -## ----------------------------------------------------------------------- - -uuid = pubnub.uuid() -print "UUID: " -print uuid diff --git a/python-twisted/migration.md b/python-twisted/migration.md new file mode 100644 index 0000000..49de5a9 --- /dev/null +++ b/python-twisted/migration.md @@ -0,0 +1,205 @@ +## Contact support@pubnub.com for all questions + +#### [PubNub](http://www.pubnub.com) Real-time Data Network +##### Twisted Migration + +#### Import + +``` +# Pre 3.5: +from Pubnub import Pubnub + +# New in 3.5+ +from Pubnub import PubnubTwisted as Pubnub + +``` + + +#### Init + +``` + +# Pre 3.5: +pubnub = Pubnub( + "demo", ## PUBLISH_KEY + "demo", ## SUBSCRIBE_KEY + False ## SSL_ON? +) + +# New in 3.5+ +pubnub = Pubnub(publish_key="demo", subscribe_key="demo", ssl_on=False) + +``` + +#### PUBLISH + +``` +channel = 'hello_world' +message = 'Hello World !!!' + +# Pre 3.5: +def callback(messages): + print(messages) + +pubnub.publish( { + 'channel' : channel, + 'message' : message, + 'callback' : callback +}) + +# New in 3.5+ + +def callback(message): + print(message) + +pubnub.publish(channel, message, callback=callback, error=callback) + +``` + + +#### SUBSCRIBE + +``` + +# Listen for Messages + +channel = 'hello_world' + +# Pre 3.5: +def connected() : + print('CONNECTED') + +def message_received(message): + print(message) + +pubnub.subscribe({ + 'channel' : channel, + 'connect' : connected, + 'callback' : message_received +}) + +# New in 3.5+ + +def callback(message, channel): + print(message) + + +def error(message): + print("ERROR : " + str(message)) + + +def connect(message): + print("CONNECTED") + + +def reconnect(message): + print("RECONNECTED") + + +def disconnect(message): + print("DISCONNECTED") + + +pubnub.subscribe(channel, callback=callback, error=callback, + connect=connect, reconnect=reconnect, disconnect=disconnect) +``` + +#### Unsubscribe +Once subscribed, you can easily, gracefully, unsubscribe: + +``` +# Pre 3.5: +pubnub.unsubscribe({ + 'channel' : 'hello_world' +}) + +# New in 3.5+ + +pubnub.unsubscribe(channel='hello_world') +``` + +#### PRESENCE + +``` + +# Pre 3.5: +# + +# New in 3.5+ + +# Listen for Presence Event Messages + +channel = 'hello_world' + +def callback(message, channel): + print(message) + + +def error(message): + print("ERROR : " + str(message)) + +pubnub.presence(channel, callback=callback, error=callback) +``` + +#### HERE_NOW + +``` + +channel = 'hello_world' + +# Pre 3.5: +def callback(messages): + print(messages) + +pubnub.here_now( { + 'channel' : channel, + 'callback' : callback +}) + + +# New in 3.5+ + +# Get info on who is here right now! + + +def callback(message): + print(message) + +pubnub.here_now(channel, callback=callback, error=callback) +``` + +#### HISTORY + +``` +channel = 'hello_world' + +# Pre 3.5: +def history_complete(messages): + print(messages) + +pubnub.history( { + 'channel' : channel, + 'limit' : 2, + 'callback' : history_complete +}) + + +# New in 3.5+ + +def callback(message): + print(message) + +pubnub.history(channel, count=2, callback=callback, error=callback) +``` + +#### IO Event Loop + +``` + +# Pre 3.5: +reactor.run() + +# New in 3.5+ +pubnub.start() +``` +## Contact support@pubnub.com for all questions diff --git a/python-twisted/tests/benchmark.py b/python-twisted/tests/benchmark.py index d4d6d80..b6477c0 100644 --- a/python-twisted/tests/benchmark.py +++ b/python-twisted/tests/benchmark.py @@ -12,8 +12,7 @@ import sys import datetime from twisted.internet import reactor -sys.path.append('../') -from Pubnub import Pubnub +from Pubnub import PubnubTwisted as Pubnub publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' diff --git a/python-twisted/tests/delivery.py b/python-twisted/tests/delivery.py index dc6b9e2..30ce55f 100644 --- a/python-twisted/tests/delivery.py +++ b/python-twisted/tests/delivery.py @@ -1,4 +1,4 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. +## www.pubnub.com - PubNub Real-time push service in the cloud. # coding=utf8 ## PubNub Real-time Push APIs and Notifications Framework @@ -14,99 +14,105 @@ import datetime import time import math -sys.path.append('../') -from Pubnub import Pubnub +from Pubnub import PubnubTwisted as Pubnub ## ----------------------------------------------------------------------- ## Configuration ## ----------------------------------------------------------------------- -publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' +publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' -secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' -cipher_key = len(sys.argv) > 4 and sys.argv[4] or 'demo' -ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False -origin = len(sys.argv) > 6 and sys.argv[6] or 'pubsub.pubnub.com' +secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' +cipher_key = len(sys.argv) > 4 and sys.argv[4] or 'demo' +ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False +origin = len(sys.argv) > 6 and sys.argv[6] or 'pubsub.pubnub.com' origin = '184.72.9.220' ## ----------------------------------------------------------------------- ## Analytics ## ----------------------------------------------------------------------- analytics = { - 'publishes' : 0, ## Total Send Requests - 'received' : 0, ## Total Received Messages (Deliveries) - 'queued' : 0, ## Total Unreceived Queue (UnDeliveries) - 'successful_publishes' : 0, ## Confirmed Successful Publish Request - 'failed_publishes' : 0, ## Confirmed UNSuccessful Publish Request - 'failed_deliveries' : 0, ## (successful_publishes - received) - 'deliverability' : 0 ## Percentage Delivery + 'publishes': 0, # Total Send Requests + 'received': 0, # Total Received Messages (Deliveries) + 'queued': 0, # Total Unreceived Queue (UnDeliveries) + 'successful_publishes': 0, # Confirmed Successful Publish Request + 'failed_publishes': 0, # Confirmed UNSuccessful Publish Request + 'failed_deliveries': 0, # (successful_publishes - received) + 'deliverability': 0 # Percentage Delivery } trips = { - 'last' : None, - 'current' : None, - 'max' : 0, - 'avg' : 0 + 'last': None, + 'current': None, + 'max': 0, + 'avg': 0 } ## ----------------------------------------------------------------------- ## Initiat Class ## ----------------------------------------------------------------------- channel = 'deliverability-' + str(time.time()) -pubnub = Pubnub( +pubnub = Pubnub( publish_key, subscribe_key, - secret_key = secret_key, - cipher_key = cipher_key, - ssl_on = ssl_on, - origin = origin + secret_key=secret_key, + cipher_key=cipher_key, + ssl_on=ssl_on, + origin=origin ) ## ----------------------------------------------------------------------- ## BENCHMARK ## ----------------------------------------------------------------------- -def publish_sent(info = None): - if info and info[0]: analytics['successful_publishes'] += 1 - else: analytics['failed_publishes'] += 1 + + +def publish_sent(info=None): + if info and info[0]: + analytics['successful_publishes'] += 1 + else: + analytics['failed_publishes'] += 1 analytics['publishes'] += 1 - analytics['queued'] += 1 + analytics['queued'] += 1 + + pubnub.timeout(send, 0.1) - pubnub.timeout( send, 0.1 ) def send(): if analytics['queued'] > 100: analytics['queued'] -= 10 - return pubnub.timeout( send, 10 ) + return pubnub.timeout(send, 10) pubnub.publish({ - 'channel' : channel, - 'callback' : publish_sent, - 'message' : "1234567890" + 'channel': channel, + 'callback': publish_sent, + 'message': "1234567890" }) + def received(message): - analytics['queued'] -= 1 + analytics['queued'] -= 1 analytics['received'] += 1 current_trip = trips['current'] = str(datetime.datetime.now())[0:19] - last_trip = trips['last'] = str( + last_trip = trips['last'] = str( datetime.datetime.now() - datetime.timedelta(seconds=1) )[0:19] ## New Trip Span (1 Second) - if not trips.has_key(current_trip) : + if current_trip not in trips: trips[current_trip] = 0 ## Average - if trips.has_key(last_trip): + if last_trip in trips: trips['avg'] = (trips['avg'] + trips[last_trip]) / 2 ## Increment Trip Counter trips[current_trip] = trips[current_trip] + 1 ## Update Max - if trips[current_trip] > trips['max'] : + if trips[current_trip] > trips['max']: trips['max'] = trips[current_trip] + def show_status(): ## Update Failed Deliveries analytics['failed_deliveries'] = \ @@ -115,45 +121,46 @@ def show_status(): ## Update Deliverability analytics['deliverability'] = ( - float(analytics['received']) / \ + float(analytics['received']) / float(analytics['successful_publishes'] or 1.0) ) * 100.0 ## Print Display - print( ( - "max:%(max)03d/sec " + \ - "avg:%(avg)03d/sec " + \ - "pubs:%(publishes)05d " + \ - "received:%(received)05d " + \ - "spub:%(successful_publishes)05d " + \ - "fpub:%(failed_publishes)05d " + \ - "failed:%(failed_deliveries)05d " + \ - "queued:%(queued)03d " + \ - "delivery:%(deliverability)03f%% " + \ - "" - ) % { - 'max' : trips['max'], - 'avg' : trips['avg'], - 'publishes' : analytics['publishes'], - 'received' : analytics['received'], - 'successful_publishes' : analytics['successful_publishes'], - 'failed_publishes' : analytics['failed_publishes'], - 'failed_deliveries' : analytics['failed_deliveries'], - 'publishes' : analytics['publishes'], - 'deliverability' : analytics['deliverability'], - 'queued' : analytics['queued'] - } ) - pubnub.timeout( show_status, 1 ) + print(( + "max:%(max)03d/sec " + + "avg:%(avg)03d/sec " + + "pubs:%(publishes)05d " + + "received:%(received)05d " + + "spub:%(successful_publishes)05d " + + "fpub:%(failed_publishes)05d " + + "failed:%(failed_deliveries)05d " + + "queued:%(queued)03d " + + "delivery:%(deliverability)03f%% " + + "" + ) % { + 'max': trips['max'], + 'avg': trips['avg'], + 'publishes': analytics['publishes'], + 'received': analytics['received'], + 'successful_publishes': analytics['successful_publishes'], + 'failed_publishes': analytics['failed_publishes'], + 'failed_deliveries': analytics['failed_deliveries'], + 'publishes': analytics['publishes'], + 'deliverability': analytics['deliverability'], + 'queued': analytics['queued'] + }) + pubnub.timeout(show_status, 1) + def connected(): show_status() - pubnub.timeout( send, 1 ) + pubnub.timeout(send, 1) -print( "Connected: %s\n" % origin ) +print("Connected: %s\n" % origin) pubnub.subscribe({ - 'channel' : channel, - 'connect' : connected, - 'callback' : received + 'channel': channel, + 'connect': connected, + 'callback': received }) ## ----------------------------------------------------------------------- diff --git a/python-twisted/tests/subscribe-test.py b/python-twisted/tests/subscribe-test.py new file mode 100755 index 0000000..ba74992 --- /dev/null +++ b/python-twisted/tests/subscribe-test.py @@ -0,0 +1,157 @@ +## www.pubnub.com - PubNub Real-time push service in the cloud. +# coding=utf8 + +## PubNub Real-time Push APIs and Notifications Framework +## Copyright (c) 2010 Stephen Blum +## http://www.pubnub.com/ + +## ----------------------------------- +## PubNub 3.1 Real-time Push Cloud API +## ----------------------------------- + +import sys +import datetime +from Pubnub import PubnubTwisted as Pubnub +from functools import partial +from threading import current_thread +import threading +publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' +subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' +secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' +cipher_key = len(sys.argv) > 4 and sys.argv[4] or None +ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False + +## ----------------------------------------------------------------------- +## Initiate Pubnub State +## ----------------------------------------------------------------------- +#pubnub = Pubnub( publish_key, subscribe_key, secret_key, cipher_key, ssl_on ) +pubnub = Pubnub(publish_key, subscribe_key, secret_key, ssl_on) +crazy = 'hello_world' + +current = -1 + +errors = 0 +received = 0 + +## ----------------------------------------------------------------------- +## Subscribe Example +## ----------------------------------------------------------------------- + + +def message_received(message): + print message + + +def check_received(message): + global current + global errors + global received + print message + print current + if message <= current: + print 'ERROR' + #sys.exit() + errors += 1 + else: + received += 1 + print 'active thread count : ', threading.activeCount() + print 'errors = ', errors + print current_thread().getName(), ' , ', 'received = ', received + + if received != message: + print '********** MISSED **************** ', message - received + current = message + + +def connected_test(ch): + print 'Connected', ch + + +def connected(ch): + pass + + +''' +pubnub.subscribe({ + 'channel' : 'abcd1', + 'connect' : connected, + 'callback' : message_received +}) +''' + + +def cb1(): + pubnub.subscribe({ + 'channel': 'efgh1', + 'connect': connected, + 'callback': message_received + }) + + +def cb2(): + pubnub.subscribe({ + 'channel': 'dsm-test', + 'connect': connected_test, + 'callback': check_received + }) + + +def cb3(): + pubnub.unsubscribe({'channel': 'efgh1'}) + + +def cb4(): + pubnub.unsubscribe({'channel': 'abcd1'}) + + +def subscribe(channel): + pubnub.subscribe({ + 'channel': channel, + 'connect': connected, + 'callback': message_received + }) + + +print threading.activeCount() + + +pubnub.timeout(15, cb1) + +pubnub.timeout(30, cb2) + + +pubnub.timeout(45, cb3) + +pubnub.timeout(60, cb4) + +#''' +for x in range(1, 1000): + #print x + def y(t): + subscribe('channel-' + str(t)) + + def z(t): + pubnub.unsubscribe({'channel': 'channel-' + str(t)}) + + pubnub.timeout(x + 5, partial(y, x)) + pubnub.timeout(x + 25, partial(z, x)) + x += 10 +#''' + +''' +for x in range(1,1000): + def cb(r): print r , ' : ', threading.activeCount() + def y(t): + pubnub.publish({ + 'message' : t, + 'callback' : cb, + 'channel' : 'dsm-test' + }) + + + pubnub.timeout(x + 1, partial(y,x)) + x += 1 +''' + + +pubnub.start() diff --git a/python-twisted/tests/test_grant_async.py b/python-twisted/tests/test_grant_async.py new file mode 100644 index 0000000..5b33b11 --- /dev/null +++ b/python-twisted/tests/test_grant_async.py @@ -0,0 +1,359 @@ + + +from Pubnub import PubnubTwisted as Pubnub +import time + +pubnub = Pubnub("demo","demo") +pubnub_pam = Pubnub("pub-c-c077418d-f83c-4860-b213-2f6c77bde29a", + "sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe", "sec-c-OGU3Y2Q4ZWUtNDQwMC00NTI1LThjNWYtNWJmY2M4OGIwNjEy") + + + +# Grant permission read true, write true, on channel ( Async Mode ) +def test_1(): + + def _callback(resp, ch= None): + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {u'abcd': {u'r': 1, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': u'abcd', u'ttl': 1} + } + + def _error(response): + assert False + + pubnub_pam.grant(channel="abcd", auth_key="abcd", read=True, write=True, ttl=1, callback=_callback, error=_error) + + +# Grant permission read false, write false, on channel ( Async Mode ) +def test_2(): + + def _callback(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {u'abcd': {u'r': 0, u'w': 0}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': u'abcd', u'ttl': 1} + } + + def _error(response): + assert False + + pubnub_pam.grant(channel="abcd", auth_key="abcd", read=False, write=False, ttl=1, callback=_callback, error=_error) + + +# Grant permission read True, write false, on channel ( Async Mode ) +def test_3(): + + def _callback(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {u'abcd': {u'r': 1, u'w': 0}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': u'abcd', u'ttl': 1} + } + + def _error(response): + assert False + + pubnub_pam.grant(channel="abcd", auth_key="abcd", read=True, write=False, ttl=1, callback=_callback, error=_error) + + +# Grant permission read False, write True, on channel ( Async Mode ) +def test_4(): + + def _callback(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {u'abcd': {u'r': 0, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': u'abcd', u'ttl': 1} + } + + def _error(response): + assert False + + pubnub_pam.grant(channel="abcd", auth_key="abcd", read=False, write=True, ttl=1, callback=_callback, error=_error) + + +# Grant permission read False, write True, on channel ( Async Mode ), TTL 10 +def test_5(): + + def _callback(resp,ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {u'abcd': {u'r': 0, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': u'abcd', u'ttl': 10} + } + + + def _error(response): + assert False + + pubnub_pam.grant(channel="abcd", auth_key="abcd", read=False, write=True, ttl=10, callback=_callback, error=_error) + + +# Grant permission read False, write True, without channel ( Async Mode ), TTL 10 +def test_6(): + def _callback(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': { u'r': 0, u'w': 1, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'subkey', u'ttl': 10} + } + + def _error(response): + assert False + + pubnub_pam.grant(auth_key="abcd", read=False, write=True, ttl=10, callback=_callback, error=_error) + + + +# Grant permission read False, write False, without channel ( Async Mode ) +def test_7(): + + def _callback(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': { u'r': 0, u'w': 0, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'subkey', u'ttl': 1} + } + + def _error(response): + resp['response'] = response + + pubnub_pam.grant(auth_key="abcd", read=False, write=False, callback=_callback, error=_error) + + +# Complete flow , try publish on forbidden channel, grant permission to subkey and try again. ( Sync Mode) + +def test_8(): + channel = "test_8-" + str(time.time()) + message = "Hello World" + auth_key = "auth-" + channel + pubnub_pam.set_auth_key(auth_key) + + def _cb1(resp, ch=None): + assert False + def _err1(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + def _cb2(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {auth_key : {u'r': 1, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': channel, u'ttl': 10} + } + def _cb3(resp, ch=None): + assert resp[0] == 1 + def _err3(resp): + assert False + + pubnub_pam.publish(channel=channel,message=message, callback=_cb3, error=_err3) + def _err2(resp): + assert False + + + pubnub_pam.grant(channel=channel, read=True, write=True, auth_key=auth_key, ttl=10, callback=_cb2, error=_err2) + + pubnub_pam.publish(channel=channel,message=message, callback=_cb1, error=_err1) + + +# Complete flow , try publish on forbidden channel, grant permission to authkey and try again. +# then revoke and try again +def test_9(): + channel = "test_9-" + str(time.time()) + message = "Hello World" + auth_key = "auth-" + channel + pubnub_pam.set_auth_key(auth_key) + + def _cb1(resp, ch=None): + assert False + def _err1(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + def _cb2(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {auth_key : {u'r': 1, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': channel, u'ttl': 10} + } + def _cb3(resp, ch=None): + assert resp[0] == 1 + def _cb4(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {auth_key : {u'r': 0, u'w': 0}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': channel, u'ttl': 1} + } + + def _cb5(resp, ch=None): + assert False + def _err5(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + + pubnub_pam.publish(channel=channel,message=message, callback=_cb5, error=_err5) + def _err4(resp): + assert False + pubnub_pam.revoke(channel=channel, auth_key=auth_key, callback=_cb4, error=_err4) + def _err3(resp): + assert False + + pubnub_pam.publish(channel=channel,message=message, callback=_cb3, error=_err3) + def _err2(resp): + assert False + + + pubnub_pam.grant(channel=channel, read=True, write=True, auth_key=auth_key, ttl=10, callback=_cb2, error=_err2) + + pubnub_pam.publish(channel=channel,message=message, callback=_cb1, error=_err1) + + +# Complete flow , try publish on forbidden channel, grant permission channel level for subkey and try again. +# then revoke and try again +def test_10(): + channel = "test_10-" + str(time.time()) + message = "Hello World" + auth_key = "auth-" + channel + pubnub_pam.set_auth_key(auth_key) + + def _cb1(resp, ch=None): + assert False + def _err1(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + def _cb2(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': { u'channels': {channel: {u'r': 1, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'channel', u'ttl': 10} + } + def _cb3(resp, ch=None): + assert resp[0] == 1 + def _cb4(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': { u'channels': {channel : {u'r': 0, u'w': 0}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'channel', u'ttl': 1} + } + + def _cb5(resp, ch=None): + assert False + def _err5(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + + pubnub_pam.publish(channel=channel,message=message, callback=_cb5, error=_err5) + def _err4(resp): + assert False + pubnub_pam.revoke(channel=channel, callback=_cb4, error=_err4) + def _err3(resp): + assert False + + pubnub_pam.publish(channel=channel,message=message, callback=_cb3, error=_err3) + def _err2(resp): + assert False + + + pubnub_pam.grant(channel=channel, read=True, write=True, ttl=10, callback=_cb2, error=_err2) + + pubnub_pam.publish(channel=channel,message=message, callback=_cb1, error=_err1) + + + + + + +# Complete flow , try publish on forbidden channel, grant permission subkey level for subkey and try again. +# then revoke and try again +def test_11(): + channel = "test_11-" + str(time.time()) + message = "Hello World" + auth_key = "auth-" + channel + pubnub_pam.set_auth_key(auth_key) + + def _cb1(resp, ch=None): + assert False + def _err1(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + def _cb2(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': { u'r': 1, u'w': 1, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'subkey', u'ttl': 10} + } + def _cb3(resp, ch=None): + assert resp[0] == 1 + def _cb4(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'r': 0, u'w': 0, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'subkey', u'ttl': 1} + } + + def _cb5(resp, ch=None): + assert False + def _err5(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + + pubnub_pam.publish(channel=channel,message=message, callback=_cb5, error=_err5) + def _err4(resp): + assert False + pubnub_pam.revoke(callback=_cb4, error=_err4) + def _err3(resp): + assert False + + pubnub_pam.publish(channel=channel,message=message, callback=_cb3, error=_err3) + def _err2(resp): + assert False + + + pubnub_pam.grant(read=True, write=True, ttl=10, callback=_cb2, error=_err2) + + pubnub_pam.publish(channel=channel,message=message, callback=_cb1, error=_err1) + + +x = 5 +def run_test(t): + global x + x += 5 + i = (x / 5) - 1 + def _print(): + print('Running test ' + str(i)) + pubnub.timeout(x, _print) + pubnub.timeout(x + 1,t) + +def stop(): + pubnub.stop() + +run_test(test_1) +run_test(test_2) +run_test(test_3) +run_test(test_4) +run_test(test_5) +run_test(test_6) +run_test(test_7) +run_test(test_8) +run_test(test_9) +run_test(test_10) +run_test(test_11) +run_test(stop) + + +pubnub_pam.start() + + diff --git a/python-twisted/tests/test_publish_async.py b/python-twisted/tests/test_publish_async.py new file mode 100644 index 0000000..391297d --- /dev/null +++ b/python-twisted/tests/test_publish_async.py @@ -0,0 +1,304 @@ + + +from Pubnub import PubnubTwisted as Pubnub +import time + +pubnub = Pubnub("demo","demo") +pubnub_enc = Pubnub("demo", "demo", cipher_key="enigma") +pubnub_pam = Pubnub("pub-c-c077418d-f83c-4860-b213-2f6c77bde29a", + "sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe", "sec-c-OGU3Y2Q4ZWUtNDQwMC00NTI1LThjNWYtNWJmY2M4OGIwNjEy") + + + +# Publish and receive string +def test_1(): + + channel = "test_1-" + str(time.time()) + message = "I am a string" + + def _cb(resp, ch=None): + assert resp == message + pubnub.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive array +def test_2(): + + channel = "test_2-" + str(time.time()) + message = [1,2] + + def _cb(resp, ch=None): + assert resp == message + pubnub.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive json object +def test_3(): + + channel = "test_2-" + str(time.time()) + message = { "a" : "b" } + + def _cb(resp, ch=None): + assert resp == message + pubnub.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive number +def test_4(): + + channel = "test_2-" + str(time.time()) + message = 100 + + def _cb(resp, ch=None): + assert resp == message + pubnub.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive number string +def test_5(): + + channel = "test_5-" + str(time.time()) + message = "100" + + def _cb(resp, ch=None): + assert resp == message + pubnub.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub.subscribe(channel, callback=_cb, connect=_connect, error=_error) + + +# Publish and receive string (Encryption enabled) +def test_6(): + + channel = "test_6-" + str(time.time()) + message = "I am a string" + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub_enc.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive array (Encryption enabled) +def test_7(): + + channel = "test_7-" + str(time.time()) + message = [1,2] + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub_enc.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive json object (Encryption enabled) +def test_8(): + + channel = "test_8-" + str(time.time()) + message = { "a" : "b" } + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub_enc.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive number (Encryption enabled) +def test_9(): + + channel = "test_9-" + str(time.time()) + message = 100 + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub_enc.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive number string (Encryption enabled) +def test_10(): + + channel = "test_10-" + str(time.time()) + message = "100" + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub_enc.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive object string (Encryption enabled) +def test_11(): + + channel = "test_11-" + str(time.time()) + message = '{"a" : "b"}' + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub_enc.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive array string (Encryption enabled) +def test_12(): + + channel = "test_12-" + str(time.time()) + message = '[1,2]' + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + def _cb1(resp,ch=None): + assert resp[0] == 1 + def _err1(resp): + assert False + pubnub_enc.publish(channel,message, callback=_cb1, error=_err1) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +x = 5 +def run_test(t): + global x + x += 5 + i = (x / 5) - 1 + def _print(): + print('Running test ' + str(i)) + pubnub.timeout(x, _print) + pubnub.timeout(x + 1,t) + +def stop(): + pubnub.stop() + +run_test(test_1) +run_test(test_2) +run_test(test_3) +run_test(test_4) +run_test(test_5) +run_test(test_6) +run_test(test_7) +run_test(test_8) +run_test(test_9) +run_test(test_10) +run_test(test_11) +run_test(stop) + +pubnub_enc.start() diff --git a/python-twisted/tests/unit-test-full.py b/python-twisted/tests/unit-test-full.py index c5940af..3aecf12 100644 --- a/python-twisted/tests/unit-test-full.py +++ b/python-twisted/tests/unit-test-full.py @@ -1,4 +1,4 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. +## www.pubnub.com - PubNub Real-time push service in the cloud. # coding=utf8 ## PubNub Real-time Push APIs and Notifications Framework @@ -8,36 +8,33 @@ ## TODO Tests ## ## - wait 20 minutes, send a message, receive and success. -## - -## - -## -## +## - +## - +## +## ## ----------------------------------- ## PubNub 3.1 Real-time Push Cloud API ## ----------------------------------- import sys -sys.path.append('../') -sys.path.append('./') -sys.path.append('../common/') -from Pubnub import Pubnub +from Pubnub import PubnubTwisted as Pubnub -publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' +publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' -secret_key = len(sys.argv) > 3 and sys.argv[3] or None -cipher_key = len(sys.argv) > 4 and sys.argv[4] or None -ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False +secret_key = len(sys.argv) > 3 and sys.argv[3] or None +cipher_key = len(sys.argv) > 4 and sys.argv[4] or None +ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False ## ----------------------------------------------------------------------- ## Command Line Options Supplied PubNub ## ----------------------------------------------------------------------- pubnub_user_supplied_options = Pubnub( - publish_key, ## OPTIONAL (supply None to disable) - subscribe_key, ## REQUIRED - secret_key, ## OPTIONAL (supply None to disable) - cipher_key, ## OPTIONAL (supply None to disable) - ssl_on ## OPTIONAL (supply None to disable) + publish_key, # OPTIONAL (supply None to disable) + subscribe_key, # REQUIRED + secret_key, # OPTIONAL (supply None to disable) + cipher_key, # OPTIONAL (supply None to disable) + ssl_on # OPTIONAL (supply None to disable) ) ## ----------------------------------------------------------------------- @@ -54,15 +51,15 @@ pubnub_high_security = Pubnub( 'sec-c-MTliNDE0NTAtYjY4Ni00MDRkLTllYTItNDhiZGE0N2JlYzBl', ## Cipher Key - 'YWxzamRmbVjFaa05HVnGFqZHM3NXRBS73jxmhVMkjiwVVXV1d5UrXR1JLSkZFRr'+ - 'WVd4emFtUm1iR0TFpUZvbiBoYXMgYmVlbxWkhNaF3uUi8kM0YkJTEVlZYVFjBYi'+ - 'jFkWFIxSkxTa1pGUjd874hjklaTFpUwRVuIFNob3VsZCB5UwRkxUR1J6YVhlQWa'+ - 'V1ZkNGVH32mDkdho3pqtRnRVbTFpUjBaeGUgYXNrZWQtZFoKjda40ZWlyYWl1eX'+ - 'U4RkNtdmNub2l1dHE2TTA1jd84jkdJTbFJXYkZwWlZtRnKkWVrSRhhWbFpZVmFz'+ - 'c2RkZmTFpUpGa1dGSXhTa3hUYTFwR1Vpkm9yIGluZm9ybWFNfdsWQdSiiYXNWVX'+ - 'RSblJWYlRGcFVqQmFlRmRyYUU0MFpXbHlZV2wxZVhVNFJrTnR51YjJsMWRIRTJU'+ - 'W91ciBpbmZvcm1hdGliBzdWJtaXR0ZWQb3UZSBhIHJlc3BvbnNlLCB3ZWxsIHJl'+ - 'VEExWdHVybiB0am0aW9uIb24gYXMgd2UgcG9zc2libHkgY2FuLuhcFe24ldWVns'+ + 'YWxzamRmbVjFaa05HVnGFqZHM3NXRBS73jxmhVMkjiwVVXV1d5UrXR1JLSkZFRr' + + 'WVd4emFtUm1iR0TFpUZvbiBoYXMgYmVlbxWkhNaF3uUi8kM0YkJTEVlZYVFjBYi' + + 'jFkWFIxSkxTa1pGUjd874hjklaTFpUwRVuIFNob3VsZCB5UwRkxUR1J6YVhlQWa' + + 'V1ZkNGVH32mDkdho3pqtRnRVbTFpUjBaeGUgYXNrZWQtZFoKjda40ZWlyYWl1eX' + + 'U4RkNtdmNub2l1dHE2TTA1jd84jkdJTbFJXYkZwWlZtRnKkWVrSRhhWbFpZVmFz' + + 'c2RkZmTFpUpGa1dGSXhTa3hUYTFwR1Vpkm9yIGluZm9ybWFNfdsWQdSiiYXNWVX' + + 'RSblJWYlRGcFVqQmFlRmRyYUU0MFpXbHlZV2wxZVhVNFJrTnR51YjJsMWRIRTJU' + + 'W91ciBpbmZvcm1hdGliBzdWJtaXR0ZWQb3UZSBhIHJlc3BvbnNlLCB3ZWxsIHJl' + + 'VEExWdHVybiB0am0aW9uIb24gYXMgd2UgcG9zc2libHkgY2FuLuhcFe24ldWVns' + 'dSaTFpU3hVUjFKNllWaFdhRmxZUWpCaQo34gcmVxdWlGFzIHNveqQl83snBfVl3', ## 2048bit SSL ON - ENABLED TRUE @@ -72,19 +69,24 @@ pubnub_high_security = Pubnub( ## ----------------------------------------------------------------------- ## Channel | Message Test Data (UTF-8) ## ----------------------------------------------------------------------- -crazy = ' ~`â¦â§!@#$%^&*(顶顅Ȓ)+=[]\\{}|;\':",./<>?abcd' -many_channels = [ str(x) + '-many_channel_test' for x in range(10) ] -runthroughs = 0 -planned_tests = 2 +crazy = ' ~`â¦â§!@#$%^&*(顶顅Ȓ)+=[]\\{}|;\':",./<>?abcd' +many_channels = [str(x) + '-many_channel_test' for x in range(10)] +runthroughs = 0 +planned_tests = 2 delivery_retries = 0 -max_retries = 10 +max_retries = 10 ## ----------------------------------------------------------------------- ## Unit Test Function ## ----------------------------------------------------------------------- -def test( trial, name ) : - if trial : print( 'PASS: ' + name ) - else : print( '- FAIL - ' + name ) + + +def test(trial, name): + if trial: + print('PASS: ' + name) + else: + print('- FAIL - ' + name) + def test_pubnub(pubnub): global runthroughs, planned_tests, delivery_retries, max_retries @@ -94,36 +96,38 @@ def test_pubnub(pubnub): ## ----------------------------------------------------------------------- def phase2(): status = { - 'sent' : 0, - 'received' : 0, - 'connections' : 0 + 'sent': 0, + 'received': 0, + 'connections': 0 } - def received( message, chan ): + def received(message, chan): global runthroughs - test( status['received'] <= status['sent'], 'many sends' ) + test(status['received'] <= status['sent'], 'many sends') status['received'] += 1 - pubnub.unsubscribe({ 'channel' : chan }) + pubnub.unsubscribe({'channel': chan}) if status['received'] == len(many_channels): runthroughs += 1 - if runthroughs == planned_tests: pubnub.stop() + if runthroughs == planned_tests: + pubnub.stop() - def publish_complete( info, chan ): + def publish_complete(info, chan): global delivery_retries, max_retries status['sent'] += 1 - test( info, 'publish complete' ) - test( info and len(info) > 2, 'publish response' ) + test(info, 'publish complete') + test(info and len(info) > 2, 'publish response') if not info[0]: delivery_retries += 1 - if max_retries > delivery_retries: sendit(chan) + if max_retries > delivery_retries: + sendit(chan) def sendit(chan): tchan = chan pubnub.publish({ - 'channel' : chan, - 'message' : "Hello World", - 'callback' : (lambda msg:publish_complete( msg, tchan )) + 'channel': chan, + 'message': "Hello World", + 'callback': (lambda msg: publish_complete(msg, tchan)) }) def connected(chan): @@ -131,88 +135,89 @@ def test_pubnub(pubnub): sendit(chan) def delivered(info): - if info and info[0]: status['sent'] += 1 + if info and info[0]: + status['sent'] += 1 def subscribe(chan): pubnub.subscribe({ - 'channel' : chan, - 'connect' : (lambda:connected(chan+'')), - 'callback' : (lambda msg:received( msg, chan )) + 'channel': chan, + 'connect': (lambda: connected(chan + '')), + 'callback': (lambda msg: received(msg, chan)) }) ## Subscribe All Channels - for chan in many_channels: subscribe(chan) - + for chan in many_channels: + subscribe(chan) + ## ----------------------------------------------------------------------- ## Time Example ## ----------------------------------------------------------------------- def time_complete(timetoken): - test( timetoken, 'timetoken fetch' ) - test( isinstance( timetoken, int ), 'timetoken int type' ) + test(timetoken, 'timetoken fetch') + test(isinstance(timetoken, int), 'timetoken int type') - pubnub.time({ 'callback' : time_complete }) + pubnub.time({'callback': time_complete}) ## ----------------------------------------------------------------------- ## Publish Example ## ----------------------------------------------------------------------- def publish_complete(info): - test( info, 'publish complete' ) - test( info and len(info) > 2, 'publish response' ) + test(info, 'publish complete') + test(info and len(info) > 2, 'publish response') - pubnub.history( { - 'channel' : crazy, - 'limit' : 10, - 'callback' : history_complete + pubnub.history({ + 'channel': crazy, + 'limit': 10, + 'callback': history_complete }) ## ----------------------------------------------------------------------- ## History Example ## ----------------------------------------------------------------------- def history_complete(messages): - test( messages and len(messages) > 0, 'history' ) - test( messages, 'history' ) - + test(messages and len(messages) > 0, 'history') + test(messages, 'history') pubnub.publish({ - 'channel' : crazy, - 'message' : "Hello World", - 'callback' : publish_complete + 'channel': crazy, + 'message': "Hello World", + 'callback': publish_complete }) ## ----------------------------------------------------------------------- ## Subscribe Example ## ----------------------------------------------------------------------- def message_received(message): - test( message, 'message received' ) - pubnub.unsubscribe({ 'channel' : crazy }) + test(message, 'message received') + pubnub.unsubscribe({'channel': crazy}) - def done() : - pubnub.unsubscribe({ 'channel' : crazy }) + def done(): + pubnub.unsubscribe({'channel': crazy}) pubnub.publish({ - 'channel' : crazy, - 'message' : "Hello World", - 'callback' : (lambda x:x) + 'channel': crazy, + 'message': "Hello World", + 'callback': (lambda x: x) }) - def dumpster(message) : - test( 0, 'never see this' ) + def dumpster(message): + test(0, 'never see this') pubnub.subscribe({ - 'channel' : crazy, - 'connect' : done, - 'callback' : dumpster + 'channel': crazy, + 'connect': done, + 'callback': dumpster }) - def connected() : + def connected(): pubnub.publish({ - 'channel' : crazy, - 'message' : { 'Info' : 'Connected!' } + 'channel': crazy, + 'message': {'Info': 'Connected!'} }) pubnub.subscribe({ - 'channel' : crazy, - 'connect' : connected, - 'callback' : message_received + 'channel': crazy, + 'connect': connected, + 'callback': message_received }) phase2() @@ -223,4 +228,3 @@ def test_pubnub(pubnub): test_pubnub(pubnub_user_supplied_options) test_pubnub(pubnub_high_security) pubnub_high_security.start() - diff --git a/python-twisted/tests/unit-tests.py b/python-twisted/tests/unit-tests.py deleted file mode 100644 index f143a3a..0000000 --- a/python-twisted/tests/unit-tests.py +++ /dev/null @@ -1,107 +0,0 @@ - -import sys -import time - -sys.path.append('../../common') -sys.path.append('../common') -sys.path.append('..') -sys.path.append('.') - -from PubnubUnitTest import Suite -from Pubnub import Pubnub - -pubnub = Pubnub("demo","demo") - -tests_count = 1 + 2 + 1 -test_suite = Suite(pubnub,tests_count) - -tests = [] - - - -def test_publish(): - channel = "hello" + str(time.time()) - name = "Publish Test" - def success(r): - test_suite.test(r[0] == 1, name) - - def fail(e): - test_suite.test(False, msg , e) - - - pubnub.publish({ - 'channel' : 'hello', - 'message' : 'hi', - 'callback' : success, - 'error' : fail - }) -tests.append(test_publish) - -#""" -def test_subscribe_publish(): - channel = "hello" + str(time.time()) - name = "Subscribe Publish Test" - publish_msg = "This is Pubnub Python-Twisted" - def connect(): - #print 'connect' - def success(r): - test_suite.test(r[0] == 1, name, "publish success") - - def fail(e): - test_suite.test(False, name , "Publish Failed", e) - - pubnub.publish({ - 'channel' : channel, - 'message' : publish_msg, - 'callback' : success, - 'error' : fail - }) - - def callback(r): - test_suite.test(r == publish_msg, name, "message received") - - pubnub.subscribe({ - 'channel' : channel, - 'callback' : callback, - 'connect' : connect - }) -tests.append(test_subscribe_publish) -#""" - -def test_here_now(): - channel = "hello12" #+ str(time.time()) - name = "Here Now Test" - - def connect(): - print 'connect' - def call_here_now(): - print 'call_here_now' - def success(r): - test_suite.test(r['occupancy'] == 1, name, "Here Now success") - - def fail(e): - test_suite.test(False, name , "Here Now Failed", e) - - pubnub.here_now({ - 'channel' : channel, - 'callback' : success, - 'error' : fail - }) - pubnub.timeout(5, call_here_now) - - def callback(r): - pass - print 'Subscribe' - pubnub.subscribe({ - 'channel' : channel, - 'callback' : callback, - 'connect' : connect - }) -tests.append(test_here_now) - - - - -for t in tests: t() - -pubnub.start() diff --git a/python-twisted/unassembled/Platform.py b/python-twisted/unassembled/Platform.py deleted file mode 100644 index 7318703..0000000 --- a/python-twisted/unassembled/Platform.py +++ /dev/null @@ -1,84 +0,0 @@ -from twisted.web.client import getPage -from twisted.internet import reactor -from twisted.internet.defer import Deferred -from twisted.internet.protocol import Protocol -from twisted.web.client import Agent, ContentDecoderAgent, RedirectAgent, GzipDecoder -from twisted.web.client import HTTPConnectionPool -from twisted.web.http_headers import Headers -from twisted.internet.ssl import ClientContextFactory -from twisted.internet.task import LoopingCall - -pnconn_pool = HTTPConnectionPool(reactor, persistent=True) -pnconn_pool.maxPersistentPerHost = 100 -pnconn_pool.cachedConnectionTimeout = 310 - -class Pubnub(PubnubCoreAsync): - - def start(self): reactor.run() - def stop(self): reactor.stop() - def timeout( self, delay, callback ): - reactor.callLater( delay, callback ) - - def __init__( - self, - publish_key, - subscribe_key, - secret_key = False, - cipher_key = False, - ssl_on = False, - origin = 'pubsub.pubnub.com' - ) : - super(Pubnub, self).__init__( - publish_key=publish_key, - subscribe_key=subscribe_key, - secret_key=secret_key, - cipher_key=cipher_key, - ssl_on=ssl_on, - origin=origin, - ) - self.headers = {} - self.headers['User-Agent'] = ['Python-Twisted'] - #self.headers['Accept-Encoding'] = [self.accept_encoding] - self.headers['V'] = [self.version] - - def _request( self, request, callback ) : - global pnconn_pool - - ## Build URL - ''' - url = self.origin + '/' + "/".join([ - "".join([ ' ~`!@#$%^&*()+=[]\\{}|;\':",./<>?'.find(ch) > -1 and - hex(ord(ch)).replace( '0x', '%' ).upper() or - ch for ch in list(bit) - ]) for bit in request]) - ''' - url = self.getUrl(request) - agent = ContentDecoderAgent(RedirectAgent(Agent( - reactor, - contextFactory = WebClientContextFactory(), - pool = self.ssl and None or pnconn_pool - )), [('gzip', GzipDecoder)]) - request = agent.request( 'GET', url, Headers(self.headers), None ) - - def received(response): - finished = Deferred() - response.deliverBody(PubNubResponse(finished)) - return finished - - def complete(data): - callback(eval(data)) - - request.addCallback(received) - request.addBoth(complete) - -class WebClientContextFactory(ClientContextFactory): - def getContext(self, hostname, port): - return ClientContextFactory.getContext(self) - -class PubNubResponse(Protocol): - def __init__( self, finished ): - self.finished = finished - - def dataReceived( self, bytes ): - self.finished.callback(bytes) - diff --git a/python/Makefile b/python/Makefile deleted file mode 100644 index 5eb9e2f..0000000 --- a/python/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -include ../Makefile.inc - - -.PHONY: all -all: build - -.PHONY: build -build: - cat ../common/LICENSE_HEADER > ./Pubnub.py - echo "\n" >> ./Pubnub.py - cat ../common/PubnubCrypto.py >> ./Pubnub.py - echo "\n" >> ./Pubnub.py - cat ../common/PubnubBase.py >> ./Pubnub.py - echo "\n" >> ./Pubnub.py - cat ../common/PubnubCore.py >> ./Pubnub.py - echo "\n" >> ./Pubnub.py - cat ./unassembled/Platform.py >> ./Pubnub.py - find -name "Pubnub*py" | xargs sed -i "s/PubNub\ [0-9]\.[0-9]\.[0-9]/PubNub\ $(VERSION)/g" - - -.PHONY: clean -clean: - rm -f Pubnub.py* - -.PHONY: test -test: - python tests/detailed-history-unit-test.py - python tests/unit-test.py - diff --git a/python/Pubnub.py b/python/Pubnub.py deleted file mode 100644 index 59a38af..0000000 --- a/python/Pubnub.py +++ /dev/null @@ -1,618 +0,0 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. -# coding=utf8 - -## PubNub Real-time Push APIs and Notifications Framework -## Copyright (c) 2010 Stephen Blum -## http://www.pubnub.com/ - -## ----------------------------------- -## PubNub 3.3.5 Real-time Push Cloud API -## ----------------------------------- - - -from Crypto.Cipher import AES -from Crypto.Hash import MD5 -from base64 import encodestring, decodestring -import hashlib -import hmac - -class PubnubCrypto() : - """ - #** - #* PubnubCrypto - #* - #** - - ## Initiate Class - pc = PubnubCrypto - - """ - - def pad( self, msg, block_size=16 ): - """ - #** - #* pad - #* - #* pad the text to be encrypted - #* appends a padding character to the end of the String - #* until the string has block_size length - #* @return msg with padding. - #** - """ - padding = block_size - (len(msg) % block_size) - return msg + chr(padding)*padding - - def depad( self, msg ): - """ - #** - #* depad - #* - #* depad the decryptet message" - #* @return msg without padding. - #** - """ - return msg[0:-ord(msg[-1])] - - def getSecret( self, key ): - """ - #** - #* getSecret - #* - #* hases the key to MD5 - #* @return key in MD5 format - #** - """ - return hashlib.sha256(key).hexdigest() - - def encrypt( self, key, msg ): - """ - #** - #* encrypt - #* - #* encrypts the message - #* @return message in encrypted format - #** - """ - secret = self.getSecret(key) - Initial16bytes='0123456789012345' - cipher = AES.new(secret[0:32],AES.MODE_CBC,Initial16bytes) - enc = encodestring(cipher.encrypt(self.pad(msg))) - return enc - def decrypt( self, key, msg ): - """ - #** - #* decrypt - #* - #* decrypts the message - #* @return message in decryped format - #** - """ - secret = self.getSecret(key) - Initial16bytes='0123456789012345' - cipher = AES.new(secret[0:32],AES.MODE_CBC,Initial16bytes) - return self.depad((cipher.decrypt(decodestring(msg)))) - - -try: import json -except ImportError: import simplejson as json - -import time -import hashlib -import urllib2 -import uuid - -class PubnubBase(object): - def __init__( - self, - publish_key, - subscribe_key, - secret_key = False, - cipher_key = False, - ssl_on = False, - origin = 'pubsub.pubnub.com', - UUID = None - ) : - """ - #** - #* Pubnub - #* - #* Init the Pubnub Client API - #* - #* @param string publish_key required key to send messages. - #* @param string subscribe_key required key to receive messages. - #* @param string secret_key optional key to sign messages. - #* @param boolean ssl required for 2048 bit encrypted messages. - #* @param string origin PUBNUB Server Origin. - #* @param string pres_uuid optional identifier for presence (auto-generated if not supplied) - #** - - ## Initiat Class - pubnub = Pubnub( 'PUBLISH-KEY', 'SUBSCRIBE-KEY', 'SECRET-KEY', False ) - - """ - self.origin = origin - self.limit = 1800 - self.publish_key = publish_key - self.subscribe_key = subscribe_key - self.secret_key = secret_key - self.cipher_key = cipher_key - self.ssl = ssl_on - self.pc = PubnubCrypto() - - if self.ssl : - self.origin = 'https://' + self.origin - else : - self.origin = 'http://' + self.origin - - self.uuid = UUID or str(uuid.uuid4()) - - if not isinstance(self.uuid, basestring): - raise AttributeError("pres_uuid must be a string") - - def sign(self, channel, message): - ## Sign Message - if self.secret_key: - signature = hashlib.md5('/'.join([ - self.publish_key, - self.subscribe_key, - self.secret_key, - channel, - message - ])).hexdigest() - else: - signature = '0' - return signature - - def encrypt(self, message): - if self.cipher_key: - message = json.dumps(self.pc.encrypt(self.cipher_key, json.dumps(message)).replace('\n','')) - else : - message = json.dumps(message) - - return message; - - def decrypt(self, message): - if self.cipher_key: - message = self.pc.decrypt(self.cipher_key, message) - - return message - - - def publish( self, args ) : - """ - #** - #* Publish - #* - #* Send a message to a channel. - #* - #* @param array args with channel and message. - #* @return array success information. - #** - - ## Publish Example - info = pubnub.publish({ - 'channel' : 'hello_world', - 'message' : { - 'some_text' : 'Hello my World' - } - }) - print(info) - - """ - ## Fail if bad input. - if not (args['channel'] and args['message']) : - return [ 0, 'Missing Channel or Message' ] - - ## Capture User Input - channel = str(args['channel']) - - ## Capture Callback - if args.has_key('callback') : - callback = args['callback'] - else : - callback = None - - #message = json.dumps(args['message'], separators=(',',':')) - message = self.encrypt(args['message']) - - signature = self.sign(channel, message) - - ## Send Message - return self._request({"urlcomponents": [ - 'publish', - self.publish_key, - self.subscribe_key, - signature, - channel, - '0', - message - ]}, callback) - - def presence( self, args ) : - """ - #** - #* presence - #* - #* This is BLOCKING. - #* Listen for presence events on a channel. - #* - #* @param array args with channel and callback. - #* @return false on fail, array on success. - #** - - ## Presence Example - def pres_event(message) : - print(message) - return True - - pubnub.presence({ - 'channel' : 'hello_world', - 'callback' : receive - }) - """ - - ## Fail if missing channel - if not 'channel' in args : - raise Exception('Missing Channel.') - return False - - ## Fail if missing callback - if not 'callback' in args : - raise Exception('Missing Callback.') - return False - - ## Capture User Input - channel = str(args['channel']) - callback = args['callback'] - subscribe_key = args.get('subscribe_key') or self.subscribe_key - - return self.subscribe({'channel': channel+'-pnpres', 'subscribe_key':subscribe_key, 'callback': callback}) - - - def here_now( self, args ) : - """ - #** - #* Here Now - #* - #* Load current occupancy from a channel. - #* - #* @param array args with 'channel'. - #* @return mixed false on fail, array on success. - #* - - ## Presence Example - here_now = pubnub.here_now({ - 'channel' : 'hello_world', - }) - print(here_now['occupancy']) - print(here_now['uuids']) - - """ - channel = str(args['channel']) - - ## Capture Callback - if args.has_key('callback') : - callback = args['callback'] - else : - callback = None - - ## Fail if bad input. - if not channel : - raise Exception('Missing Channel') - return False - - ## Get Presence Here Now - return self._request({"urlcomponents": [ - 'v2','presence', - 'sub_key', self.subscribe_key, - 'channel', channel - ]}, callback); - - - def history( self, args ) : - """ - #** - #* History - #* - #* Load history from a channel. - #* - #* @param array args with 'channel' and 'limit'. - #* @return mixed false on fail, array on success. - #* - - ## History Example - history = pubnub.history({ - 'channel' : 'hello_world', - 'limit' : 1 - }) - print(history) - - """ - ## Capture User Input - limit = args.has_key('limit') and int(args['limit']) or 10 - channel = str(args['channel']) - - ## Fail if bad input. - if not channel : - raise Exception('Missing Channel') - return False - - ## Capture Callback - if args.has_key('callback') : - callback = args['callback'] - else : - callback = None - - ## Get History - return self._request({ "urlcomponents" : [ - 'history', - self.subscribe_key, - channel, - '0', - str(limit) - ] }, callback); - - def detailedHistory(self, args) : - """ - #** - #* Detailed History - #* - #* Load Detailed history from a channel. - #* - #* @param array args with 'channel', optional: 'start', 'end', 'reverse', 'count' - #* @return mixed false on fail, array on success. - #* - - ## History Example - history = pubnub.detailedHistory({ - 'channel' : 'hello_world', - 'count' : 5 - }) - print(history) - - """ - ## Capture User Input - channel = str(args['channel']) - - params = dict() - count = 100 - - if args.has_key('count'): - count = int(args['count']) - - params['count'] = str(count) - - if args.has_key('reverse'): - params['reverse'] = str(args['reverse']).lower() - - if args.has_key('start'): - params['start'] = str(args['start']) - - if args.has_key('end'): - params['end'] = str(args['end']) - - ## Fail if bad input. - if not channel : - raise Exception('Missing Channel') - return False - - ## Capture Callback - if args.has_key('callback') : - callback = args['callback'] - else : - callback = None - - ## Get History - return self._request({ 'urlcomponents' : [ - 'v2', - 'history', - 'sub-key', - self.subscribe_key, - 'channel', - channel, - ],'urlparams' : params }, callback=callback); - - def time(self, args = None) : - """ - #** - #* Time - #* - #* Timestamp from PubNub Cloud. - #* - #* @return int timestamp. - #* - - ## PubNub Server Time Example - timestamp = pubnub.time() - print(timestamp) - - """ - ## Capture Callback - if args and args.has_key('callback') : - callback = args['callback'] - else : - callback = None - time = self._request({'urlcomponents' : [ - 'time', - '0' - ]}, callback) - if time != None: - return time[0] - - - def _encode( self, request ) : - return [ - "".join([ ' ~`!@#$%^&*()+=[]\\{}|;\':",./<>?'.find(ch) > -1 and - hex(ord(ch)).replace( '0x', '%' ).upper() or - ch for ch in list(bit) - ]) for bit in request] - - def getUrl(self,request): - ## Build URL - url = self.origin + '/' + "/".join([ - "".join([ ' ~`!@#$%^&*()+=[]\\{}|;\':",./<>?'.find(ch) > -1 and - hex(ord(ch)).replace( '0x', '%' ).upper() or - ch for ch in list(bit) - ]) for bit in request["urlcomponents"]]) - if (request.has_key("urlparams")): - url = url + '?' + "&".join([ x + "=" + y for x,y in request["urlparams"].iteritems()]) - return url - - -class PubnubCore(PubnubBase): - def __init__( - self, - publish_key, - subscribe_key, - secret_key = False, - cipher_key = False, - ssl_on = False, - origin = 'pubsub.pubnub.com', - uuid = None - ) : - """ - #** - #* Pubnub - #* - #* Init the Pubnub Client API - #* - #* @param string publish_key required key to send messages. - #* @param string subscribe_key required key to receive messages. - #* @param string secret_key optional key to sign messages. - #* @param boolean ssl required for 2048 bit encrypted messages. - #* @param string origin PUBNUB Server Origin. - #* @param string pres_uuid optional identifier for presence (auto-generated if not supplied) - #** - - ## Initiat Class - pubnub = Pubnub( 'PUBLISH-KEY', 'SUBSCRIBE-KEY', 'SECRET-KEY', False ) - - """ - super(PubnubCore, self).__init__( - publish_key=publish_key, - subscribe_key=subscribe_key, - secret_key=secret_key, - cipher_key=cipher_key, - ssl_on=ssl_on, - origin=origin, - UUID=uuid - ) - - self.subscriptions = {} - self.timetoken = 0 - self.version = '3.4' - self.accept_encoding = 'gzip' - - - - def subscribe( self, args ) : - """ - #** - #* Subscribe - #* - #* This is BLOCKING. - #* Listen for a message on a channel. - #* - #* @param array args with channel and callback. - #* @return false on fail, array on success. - #** - - ## Subscribe Example - def receive(message) : - print(message) - return True - - pubnub.subscribe({ - 'channel' : 'hello_world', - 'callback' : receive - }) - - """ - - ## Fail if missing channel - if not 'channel' in args : - raise Exception('Missing Channel.') - return False - - ## Fail if missing callback - if not 'callback' in args : - raise Exception('Missing Callback.') - return False - - ## Capture User Input - channel = str(args['channel']) - callback = args['callback'] - subscribe_key = args.get('subscribe_key') or self.subscribe_key - - ## Begin Subscribe - while True : - - timetoken = 'timetoken' in args and args['timetoken'] or 0 - try : - ## Wait for Message - response = self._request({"urlcomponents" : [ - 'subscribe', - subscribe_key, - channel, - '0', - str(timetoken) - ],"urlparams" : {"uuid" : self.uuid }}) - - messages = response[0] - args['timetoken'] = response[1] - - ## If it was a timeout - if not len(messages) : - continue - - ## Run user Callback and Reconnect if user permits. - for message in messages : - if not callback(self.decrypt(message)) : - return - - except Exception: - time.sleep(1) - - return True - - - -class Pubnub(PubnubCore): - def __init__( - self, - publish_key, - subscribe_key, - secret_key = False, - cipher_key = False, - ssl_on = False, - origin = 'pubsub.pubnub.com', - pres_uuid = None - ) : - super(Pubnub, self).__init__( - publish_key = publish_key, - subscribe_key = subscribe_key, - secret_key = secret_key, - cipher_key = cipher_key, - ssl_on = ssl_on, - origin = origin, - uuid = pres_uuid - ) - - def _request( self, request, callback = None ) : - ## Build URL - url = self.getUrl(request) - - ## Send Request Expecting JSONP Response - try: - try: usock = urllib2.urlopen( url, None, 310 ) - except TypeError: usock = urllib2.urlopen( url, None ) - response = usock.read() - usock.close() - resp_json = json.loads(response) - except: - return None - - if (callback): - callback(resp_json) - else: - return resp_json diff --git a/python/README.md b/python/README.md index 68065f0..c077918 100644 --- a/python/README.md +++ b/python/README.md @@ -1,60 +1,93 @@ -## PubNub 3.3 Web Data Push Cloud-hosted API - PYTHON -#### www.pubnub.com - PubNub Web Data Push Service in the Cloud. -#### http://github.com/pubnub/python +## Contact support@pubnub.com for all questions +#### [PubNub](http://www.pubnub.com) Real-time Data Network +##### Standalone Python Client #### Init ``` -pubnub = Pubnub( - "demo", ## PUBLISH_KEY - "demo", ## SUBSCRIBE_KEY - None, ## SECRET_KEY - False ## SSL_ON? -) +pubnub = Pubnub(publish_key="demo", subscribe_key="demo", ssl_on=False) + ``` #### PUBLISH ``` -info = pubnub.publish({ - 'channel' : 'hello_world', - 'message' : { - 'some_text' : 'Hello my World' - } -}) -print(info) +channel = 'hello_world' +message = 'Hello World !!!' + +# Synchronous usage +print pubnub.publish(channel='hello_world', message='Hello World !!!') + +# Asynchronous usage + +def callback(message): + print(message) + +pubnub.publish(channel, message, callback=callback, error=callback) + ``` #### SUBSCRIBE ``` -# Listen for Messages *BLOCKING* -def receive(message) : +# Listen for Messages + +channel = 'hello_world' + +def callback(message, channel): print(message) - return True -pubnub.subscribe({ - 'channel' : 'hello_world', - 'callback' : receive -}) + +def error(message): + print("ERROR : " + str(message)) + + +def connect(message): + print("CONNECTED") + + +def reconnect(message): + print("RECONNECTED") + + +def disconnect(message): + print("DISCONNECTED") + + +pubnub.subscribe(channel, callback=callback, error=callback, + connect=connect, reconnect=reconnect, disconnect=disconnect) +``` + +#### UNSUBSCRIBE + +``` +# Listen for Messages + +channel = 'hello_world' + +pubnub.unsubscribe(channel=channel) ``` #### PRESENCE ``` -# Listen for Presence Event Messages *BLOCKING* +# Listen for Presence Event Messages + +channel = 'hello_world' -def pres_event(message) : +def callback(message, channel): print(message) - return True -pubnub.presence({ - 'channel' : 'hello_world', - 'callback' : receive -}) + +def error(message): + print("ERROR : " + str(message)) + + + +pubnub.presence(channel, callback=callback, error=callback) ``` #### HERE_NOW @@ -62,36 +95,33 @@ pubnub.presence({ ``` # Get info on who is here right now! -here_now = pubnub.here_now({ - 'channel' : 'hello_world', -}) +channel = 'hello_world' -print(here_now['occupancy']) -print(here_now['uuids']) -``` +# Synchronous usage +print pubnub.here_now(channel) -#### Channel Analytics -``` -analytics = pubnub.analytics({ - 'channel' : 'channel-name-here', ## Leave blank for all channels - 'limit' : 100, ## aggregation range - 'ago' : 0, ## minutes ago to look backward - 'duration' : 100 ## minutes offset -}) -print(analytics) +# Asynchronous usage + +def callback(message): + print(message) +pubnub.here_now(channel, callback=callback, error=callback) ``` #### HISTORY ``` -# Load Previously Published Messages -history = pubnub.detailedHistory({ - 'channel' : 'my_channel', - 'end' : my_end_time_token, # Optional - 'start' : my_start_time_token, # Optional - 'count' : num_of_msgs_to_return # Optional, default is 100 -}) -print(history) +# Synchronous usage + +print pubnub.history(channel, count=2) + +# Asynchronous usage + + +def callback(message): + print(message) + +pubnub.history(channel, count=2, callback=callback, error=callback) ``` +## Contact support@pubnub.com for all questions diff --git a/python/examples/config b/python/examples/config new file mode 100644 index 0000000..f35134f --- /dev/null +++ b/python/examples/config @@ -0,0 +1,9 @@ +sessionname pubnub-console +screen -t output tail -f ./pubnub-console.log +split +focus down +screen -t console python console.py "set_output_file" +split -v +focus down +screen -t help vi -R ./console-help.txt +focus up diff --git a/python/examples/config_osx b/python/examples/config_osx new file mode 100644 index 0000000..cdb186c --- /dev/null +++ b/python/examples/config_osx @@ -0,0 +1,8 @@ +sessionname pubnub-console +screen -t help vi -R ./console-help.txt +split +focus down +screen -t output tail -f ./pubnub-console.log +split +focus down +screen -t console python console.py "set_output_file" diff --git a/python/examples/console-help.txt b/python/examples/console-help.txt new file mode 100644 index 0000000..abe92c8 --- /dev/null +++ b/python/examples/console-help.txt @@ -0,0 +1,37 @@ +********************** HELP ****************************** + +TO EXIT : +Ctrl-A \ followed by y ( on linux ) +Ctrl-A Ctrl-\ followed by y ( on mac osx ) + +TO MOVE BETWEEN PANES . Ctrl-A TAB + +********************************************************** + +PUBLISH + +Usage: publish [options] arg + +Options: + -h, --help show this help message and exit + -c CHANNEL, --channel=CHANNEL + Channel on which to publish + +Examples: + (1) publish -c hello_world hi how r u + (2) pub -c hello_world [1,2] + + + +SUBSCRIBE + +Usage: subscribe [options] arg + +Options: + -h, --help show this help message and exit + -c CHANNEL, --channel=CHANNEL + Channel for subscribe + +Examples: + (1) subscribe -c hello_world + (2) sub -c hello_world
\ No newline at end of file diff --git a/python/examples/console.py b/python/examples/console.py new file mode 100644 index 0000000..bf82b5f --- /dev/null +++ b/python/examples/console.py @@ -0,0 +1,689 @@ +## www.pubnub.com - PubNub Real-time push service in the cloud. +# coding=utf8 + +## PubNub Real-time Push APIs and Notifications Framework +## Copyright (c) 2010 Stephen Blum +## http://www.pubnub.com/ + + +import sys +from Pubnub import Pubnub +import threading +from datetime import datetime + +from cmd2 import Cmd, make_option, options, Cmd2TestCase +import optparse +import json + +import atexit +import os +import readline +import rlcompleter + +import pygments +from pygments.lexers import JsonLexer +from pygments.formatters import TerminalFormatter + +lexer = JsonLexer() +formatter = TerminalFormatter() +def highlight(msg): + return pygments.highlight(msg, lexer, formatter) + + + +historyPath = os.path.expanduser("~/.pubnub_console_history") + + +def save_history(historyPath=historyPath): + import readline + readline.write_history_file(historyPath) + +if os.path.exists(historyPath): + readline.read_history_file(historyPath) + +atexit.register(save_history) + +of = sys.stdout + +color = Cmd() + +stop = None + +full_date = False + + +def stop_2(th): + th._Thread__stop() + + +def stop_3(th): + th._stop() + + +def print_console_2(of, message): + print >>of, message + + +def print_console_3(of, message): + of.write(message) + of.write("\n") + +print_console = None + +if type(sys.version_info) is tuple: + print_console = print_console_2 + stop = stop_2 +else: + if sys.version_info.major == 2: + print_console = print_console_2 + stop = stop_2 + else: + print_console = print_console_3 + stop = stop_3 + + +def get_date(): + if full_date is True: + return color.colorize(datetime.now().strftime( + '%Y-%m-%d %H:%M:%S'), "magenta") + else: + return color.colorize(datetime.now().strftime( + '%H:%M:%S'), "magenta") + +def print_ok_normal(msg, channel=None): + if msg is None: + return + chstr = color.colorize("[" + get_date() + "] ", "magenta") + chstr += color.colorize("[Channel : " + channel + + "] " if channel is not None else "", "cyan") + try: + print_console(of, (chstr + color.colorize(str(msg), "green"))) + except UnicodeEncodeError as e: + print_console(of, (msg)) + + of.flush() + + +def print_error_normal(msg, channel=None): + if msg is None: + return + chstr = color.colorize("[" + get_date() + "] ", "magenta") + chstr += color.colorize("[Channel : " + channel + + "] " if channel is not None else "", "cyan") + try: + print_console(of, (chstr + color.colorize(color.colorize( + str(msg), "red"), "bold"))) + except UnicodeEncodeError as e: + print_console(of, (msg)) + of.flush() + +def print_ok_pretty(msg, channel=None): + if msg is None: + return + chstr = color.colorize("[" + get_date() + "] ", "magenta") + chstr += color.colorize("[Channel : " + channel + + "] " if channel is not None else "", "cyan") + try: + print_console(of, (chstr + highlight(json.dumps(msg, indent=2)))) + except UnicodeEncodeError as e: + print_console(of, (msg)) + + of.flush() + + +def print_error_pretty(msg, channel=None): + if msg is None: + return + chstr = color.colorize("[" + get_date() + "] ", "magenta") + chstr += color.colorize("[Channel : " + channel + + "] " if channel is not None else "", "cyan") + try: + print_console(of, (chstr + color.colorize(color.colorize( + "ERROR: ", "red"), "bold") + + highlight(json.dumps(msg, indent=2)))) + except UnicodeEncodeError as e: + print_console(of, (msg)) + of.flush() + +print_ok = print_ok_pretty +print_error = print_error_pretty + + +class DefaultPubnub(object): + def handlerFunctionClosure(self, name): + def handlerFunction(*args, **kwargs): + print_error("Pubnub not initialized." + + "Use init command to initialize") + return handlerFunction + + def __getattr__(self, name): + return self.handlerFunctionClosure(name) + +pubnub = DefaultPubnub() + + +def kill_all_threads(): + for thread in threading.enumerate(): + if thread.isAlive(): + stop(thread) + + +def get_input(message, t=None): + while True: + try: + try: + command = raw_input(message) + except NameError: + command = input(message) + except KeyboardInterrupt: + return None + + command = command.strip() + + if command is None or len(command) == 0: + raise ValueError + + if t is not None and t == bool: + valid = ["True", "true", "1", 1, "y", "Y", "yes", "Yes", "YES"] + if command in valid: + return True + else: + return False + if t is not None: + command = t(command) + else: + command = eval("'" + command + "'") + + return command + except ValueError: + print_error("Invalid input : " + command) + + +def _publish_command_handler(channel, message, async=False): + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + print_ok(pubnub.publish(channel, message, + _callback if async is True else None, + _error if async is True else None)) + + +def _subscribe_command_handler(channel): + + def _callback(r, ch): + print_ok(r, ch) + + def _error(r, ch=None): + print_error(r, ch if ch is not None else channel) + + def _disconnect(r): + print_error("DISCONNECTED", r) + + def _reconnect(r): + print_error("RECONNECTED", r) + + def _connect(r): + print_error("CONNECTED", r) + + pubnub.subscribe(channel, _callback, _error, connect=_connect, + disconnect=_disconnect, reconnect=_reconnect) + + +def _unsubscribe_command_handler(channels): + + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + if not isinstance(channels, list): + ch = [] + ch.append(channels) + channels = ch + + for channel in channels: + pubnub.unsubscribe(channel) + pubnub.unsubscribe(channel + '-pnpres') + print_ok('Unsubscribed from : ' + str(channels)) + + +def _grant_command_handler(channel, auth_key, read, write, ttl, async=False): + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + + print_ok(pubnub.grant(channel, auth_key, + read, write, ttl, + _callback if async is True else None, + _error if async is True else None)) + + +def _revoke_command_handler(channel, auth_key, ttl, async=False): + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + + print_ok(pubnub.revoke(channel, auth_key, ttl, + _callback if async is True else None, + _error if async is True else None)) + + +def _audit_command_handler(channel, auth_key, async=False): + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + + print_ok(pubnub.audit(channel, auth_key, + _callback if async is True else None, + _error if async is True else None)) + + +def _history_command_handler(channel, count, async=False): + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + + print_ok(pubnub.history(channel, count, + _callback if async is True else None, + _error if async is True else None)) + + +def _here_now_command_handler(channel, async=False): + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + + print_ok(pubnub.here_now(channel, _callback if async is True else None, + _error if async is True else None)) + + +def kill_all_threads(): + for thread in threading.enumerate(): + if thread.isAlive(): + stop(thread) + + +def get_channel_array(): + channels = pubnub.get_channel_array() + + for channel in channels: + if "-pnpres" in channel: + i = channels.index(channel.split("-pnpres")[0]) + channels[i] = channels[i] + color.colorize("(P)", "blue") + channels.remove(channel) + return channels + + +class DevConsole(Cmd): + def __init__(self): + Cmd.__init__(self) + global pubnub + self.intro = "For Help type ? or help . " + \ + "To quit/exit type exit" + self.default_channel = None + self.async = False + pubnub = Pubnub("demo", "demo") + self.channel_truncation = 3 + self.prompt = self.get_prompt() + self.publish_key = "demo" + self.subscribe_key = "demo" + self.origin = "pubsub.pubnub.com" + self.auth_key = None + self.cipher_key = None + self.secret_key = "demo" + self.ssl = False + self.uuid = None + self.disable_pretty = False + + def get_channel_origin(self): + cho = " [" + channels = get_channel_array() + channels_str = ",".join(channels) + sl = self.channel_truncation + if len(channels) > int(sl) and int(sl) > 0: + cho += ",".join(channels[:int(sl)]) + " " + str( + len(channels) - int(sl)) + " more..." + else: + cho += ",".join(channels) + + if len(channels) > 0: + cho = color.colorize(cho, "bold") + "@" + + origin = pubnub.get_origin().split("://")[1] + origin += color.colorize(" (SSL)", "green") if pubnub.get_origin( + ).split("://")[0] == "https" else "" + return cho + color.colorize(origin, "blue") + "] > " + + def get_prompt(self): + prompt = "[" + get_date() + "]" + + if self.default_channel is not None and len(self.default_channel) > 0: + prompt += " [default channel: " + color.colorize( + self.default_channel, "bold") + "]" + + prompt += self.get_channel_origin() + return prompt + + def precmd(self, line): + self.prompt = self.get_prompt() + return line + + #def emptyline(self): + # self.prompt = self.get_prompt() + + def cmdloop_with_keyboard_interrupt(self): + try: + self.cmdloop() + except KeyboardInterrupt as e: + pass + sys.stdout.write('\n') + kill_all_threads() + + @options([make_option('-p', '--publish-key', action="store", + default=None, help="Publish Key"), + make_option('-s', '--subscribe-key', action="store", + default=None, help="Subscribe Key"), + make_option('-k', '--secret-key', action="store", + default=None, help="cipher Key"), + make_option('-c', '--cipher-key', action="store", + default=None, help="Secret Key"), + make_option('-a', '--auth-key', action="store", + default=None, help="Auth Key"), + make_option('--ssl-on', dest='ssl', action='store_true', + default=False, help="SSL Enabled ?"), + make_option('-o', '--origin', action="store", + default=None, help="Origin"), + make_option('-u', '--uuid', action="store", + default=None, help="UUID"), + make_option('--disable-pretty-print', dest='disable_pretty', action='store_true', + default=False, help="Disable Pretty Print ?") + ]) + def do_init(self, command, opts): + global pubnub + global print_ok + global print_error + global print_ok_normal + global print_error_normal + global print_error_pretty + global print_ok_pretty + + self.publish_key = opts.publish_key if opts.publish_key is not None else self.publish_key + self.subscribe_key = opts.subscribe_key if opts.subscribe_key is not None else self.subscribe_key + self.secret_key = opts.secret_key if opts.secret_key is not None else self.secret_key + self.cipher_key = opts.cipher_key if opts.cipher_key is not None else self.cipher_key + self.auth_key = opts.auth_key if opts.auth_key is not None else self.auth_key + self.origin = opts.origin if opts.origin is not None else self.origin + self.uuid = opts.uuid if opts.uuid is not None else self.uuid + self.ssl = opts.ssl if opts.ssl is not None else self.ssl + self.disable_pretty = opts.disable_pretty if opts.disable_pretty is not None else self.disable_pretty + + pubnub = Pubnub(self.publish_key, + self.subscribe_key, + self.secret_key, + self.cipher_key, + self.auth_key, + self.ssl, + self.origin, + self.uuid) + self.prompt = self.get_prompt() + + if opts.disable_pretty is True: + print_ok = print_ok_normal + print_error = print_error_normal + else: + print_ok = print_ok_pretty + print_error = print_error_pretty + + def do_set_sync(self, command): + """unset_async + Unset Async mode""" + self.async = False + + def do_set_async(self, command): + """set_async + Set Async mode""" + self.async = True + + @options([make_option('-n', '--count', action="store", + default=3, help="Number of channels on prompt") + ]) + def do_set_channel_truncation(self, command, opts): + """set_channel_truncation + Set Channel Truncation""" + + self.channel_truncation = opts.count + + self.prompt = self.get_prompt() + + def do_unset_channel_truncation(self, command): + """unset_channel_truncation + Unset Channel Truncation""" + self.channel_truncation = 0 + self.prompt = self.get_prompt() + + def do_set_full_date(self, command): + global full_date + """do_set_full_date + Set Full Date""" + full_date = True + self.prompt = self.get_prompt() + + def do_unset_full_date(self, command): + global full_date + """do_unset_full_date + Unset Full Date""" + full_date = False + self.prompt = self.get_prompt() + + @options([make_option('-c', '--channel', + action="store", help="Default Channel") + ]) + def do_set_default_channel(self, command, opts): + + if opts.channel is None: + print_error("Missing channel") + return + self.default_channel = opts.channel + self.prompt = self.get_prompt() + + @options([make_option('-f', '--file', action="store", + default="./pubnub-console.log", help="Output file") + ]) + def do_set_output_file(self, command, opts): + global of + try: + of = file(opts.file, 'w+') + except IOError as e: + print_error("Could not set output file. " + e.reason) + + @options([make_option('-c', '--channel', action="store", + help="Channel for here now data") + ]) + def do_here_now(self, command, opts): + opts.channel = self.default_channel \ + if opts.channel is None else opts.channel + if opts.channel is None: + print_error("Missing channel") + return + + _here_now_command_handler(opts.channel, async=self.async) + + @options([make_option('-c', '--channel', action="store", + help="Channel for history data"), + make_option('-n', '--count', action="store", + default=5, help="Number of messages") + ]) + def do_get_history(self, command, opts): + opts.channel = self.default_channel \ + if opts.channel is None else opts.channel + if opts.channel is None: + print_error("Missing channel") + return + + _history_command_handler(opts.channel, opts.count, async=self.async) + + @options([make_option('-c', '--channel', action="store", + help="Channel on which to publish") + ]) + def do_publish(self, command, opts): + opts.channel = self.default_channel \ + if opts.channel is None else opts.channel + if opts.channel is None: + print_error("Missing channel") + return + + if command is None: + print_error("Missing message") + return + + try: + message = json.loads(str(command)) + except ValueError as ve: + message = str(command) + + _publish_command_handler(opts.channel, message, async=self.async) + + @options([make_option('-c', '--channel', action="store", + help="Channel on which to grant"), + make_option('-a', '--auth-key', dest="auth_key", + action="store", + help="Auth Key"), + make_option('-r', '--read-enabled', dest='read', + action='store_true', + default=False, help="Read ?"), + make_option('-w', '--write-enabled', dest='write', + action='store_true', + default=False, help="Write ?"), + make_option('-t', '--ttl', action="store", + default=5, help="TTL"), + make_option('-p', '--presence', action="store_true", + dest="presence", + default=False, help="Grant on presence channel ?") + ]) + def do_grant(self, command, opts): + opts.channel = self.default_channel \ + if opts.channel is None else opts.channel + + opts.auth_key = pubnub.auth_key \ + if opts.auth_key is None else opts.auth_key + + _grant_command_handler(opts.channel, opts.auth_key, + opts.read, opts.write, + opts.ttl, async=self.async) + + if opts.presence is True: + _grant_command_handler(opts.channel + '-pnpres', opts.auth_key, + opts.read, opts.write, + opts.ttl, async=self.async) + + @options([make_option('-c', '--channel', action="store", + help="Channel on which to revoke"), + make_option('-a', '--auth-key', dest="auth_key", action="store", + help="Auth Key"), + make_option('-t', '--ttl', action="store", + default=5, help="TTL"), + make_option('-p', '--presence', action="store_true", + dest="presence", + default=False, help="Revoke on presence channel ?") + ]) + def do_revoke(self, command, opts): + opts.channel = self.default_channel \ + if opts.channel is None else opts.channel + + opts.auth_key = pubnub.auth_key \ + if opts.auth_key is None else opts.auth_key + + _revoke_command_handler( + opts.channel, opts.auth_key, opts.ttl, async=self.async) + + if opts.presence is True: + _revoke_command_handler( + opts.channel + '-pnpres', opts.auth_key, + opts.ttl, async=self.async) + + @options([make_option('-c', '--channel', action="store", + help="Channel on which to revoke"), + make_option('-a', '--auth-key', dest="auth_key", action="store", + help="Auth Key") + ]) + def do_audit(self, command, opts): + opts.channel = self.default_channel \ + if opts.channel is None else opts.channel + + opts.auth_key = pubnub.auth_key \ + if opts.auth_key is None else opts.auth_key + + _audit_command_handler(opts.channel, opts.auth_key, async=self.async) + + @options([make_option('-c', '--channel', action="store", + help="Channel for unsubscribe"), + make_option('-a', '--all', action="store_true", dest="all", + default=False, help="Unsubscribe from all channels") + ]) + def do_unsubscribe(self, command, opts): + opts.channel = self.default_channel \ + if opts.channel is None else opts.channel + if (opts.all is True): + opts.channel = pubnub.get_channel_array() + if opts.channel is None: + print_error("Missing channel") + return + _unsubscribe_command_handler(opts.channel) + self.prompt = self.get_prompt() + + @options([make_option('-c', '--channel', action="store", + help="Channel for subscribe"), + make_option('-g', '--get-channel-list', action="store_true", + dest="get", + default=False, help="Get susbcribed channel list"), + make_option('-p', '--presence', action="store_true", + dest="presence", + default=False, help="Presence events ?") + ]) + def do_subscribe(self, command, opts): + opts.channel = self.default_channel \ + if opts.channel is None else opts.channel + if opts is None: + print_error("Missing argument") + return + + if opts.channel is not None: + _subscribe_command_handler(opts.channel) + + if opts.presence is True: + _subscribe_command_handler(opts.channel + '-pnpres') + + if opts.get is True: + print_ok(get_channel_array()) + self.prompt = self.get_prompt() + + def do_exit(self, args): + kill_all_threads() + return -1 + + #def do_EOF(self, args): + # kill_all_threads() + # return self.do_exit(args) + + #def handler(self, signum, frame): + # kill_all_threads() + + +def main(): + app = DevConsole() + app.cmdloop_with_keyboard_interrupt() + +if __name__ == "__main__": + main() diff --git a/python/examples/dev-console.py b/python/examples/dev-console.py new file mode 100755 index 0000000..134d2e7 --- /dev/null +++ b/python/examples/dev-console.py @@ -0,0 +1,278 @@ +## www.pubnub.com - PubNub Real-time push service in the cloud. +# coding=utf8 + +## PubNub Real-time Push APIs and Notifications Framework +## Copyright (c) 2010 Stephen Blum +## http://www.pubnub.com/ + +import sys +from Pubnub import Pubnub + +from optparse import OptionParser + + +parser = OptionParser() + +parser.add_option("--publish-key", + dest="publish_key", default="demo", + help="Publish Key ( default : 'demo' )") + +parser.add_option("--subscribe-key", + dest="subscribe_key", default="demo", + help="Subscribe Key ( default : 'demo' )") + +parser.add_option("--secret-key", + dest="secret_key", default="demo", + help="Secret Key ( default : 'demo' )") + +parser.add_option("--cipher-key", + dest="cipher_key", default="", + help="Cipher Key") + +parser.add_option("--auth-key", + dest="auth_key", default=None, + help="Auth Key") + +parser.add_option("--origin", + dest="origin", default="pubsub.pubnub.com", + help="Origin ( default: pubsub.pubnub.com )") + +parser.add_option("--ssl-on", + action="store_false", dest="ssl", default=False, + help="SSL") + +parser.add_option("--uuid", + dest="uuid", default=None, + help="UUID") + +(options, args) = parser.parse_args() + +print(options) + +pubnub = Pubnub(options.publish_key, + options.subscribe_key, + options.secret_key, + options.cipher_key, + options.auth_key, + options.ssl, + options.origin, + options.uuid) + + +class color(object): + PURPLE = '\033[95m' + CYAN = '\033[96m' + DARKCYAN = '\033[36m' + BLUE = '\033[94m' + GREEN = '\033[92m' + YELLOW = '\033[93m' + RED = '\033[91m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + END = '\033[0m' + +from datetime import datetime + + +def print_ok(msg, channel=None): + chstr = color.PURPLE + "[" + datetime.now().strftime( + '%Y-%m-%d %H:%M:%S') + "] " + color.END + chstr += color.CYAN + "[Channel : " + channel + \ + "] " if channel is not None else "" + color.END + try: + print(chstr + color.GREEN + str(msg) + color.END) + except UnicodeEncodeError as e: + print(msg) + + +def print_error(msg, channel=None): + chstr = color.PURPLE + "[" + datetime.now().strftime( + '%Y-%m-%d %H:%M:%S') + "] " + color.END + chstr += color.CYAN + "[Channel : " + channel + \ + "] " if channel is not None else "" + color.END + try: + print(chstr + color.RED + color.BOLD + str(msg) + color.END) + except UnicodeEncodeError as e: + print(msg) + +import threading + + +def kill_all_threads(): + for thread in threading.enumerate(): + if thread.isAlive(): + thread._Thread__stop() + + +def get_input(message, t=None): + while True: + try: + try: + command = raw_input(message) + except NameError: + command = input(message) + except KeyboardInterrupt: + return None + + command = command.strip() + + if command is None or len(command) == 0: + raise ValueError + + if t is not None and t == bool: + valid = ["True", "true", "1", 1, "y", "Y", "yes", "Yes", "YES"] + if command in valid: + return True + else: + return False + if t is not None: + command = t(command) + else: + command = eval("'" + command + "'") + + return command + except ValueError: + print_error("Invalid input : " + command) + + +def _publish_command_handler(): + + channel = get_input("[PUBLISH] Enter Channel Name ", str) + if channel is None: + return + while True: + message = get_input("[PUBLISH] Enter Message \ + ( QUIT or CTRL-C for exit from publish mode ) ") + if message == 'QUIT' or message == 'quit' or message is None: + return + + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + pubnub.publish(channel, message, _callback, _error) + + +def _subscribe_command_handler(): + channel = get_input("[SUBSCRIBE] Enter Channel Name ", str) + + def _callback(r): + print_ok(r, channel) + + def _error(r): + print_error(r, channel) + pubnub.subscribe(channel, _callback, _error) + + +def _unsubscribe_command_handler(): + channel = get_input("[UNSUBSCRIBE] Enter Channel Name ", str) + + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + pubnub.unsubscribe(channel) + + +def _grant_command_handler(): + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + channel = get_input("[GRANT] Enter Channel Name ", str) + auth_key = get_input("[GRANT] Enter Auth Key ", str) + ttl = get_input("[GRANT] Enter ttl ", int) + read = get_input("[GRANT] Read ? ", bool) + write = get_input("[GRANT] Write ? ", bool) + pubnub.grant(channel, auth_key, read, write, ttl, _callback) + + +def _revoke_command_handler(): + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + channel = get_input("[REVOKE] Enter Channel Name ", str) + auth_key = get_input("[REVOKE] Enter Auth Key ", str) + ttl = get_input("[REVOKE] Enter ttl ", int) + + pubnub.revoke(channel, auth_key, ttl, _callback) + + +def _audit_command_handler(): + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + channel = get_input("[AUDIT] Enter Channel Name ", str) + auth_key = get_input("[AUDIT] Enter Auth Key ", str) + pubnub.audit(channel, auth_key, _callback) + + +def _history_command_handler(): + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + channel = get_input("[HISTORY] Enter Channel Name ", str) + count = get_input("[HISTORY] Enter Count ", int) + + pubnub.history(channel, count, callback=_callback, error=_error) + + +def _here_now_command_handler(): + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + channel = get_input("[HERE NOW] Enter Channel Name ", str) + + pubnub.here_now(channel, callback=_callback, error=_error) + + +commands = [] +commands.append({"command": "publish", "handler": _publish_command_handler}) +commands.append( + {"command": "subscribe", "handler": _subscribe_command_handler}) +commands.append( + {"command": "unsubscribe", "handler": _unsubscribe_command_handler}) +commands.append( + {"command": "here_now", "handler": _here_now_command_handler}) +commands.append({"command": "history", "handler": _history_command_handler}) +commands.append({"command": "grant", "handler": _grant_command_handler}) +commands.append({"command": "revoke", "handler": _revoke_command_handler}) +commands.append({"command": "audit", "handler": _audit_command_handler}) + +# last command is quit. add new commands before this line +commands.append({"command": "QUIT"}) + + +def get_help(): + help = "" + help += "Channels currently subscribed to : " + help += str(pubnub.get_channel_array()) + help += "\n" + for i, v in enumerate(commands): + help += "Enter " + str(i) + " for " + v['command'] + "\n" + return help + + +while True: + command = get_input(color.BLUE + get_help(), int) + if command == len(commands) - 1 or command is None: + kill_all_threads() + break + if command >= len(commands): + print_error("Invalid input " + str(command)) + continue + + commands[command]['handler']() + +#pubnub.start() diff --git a/python/examples/here-now-example.py b/python/examples/here-now-example.py deleted file mode 100644 index d2ca9bd..0000000 --- a/python/examples/here-now-example.py +++ /dev/null @@ -1,37 +0,0 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. -# coding=utf8 - -## PubNub Real-time Push APIs and Notifications Framework -## Copyright (c) 2010 Stephen Blum -## http://www.pubnub.com/ - -## ----------------------------------- -## PubNub 3.1 Real-time Push Cloud API -## ----------------------------------- - -import sys -sys.path.append('../') -from twisted.internet import reactor -from Pubnub import Pubnub - -publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' -subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' -secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' -cipher_key = len(sys.argv) > 4 and sys.argv[4] or '' -ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False - -## ----------------------------------------------------------------------- -## Initiate Pubnub State -## ----------------------------------------------------------------------- -pubnub = Pubnub( publish_key=publish_key, subscribe_key=subscribe_key, - secret_key=secret_key, cipher_key=cipher_key, ssl_on=ssl_on) -crazy = 'hello_world' - -def print_cb(message): - print message - -pubnub.here_now( { - 'channel' : crazy, - 'callback' : print_cb -}) - diff --git a/python/examples/here-now.py b/python/examples/here-now.py new file mode 100644 index 0000000..9640cc5 --- /dev/null +++ b/python/examples/here-now.py @@ -0,0 +1,35 @@ +## www.pubnub.com - PubNub Real-time push service in the cloud. +# coding=utf8 + +## PubNub Real-time Push APIs and Notifications Framework +## Copyright (c) 2010 Stephen Blum +## http://www.pubnub.com/ + + +import sys +from Pubnub import Pubnub + +publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' +subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' +secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' +cipher_key = len(sys.argv) > 4 and sys.argv[4] or '' +ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False + +## ----------------------------------------------------------------------- +## Initiate Pubnub State +## ----------------------------------------------------------------------- +pubnub = Pubnub(publish_key=publish_key, subscribe_key=subscribe_key, + secret_key=secret_key, cipher_key=cipher_key, ssl_on=ssl_on) +channel = 'hello_world' + + +# Synchronous usage +print pubnub.here_now(channel) + +# Asynchronous usage + + +def callback(message): + print(message) + +pubnub.here_now(channel, callback=callback, error=callback) diff --git a/python/examples/history-example.py b/python/examples/history-example.py deleted file mode 100755 index c7c9547..0000000 --- a/python/examples/history-example.py +++ /dev/null @@ -1,14 +0,0 @@ -import sys -sys.path.append('../') -from Pubnub import Pubnub - -## Initiat Class -pubnub = Pubnub( 'demo', 'demo', None, False ) - -## History Example -history = pubnub.history({ - 'channel' : 'hello_world', - 'limit' : 1 -}) -print(history) - diff --git a/python/examples/history.py b/python/examples/history.py new file mode 100644 index 0000000..603a0f8 --- /dev/null +++ b/python/examples/history.py @@ -0,0 +1,35 @@ +## www.pubnub.com - PubNub Real-time push service in the cloud. +# coding=utf8 + +## PubNub Real-time Push APIs and Notifications Framework +## Copyright (c) 2010 Stephen Blum +## http://www.pubnub.com/ + + +import sys +from Pubnub import Pubnub + +publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' +subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' +secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' +cipher_key = len(sys.argv) > 4 and sys.argv[4] or '' +ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False + +## ----------------------------------------------------------------------- +## Initiate Pubnub State +## ----------------------------------------------------------------------- +pubnub = Pubnub(publish_key=publish_key, subscribe_key=subscribe_key, + secret_key=secret_key, cipher_key=cipher_key, ssl_on=ssl_on) +channel = 'a' + +# Synchronous usage + +print pubnub.history(channel, count=2) + +# Asynchronous usage + + +def callback(message): + print(message) + +pubnub.history(channel, count=2, callback=callback, error=callback) diff --git a/python/examples/publish-example.py b/python/examples/publish-example.py deleted file mode 100755 index c97034b..0000000 --- a/python/examples/publish-example.py +++ /dev/null @@ -1,14 +0,0 @@ -from Pubnub import Pubnub - -## Initiate Class -pubnub = Pubnub( publish_key='demo', subscribe_key='demo', ssl_on=False ) - -## Publish Example -info = pubnub.publish({ - 'channel' : 'hello_world', - 'message' : { - 'some_text' : 'Hello my World' - } -}) -print(info) - diff --git a/python/examples/publish.py b/python/examples/publish.py new file mode 100644 index 0000000..594e7c4 --- /dev/null +++ b/python/examples/publish.py @@ -0,0 +1,36 @@ +## www.pubnub.com - PubNub Real-time push service in the cloud. +# coding=utf8 + +## PubNub Real-time Push APIs and Notifications Framework +## Copyright (c) 2010 Stephen Blum +## http://www.pubnub.com/ + + +import sys +from Pubnub import Pubnub + +publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' +subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' +secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' +cipher_key = len(sys.argv) > 4 and sys.argv[4] or '' +ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False + +## ----------------------------------------------------------------------- +## Initiate Pubnub State +## ----------------------------------------------------------------------- +pubnub = Pubnub(publish_key=publish_key, subscribe_key=subscribe_key, + secret_key=secret_key, cipher_key=cipher_key, ssl_on=ssl_on) +channel = 'hello_world' +message = 'Hello World !!!' + + +# Synchronous usage +print pubnub.publish(channel, message) + +# Asynchronous usage + + +def callback(message): + print(message) + +pubnub.publish(channel, message, callback=callback, error=callback) diff --git a/python/examples/pubnub-console/pubnub-console b/python/examples/pubnub-console/pubnub-console new file mode 100644 index 0000000..058253f --- /dev/null +++ b/python/examples/pubnub-console/pubnub-console @@ -0,0 +1,691 @@ +#!/usr/bin/python + +## www.pubnub.com - PubNub Real-time push service in the cloud. +# coding=utf8 + +## PubNub Real-time Push APIs and Notifications Framework +## Copyright (c) 2010 Stephen Blum +## http://www.pubnub.com/ + + +import sys +from Pubnub import Pubnub +import threading +from datetime import datetime + +from cmd2 import Cmd, make_option, options, Cmd2TestCase +import optparse +import json + +import atexit +import os +import readline +import rlcompleter + +import pygments +from pygments.lexers import JsonLexer +from pygments.formatters import TerminalFormatter + +lexer = JsonLexer() +formatter = TerminalFormatter() +def highlight(msg): + return pygments.highlight(msg, lexer, formatter) + + + +historyPath = os.path.expanduser("~/.pubnub_console_history") + + +def save_history(historyPath=historyPath): + import readline + readline.write_history_file(historyPath) + +if os.path.exists(historyPath): + readline.read_history_file(historyPath) + +atexit.register(save_history) + +of = sys.stdout + +color = Cmd() + +stop = None + +full_date = False + + +def stop_2(th): + th._Thread__stop() + + +def stop_3(th): + th._stop() + + +def print_console_2(of, message): + print >>of, message + + +def print_console_3(of, message): + of.write(message) + of.write("\n") + +print_console = None + +if type(sys.version_info) is tuple: + print_console = print_console_2 + stop = stop_2 +else: + if sys.version_info.major == 2: + print_console = print_console_2 + stop = stop_2 + else: + print_console = print_console_3 + stop = stop_3 + + +def get_date(): + if full_date is True: + return color.colorize(datetime.now().strftime( + '%Y-%m-%d %H:%M:%S'), "magenta") + else: + return color.colorize(datetime.now().strftime( + '%H:%M:%S'), "magenta") + +def print_ok_normal(msg, channel=None): + if msg is None: + return + chstr = color.colorize("[" + get_date() + "] ", "magenta") + chstr += color.colorize("[Channel : " + channel + + "] " if channel is not None else "", "cyan") + try: + print_console(of, (chstr + color.colorize(str(msg), "green"))) + except UnicodeEncodeError as e: + print_console(of, (msg)) + + of.flush() + + +def print_error_normal(msg, channel=None): + if msg is None: + return + chstr = color.colorize("[" + get_date() + "] ", "magenta") + chstr += color.colorize("[Channel : " + channel + + "] " if channel is not None else "", "cyan") + try: + print_console(of, (chstr + color.colorize(color.colorize( + str(msg), "red"), "bold"))) + except UnicodeEncodeError as e: + print_console(of, (msg)) + of.flush() + +def print_ok_pretty(msg, channel=None): + if msg is None: + return + chstr = color.colorize("[" + get_date() + "] ", "magenta") + chstr += color.colorize("[Channel : " + channel + + "] " if channel is not None else "", "cyan") + try: + print_console(of, (chstr + highlight(json.dumps(msg, indent=2)))) + except UnicodeEncodeError as e: + print_console(of, (msg)) + + of.flush() + + +def print_error_pretty(msg, channel=None): + if msg is None: + return + chstr = color.colorize("[" + get_date() + "] ", "magenta") + chstr += color.colorize("[Channel : " + channel + + "] " if channel is not None else "", "cyan") + try: + print_console(of, (chstr + color.colorize(color.colorize( + "ERROR: ", "red"), "bold") + + highlight(json.dumps(msg, indent=2)))) + except UnicodeEncodeError as e: + print_console(of, (msg)) + of.flush() + +print_ok = print_ok_pretty +print_error = print_error_pretty + + +class DefaultPubnub(object): + def handlerFunctionClosure(self, name): + def handlerFunction(*args, **kwargs): + print_error("Pubnub not initialized." + + "Use init command to initialize") + return handlerFunction + + def __getattr__(self, name): + return self.handlerFunctionClosure(name) + +pubnub = DefaultPubnub() + + +def kill_all_threads(): + for thread in threading.enumerate(): + if thread.isAlive(): + stop(thread) + + +def get_input(message, t=None): + while True: + try: + try: + command = raw_input(message) + except NameError: + command = input(message) + except KeyboardInterrupt: + return None + + command = command.strip() + + if command is None or len(command) == 0: + raise ValueError + + if t is not None and t == bool: + valid = ["True", "true", "1", 1, "y", "Y", "yes", "Yes", "YES"] + if command in valid: + return True + else: + return False + if t is not None: + command = t(command) + else: + command = eval("'" + command + "'") + + return command + except ValueError: + print_error("Invalid input : " + command) + + +def _publish_command_handler(channel, message, async=False): + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + print_ok(pubnub.publish(channel, message, + _callback if async is True else None, + _error if async is True else None)) + + +def _subscribe_command_handler(channel): + + def _callback(r, ch): + print_ok(r, ch) + + def _error(r, ch=None): + print_error(r, ch if ch is not None else channel) + + def _disconnect(r): + print_error("DISCONNECTED", r) + + def _reconnect(r): + print_error("RECONNECTED", r) + + def _connect(r): + print_error("CONNECTED", r) + + pubnub.subscribe(channel, _callback, _error, connect=_connect, + disconnect=_disconnect, reconnect=_reconnect) + + +def _unsubscribe_command_handler(channels): + + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + if not isinstance(channels, list): + ch = [] + ch.append(channels) + channels = ch + + for channel in channels: + pubnub.unsubscribe(channel) + pubnub.unsubscribe(channel + '-pnpres') + print_ok('Unsubscribed from : ' + str(channels)) + + +def _grant_command_handler(channel, auth_key, read, write, ttl, async=False): + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + + print_ok(pubnub.grant(channel, auth_key, + read, write, ttl, + _callback if async is True else None, + _error if async is True else None)) + + +def _revoke_command_handler(channel, auth_key, ttl, async=False): + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + + print_ok(pubnub.revoke(channel, auth_key, ttl, + _callback if async is True else None, + _error if async is True else None)) + + +def _audit_command_handler(channel, auth_key, async=False): + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + + print_ok(pubnub.audit(channel, auth_key, + _callback if async is True else None, + _error if async is True else None)) + + +def _history_command_handler(channel, count, async=False): + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + + print_ok(pubnub.history(channel, count, + _callback if async is True else None, + _error if async is True else None)) + + +def _here_now_command_handler(channel, async=False): + def _callback(r): + print_ok(r) + + def _error(r): + print_error(r) + + print_ok(pubnub.here_now(channel, _callback if async is True else None, + _error if async is True else None)) + + +def kill_all_threads(): + for thread in threading.enumerate(): + if thread.isAlive(): + stop(thread) + + +def get_channel_array(): + channels = pubnub.get_channel_array() + + for channel in channels: + if "-pnpres" in channel: + i = channels.index(channel.split("-pnpres")[0]) + channels[i] = channels[i] + color.colorize("(P)", "blue") + channels.remove(channel) + return channels + + +class DevConsole(Cmd): + def __init__(self): + Cmd.__init__(self) + global pubnub + self.intro = "For Help type ? or help . " + \ + "To quit/exit type exit" + self.default_channel = None + self.async = False + pubnub = Pubnub("demo", "demo") + self.channel_truncation = 3 + self.prompt = self.get_prompt() + self.publish_key = "demo" + self.subscribe_key = "demo" + self.origin = "pubsub.pubnub.com" + self.auth_key = None + self.cipher_key = None + self.secret_key = "demo" + self.ssl = False + self.uuid = None + self.disable_pretty = False + + def get_channel_origin(self): + cho = " [" + channels = get_channel_array() + channels_str = ",".join(channels) + sl = self.channel_truncation + if len(channels) > int(sl) and int(sl) > 0: + cho += ",".join(channels[:int(sl)]) + " " + str( + len(channels) - int(sl)) + " more..." + else: + cho += ",".join(channels) + + if len(channels) > 0: + cho = color.colorize(cho, "bold") + "@" + + origin = pubnub.get_origin().split("://")[1] + origin += color.colorize(" (SSL)", "green") if pubnub.get_origin( + ).split("://")[0] == "https" else "" + return cho + color.colorize(origin, "blue") + "] > " + + def get_prompt(self): + prompt = "[" + get_date() + "]" + + if self.default_channel is not None and len(self.default_channel) > 0: + prompt += " [default channel: " + color.colorize( + self.default_channel, "bold") + "]" + + prompt += self.get_channel_origin() + return prompt + + def precmd(self, line): + self.prompt = self.get_prompt() + return line + + #def emptyline(self): + # self.prompt = self.get_prompt() + + def cmdloop_with_keyboard_interrupt(self): + try: + self.cmdloop() + except KeyboardInterrupt as e: + pass + sys.stdout.write('\n') + kill_all_threads() + + @options([make_option('-p', '--publish-key', action="store", + default=None, help="Publish Key"), + make_option('-s', '--subscribe-key', action="store", + default=None, help="Subscribe Key"), + make_option('-k', '--secret-key', action="store", + default=None, help="cipher Key"), + make_option('-c', '--cipher-key', action="store", + default=None, help="Secret Key"), + make_option('-a', '--auth-key', action="store", + default=None, help="Auth Key"), + make_option('--ssl-on', dest='ssl', action='store_true', + default=False, help="SSL Enabled ?"), + make_option('-o', '--origin', action="store", + default=None, help="Origin"), + make_option('-u', '--uuid', action="store", + default=None, help="UUID"), + make_option('--disable-pretty-print', dest='disable_pretty', action='store_true', + default=False, help="Disable Pretty Print ?") + ]) + def do_init(self, command, opts): + global pubnub + global print_ok + global print_error + global print_ok_normal + global print_error_normal + global print_error_pretty + global print_ok_pretty + + self.publish_key = opts.publish_key if opts.publish_key is not None else self.publish_key + self.subscribe_key = opts.subscribe_key if opts.subscribe_key is not None else self.subscribe_key + self.secret_key = opts.secret_key if opts.secret_key is not None else self.secret_key + self.cipher_key = opts.cipher_key if opts.cipher_key is not None else self.cipher_key + self.auth_key = opts.auth_key if opts.auth_key is not None else self.auth_key + self.origin = opts.origin if opts.origin is not None else self.origin + self.uuid = opts.uuid if opts.uuid is not None else self.uuid + self.ssl = opts.ssl if opts.ssl is not None else self.ssl + self.disable_pretty = opts.disable_pretty if opts.disable_pretty is not None else self.disable_pretty + + pubnub = Pubnub(self.publish_key, + self.subscribe_key, + self.secret_key, + self.cipher_key, + self.auth_key, + self.ssl, + self.origin, + self.uuid) + self.prompt = self.get_prompt() + + if opts.disable_pretty is True: + print_ok = print_ok_normal + print_error = print_error_normal + else: + print_ok = print_ok_pretty + print_error = print_error_pretty + + def do_set_sync(self, command): + """unset_async + Unset Async mode""" + self.async = False + + def do_set_async(self, command): + """set_async + Set Async mode""" + self.async = True + + @options([make_option('-n', '--count', action="store", + default=3, help="Number of channels on prompt") + ]) + def do_set_channel_truncation(self, command, opts): + """set_channel_truncation + Set Channel Truncation""" + + self.channel_truncation = opts.count + + self.prompt = self.get_prompt() + + def do_unset_channel_truncation(self, command): + """unset_channel_truncation + Unset Channel Truncation""" + self.channel_truncation = 0 + self.prompt = self.get_prompt() + + def do_set_full_date(self, command): + global full_date + """do_set_full_date + Set Full Date""" + full_date = True + self.prompt = self.get_prompt() + + def do_unset_full_date(self, command): + global full_date + """do_unset_full_date + Unset Full Date""" + full_date = False + self.prompt = self.get_prompt() + + @options([make_option('-c', '--channel', + action="store", help="Default Channel") + ]) + def do_set_default_channel(self, command, opts): + + if opts.channel is None: + print_error("Missing channel") + return + self.default_channel = opts.channel + self.prompt = self.get_prompt() + + @options([make_option('-f', '--file', action="store", + default="./pubnub-console.log", help="Output file") + ]) + def do_set_output_file(self, command, opts): + global of + try: + of = file(opts.file, 'w+') + except IOError as e: + print_error("Could not set output file. " + e.reason) + + @options([make_option('-c', '--channel', action="store", + help="Channel for here now data") + ]) + def do_here_now(self, command, opts): + opts.channel = self.default_channel \ + if opts.channel is None else opts.channel + if opts.channel is None: + print_error("Missing channel") + return + + _here_now_command_handler(opts.channel, async=self.async) + + @options([make_option('-c', '--channel', action="store", + help="Channel for history data"), + make_option('-n', '--count', action="store", + default=5, help="Number of messages") + ]) + def do_get_history(self, command, opts): + opts.channel = self.default_channel \ + if opts.channel is None else opts.channel + if opts.channel is None: + print_error("Missing channel") + return + + _history_command_handler(opts.channel, opts.count, async=self.async) + + @options([make_option('-c', '--channel', action="store", + help="Channel on which to publish") + ]) + def do_publish(self, command, opts): + opts.channel = self.default_channel \ + if opts.channel is None else opts.channel + if opts.channel is None: + print_error("Missing channel") + return + + if command is None: + print_error("Missing message") + return + + try: + message = json.loads(str(command)) + except ValueError as ve: + message = str(command) + + _publish_command_handler(opts.channel, message, async=self.async) + + @options([make_option('-c', '--channel', action="store", + help="Channel on which to grant"), + make_option('-a', '--auth-key', dest="auth_key", + action="store", + help="Auth Key"), + make_option('-r', '--read-enabled', dest='read', + action='store_true', + default=False, help="Read ?"), + make_option('-w', '--write-enabled', dest='write', + action='store_true', + default=False, help="Write ?"), + make_option('-t', '--ttl', action="store", + default=5, help="TTL"), + make_option('-p', '--presence', action="store_true", + dest="presence", + default=False, help="Grant on presence channel ?") + ]) + def do_grant(self, command, opts): + opts.channel = self.default_channel \ + if opts.channel is None else opts.channel + + opts.auth_key = pubnub.auth_key \ + if opts.auth_key is None else opts.auth_key + + _grant_command_handler(opts.channel, opts.auth_key, + opts.read, opts.write, + opts.ttl, async=self.async) + + if opts.presence is True: + _grant_command_handler(opts.channel + '-pnpres', opts.auth_key, + opts.read, opts.write, + opts.ttl, async=self.async) + + @options([make_option('-c', '--channel', action="store", + help="Channel on which to revoke"), + make_option('-a', '--auth-key', dest="auth_key", action="store", + help="Auth Key"), + make_option('-t', '--ttl', action="store", + default=5, help="TTL"), + make_option('-p', '--presence', action="store_true", + dest="presence", + default=False, help="Revoke on presence channel ?") + ]) + def do_revoke(self, command, opts): + opts.channel = self.default_channel \ + if opts.channel is None else opts.channel + + opts.auth_key = pubnub.auth_key \ + if opts.auth_key is None else opts.auth_key + + _revoke_command_handler( + opts.channel, opts.auth_key, opts.ttl, async=self.async) + + if opts.presence is True: + _revoke_command_handler( + opts.channel + '-pnpres', opts.auth_key, + opts.ttl, async=self.async) + + @options([make_option('-c', '--channel', action="store", + help="Channel on which to revoke"), + make_option('-a', '--auth-key', dest="auth_key", action="store", + help="Auth Key") + ]) + def do_audit(self, command, opts): + opts.channel = self.default_channel \ + if opts.channel is None else opts.channel + + opts.auth_key = pubnub.auth_key \ + if opts.auth_key is None else opts.auth_key + + _audit_command_handler(opts.channel, opts.auth_key, async=self.async) + + @options([make_option('-c', '--channel', action="store", + help="Channel for unsubscribe"), + make_option('-a', '--all', action="store_true", dest="all", + default=False, help="Unsubscribe from all channels") + ]) + def do_unsubscribe(self, command, opts): + opts.channel = self.default_channel \ + if opts.channel is None else opts.channel + if (opts.all is True): + opts.channel = pubnub.get_channel_array() + if opts.channel is None: + print_error("Missing channel") + return + _unsubscribe_command_handler(opts.channel) + self.prompt = self.get_prompt() + + @options([make_option('-c', '--channel', action="store", + help="Channel for subscribe"), + make_option('-g', '--get-channel-list', action="store_true", + dest="get", + default=False, help="Get susbcribed channel list"), + make_option('-p', '--presence', action="store_true", + dest="presence", + default=False, help="Presence events ?") + ]) + def do_subscribe(self, command, opts): + opts.channel = self.default_channel \ + if opts.channel is None else opts.channel + if opts is None: + print_error("Missing argument") + return + + if opts.channel is not None: + _subscribe_command_handler(opts.channel) + + if opts.presence is True: + _subscribe_command_handler(opts.channel + '-pnpres') + + if opts.get is True: + print_ok(get_channel_array()) + self.prompt = self.get_prompt() + + def do_exit(self, args): + kill_all_threads() + return -1 + + #def do_EOF(self, args): + # kill_all_threads() + # return self.do_exit(args) + + #def handler(self, signum, frame): + # kill_all_threads() + + +def main(): + app = DevConsole() + app.cmdloop_with_keyboard_interrupt() + +if __name__ == "__main__": + main() diff --git a/python/examples/pubnub-console/setup.py b/python/examples/pubnub-console/setup.py new file mode 100644 index 0000000..a9fa506 --- /dev/null +++ b/python/examples/pubnub-console/setup.py @@ -0,0 +1,27 @@ +from setuptools import setup, find_packages + +setup( + name='pubnub-console', + version='3.5.0', + description='PubNub Developer Console', + author='Stephen Blum', + author_email='support@pubnub.com', + url='http://pubnub.com', + scripts=['pubnub-console'], + license='MIT', + classifiers=( + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'Programming Language :: Python', + 'License :: OSI Approved :: MIT License', + 'Operating System :: OS Independent', + 'Topic :: Internet :: WWW/HTTP', + 'Topic :: Software Development :: Libraries :: Python Modules', + ), + install_requires=[ + 'pubnub>=3.5.0', + 'cmd2>=0.6.7', + 'pygments >= 1.6' + ], + zip_safe=False, +) diff --git a/python/examples/requirements.pip b/python/examples/requirements.pip new file mode 100644 index 0000000..738c606 --- /dev/null +++ b/python/examples/requirements.pip @@ -0,0 +1,3 @@ +pycrypto==2.6.1 +cmd2==0.6.7 +requests==2.2.1 diff --git a/python/examples/start-console.sh b/python/examples/start-console.sh new file mode 100755 index 0000000..a928cb3 --- /dev/null +++ b/python/examples/start-console.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +#!/bin/bash -e + +BASEDIR=. + +if [ ! -d "$BASEDIR/ve" ]; then + virtualenv -q $BASEDIR/ve --no-site-packages + $BASEDIR/ve/bin/activate + echo "Virtualenv created." +fi + +chmod 755 $BASEDIR/ve/bin/activate +$BASEDIR/ve/bin/activate + +if [ ! -f "$BASEDIR/ve/updated" -o $BASEDIR/requirements.pip -nt $BASEDIR/ve/updated ]; then + pip install -r $BASEDIR/requirements.pip -E $BASEDIR/ve + touch $BASEDIR/ve/updated + echo "Requirements installed." +fi + + + +if ! type "screen" > /dev/null; then + echo "[ERROR] Screen is not installed. Please install screen to use this utility ." + exit +fi +rm ./pubnub-console.log +touch ./pubnub-console.log +export PYTHONPATH=../.. +screen -X -S pubnub-console quit 2>&1 > /dev/null +OS="`uname`" +case $OS in + [dD]'arwin') + screen -c config_osx + ;; + *) screen -c config ;; +esac diff --git a/python/examples/subscribe-example.py b/python/examples/subscribe-example.py deleted file mode 100755 index 14a43d9..0000000 --- a/python/examples/subscribe-example.py +++ /dev/null @@ -1,65 +0,0 @@ -import sys -sys.path.append('../') -import threading -import time -import random -import string -from Pubnub import Pubnub - -## Initiate Class -pubnub = Pubnub( 'demo', 'demo', None, False ) - -print("My UUID is: "+pubnub.uuid) - -channel = ''.join(random.choice(string.ascii_letters + string.digits) for x in range(20)) - -## Subscribe Example -def receive(message) : - print(message) - return False - -def pres_event(message): - print(message) - return False - -def subscribe(): - print("Listening for messages on '%s' channel..." % channel) - pubnub.subscribe({ - 'channel' : channel, - 'callback' : receive - }) - -def presence(): - print("Listening for presence events on '%s' channel..." % channel) - pubnub.presence({ - 'channel' : channel, - 'callback' : pres_event - }) - -def publish(): - print("Publishing a test message on '%s' channel..." % channel) - pubnub.publish({ - 'channel' : channel, - 'message' : { 'text':'foo bar' } - }) - -pres_thread = threading.Thread(target=presence) -pres_thread.daemon=True -pres_thread.start() - -sub_thread = threading.Thread(target=subscribe) -sub_thread.daemon=True -sub_thread.start() - -time.sleep(3) - -publish() - - -print("waiting for subscribes and presence") -pres_thread.join() - -print pubnub.here_now({'channel':channel}) - -sub_thread.join() - diff --git a/python/examples/subscribe.py b/python/examples/subscribe.py new file mode 100644 index 0000000..9b8b223 --- /dev/null +++ b/python/examples/subscribe.py @@ -0,0 +1,49 @@ +## www.pubnub.com - PubNub Real-time push service in the cloud. +# coding=utf8 + +## PubNub Real-time Push APIs and Notifications Framework +## Copyright (c) 2010 Stephen Blum +## http://www.pubnub.com/ + + +import sys +from Pubnub import Pubnub + +publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' +subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' +secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' +cipher_key = len(sys.argv) > 4 and sys.argv[4] or '' +ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False + +## ----------------------------------------------------------------------- +## Initiate Pubnub State +## ----------------------------------------------------------------------- +pubnub = Pubnub(publish_key=publish_key, subscribe_key=subscribe_key, + secret_key=secret_key, cipher_key=cipher_key, ssl_on=ssl_on) + +channel = 'a' + + +# Asynchronous usage +def callback(message, channel): + print(message) + + +def error(message): + print("ERROR : " + str(message)) + + +def connect(message): + print("CONNECTED") + + +def reconnect(message): + print("RECONNECTED") + + +def disconnect(message): + print("DISCONNECTED") + + +pubnub.subscribe(channel, callback=callback, error=callback, + connect=connect, reconnect=reconnect, disconnect=disconnect) diff --git a/python/migration.md b/python/migration.md new file mode 100644 index 0000000..61cf203 --- /dev/null +++ b/python/migration.md @@ -0,0 +1,205 @@ +## Contact support@pubnub.com for all questions + +#### [PubNub](http://www.pubnub.com) Real-time Data Network +##### Standalone Python Migration + +#### Init + +``` + +# Pre 3.5: +pubnub = Pubnub( + "demo", ## PUBLISH_KEY + "demo", ## SUBSCRIBE_KEY + False ## SSL_ON? +) + +# New in 3.5+ +pubnub = Pubnub(publish_key="demo", subscribe_key="demo", ssl_on=False) + +``` + +#### PUBLISH + +``` +channel = 'hello_world' +message = 'Hello World !!!' + +# Pre 3.5: +info = pubnub.publish({ + 'channel' : channel, + 'message' : message +}) +print(info) + +# New in 3.5+ + +# Synchronous usage +print pubnub.publish(channel='hello_world', message='Hello World !!!') + +# Asynchronous usage + +def callback(message): + print(message) + +pubnub.publish(channel, message, callback=callback, error=callback) + +``` + + +#### SUBSCRIBE +Pre 3.5.x, subscribe was blocking and would only be terminated via a false return from the callback. In our latest version of the SDK, subscribe is asyncronous, and because of this, usage is a bit different, but the experience is more like our other async SDKs. + +``` + +# Listen for Messages + +channel = 'hello_world' + +# Pre 3.5: +# Listen for Messages *BLOCKING* +def receive(message) : + print(message) + return True + +pubnub.subscribe({ + 'channel' : channel, + 'callback' : receive +}) + + +# New in 3.5+ + +def callback(message, channel): + print(message) + + +def error(message): + print("ERROR : " + str(message)) + + +def connect(message): + print("CONNECTED") + + +def reconnect(message): + print("RECONNECTED") + + +def disconnect(message): + print("DISCONNECTED") + + +pubnub.subscribe(channel, callback=callback, error=callback, + connect=connect, reconnect=reconnect, disconnect=disconnect) +``` + +#### Unsubscribe +Once subscribed, you can easily, gracefully, unsubscribe: + +``` +# Pre 3.5: +# + +# New in 3.5+ + +pubnub.unsubscribe(channel='hello_world') +``` + +#### PRESENCE + +``` + + +channel = 'hello_world' + +# Pre 3.5: +def pres_event(message) : + print(message) + return True + +pubnub.presence({ + 'channel' : channel, + 'callback' : receive +}) + + +# New in 3.5+ + +# Listen for Presence Event Messages + +def callback(message, channel): + print(message) + + +def error(message): + print("ERROR : " + str(message)) + + + +pubnub.presence(channel, callback=callback, error=callback) +``` + +#### HERE_NOW + +``` + +# Pre 3.5: +# Get info on who is here right now! + +here_now = pubnub.here_now({ + 'channel' : 'hello_world', +}) + +print(here_now['occupancy']) +print(here_now['uuids']) + + +# New in 3.5+ + +# Get info on who is here right now! + +channel = 'hello_world' + +# Synchronous usage +print pubnub.here_now(channel) + + +# Asynchronous usage + +def callback(message): + print(message) + +pubnub.here_now(channel, callback=callback, error=callback) +``` + +#### HISTORY + +``` + +# Pre 3.5: +# Load Previously Published Messages +history = pubnub.detailedHistory({ + 'channel' : 'my_channel', + 'end' : my_end_time_token, # Optional + 'start' : my_start_time_token, # Optional + 'count' : num_of_msgs_to_return # Optional, default is 100 +}) +print(history) + +# New in 3.5+ + +# Synchronous usage + +print pubnub.history(channel, count=2) + +# Asynchronous usage + + +def callback(message): + print(message) + +pubnub.history(channel, count=2, callback=callback, error=callback) +``` + +## Contact support@pubnub.com for all questions diff --git a/python/tests/detailed-history-unit-test.py b/python/tests/detailed-history-unit-test.py deleted file mode 100755 index 31bdef8..0000000 --- a/python/tests/detailed-history-unit-test.py +++ /dev/null @@ -1,137 +0,0 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. -# coding=utf8 - -## PubNub Real-time Push APIs and Notifications Framework -## Copyright (c) 2010 Stephen Blum -## http://www.pubnub.com/ - -## ----------------------------------- -## PubNub 3.0 Real-time Push Cloud API -## ----------------------------------- - -import sys -sys.path.append('.') -sys.path.append('..') -sys.path.append('../common') -from Pubnub import Pubnub -import unittest2 as unittest - - -publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' -subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' -secret_key = len(sys.argv) > 3 and sys.argv[3] or None -ssl_on = len(sys.argv) > 4 and bool(sys.argv[4]) or False -pubnub = Pubnub(publish_key, subscribe_key, secret_key, ssl_on) -crazy = ' ~`!@#$%^&*(é¡¶é¡…È’)+=[]\\{}|;\':",./<>?abcd' - - -class TestDetailedHistory(unittest.TestCase): - total_msg = 10 - channel = pubnub.time() - starttime = None - inputs = [] - endtime = None - slice_a = 8 - slice_b = 2 - slice_size = slice_a - slice_b - - @classmethod - def publish_msg(cls, start, end, offset): - print 'Publishing messages' - inputs = [] - for i in range(start + offset, end + offset): - message = str(i) + " " + crazy - success = pubnub.publish({ - 'channel': cls.channel, - 'message': message, - }) - t = pubnub.time() - inputs.append({'timestamp': t, 'message': message}) - print 'Message # ', i, ' published' - return inputs - - @classmethod - def setUpClass(cls): - print 'Setting up context for Detailed History tests. Please wait ...' - cls.starttime = pubnub.time() - cls.inputs = cls.inputs + cls.publish_msg(0, cls.total_msg / 2, 0) - cls.midtime = pubnub.time() - cls.inputs = cls.inputs + cls.publish_msg( - 0, cls.total_msg / 2, cls.total_msg / 2) - cls.endtime = pubnub.time() - print 'Context setup for Detailed History tests. Now running tests' - - def test_begin_to_end_count(self): - count = 5 - history = pubnub.detailedHistory({ - 'channel': self.__class__.channel, - 'start': self.__class__.starttime, - 'end': self.__class__.endtime, - 'count': count - })[0] - self.assertTrue(len(history) == count and history[-1].encode( - 'utf-8') == self.__class__.inputs[count - 1]['message']) - - def test_end_to_begin_count(self): - count = 5 - history = pubnub.detailedHistory({ - 'channel': self.__class__.channel, - 'start': self.__class__.endtime, - 'end': self.__class__.starttime, - 'count': count - })[0] - self.assertTrue(len(history) == count and history[-1] - .encode('utf-8') == self.__class__.inputs[-1]['message']) - - def test_start_reverse_true(self): - history = pubnub.detailedHistory({ - 'channel': self.__class__.channel, - 'start': self.__class__.midtime, - 'reverse': True - })[0] - self.assertTrue(len(history) == self.__class__.total_msg / 2) - expected_msg = self.__class__.inputs[-1]['message'] - self.assertTrue(history[-1].encode('utf-8') == expected_msg) - - def test_start_reverse_false(self): - history = pubnub.detailedHistory({ - 'channel': self.__class__.channel, - 'start': self.__class__.midtime, - })[0] - self.assertTrue(history[0].encode('utf-8') - == self.__class__.inputs[0]['message']) - - def test_end_reverse_true(self): - history = pubnub.detailedHistory({ - 'channel': self.__class__.channel, - 'end': self.__class__.midtime, - 'reverse': True - })[0] - self.assertTrue(history[0].encode('utf-8') - == self.__class__.inputs[0]['message']) - - def test_end_reverse_false(self): - history = pubnub.detailedHistory({ - 'channel': self.__class__.channel, - 'end': self.__class__.midtime, - })[0] - self.assertTrue(len(history) == self.__class__.total_msg / 2) - self.assertTrue(history[-1].encode('utf-8') - == self.__class__.inputs[-1]['message']) - - def test_count(self): - history = pubnub.detailedHistory({ - 'channel': self.__class__.channel, - 'count': 5 - })[0] - self.assertTrue(len(history) == 5) - - def test_count_zero(self): - history = pubnub.detailedHistory({ - 'channel': self.__class__.channel, - 'count': 0 - })[0] - self.assertTrue(len(history) == 0) - -if __name__ == '__main__': - unittest.main() diff --git a/python/tests/subscribe-test.py b/python/tests/subscribe-test.py new file mode 100755 index 0000000..a1b1826 --- /dev/null +++ b/python/tests/subscribe-test.py @@ -0,0 +1,154 @@ +## www.pubnub.com - PubNub Real-time push service in the cloud. +# coding=utf8 + +## PubNub Real-time Push APIs and Notifications Framework +## Copyright (c) 2010 Stephen Blum +## http://www.pubnub.com/ + +## ----------------------------------- +## PubNub 3.1 Real-time Push Cloud API +## ----------------------------------- + +import sys +import datetime +from Pubnub import PubnubAsync as Pubnub +from functools import partial +from threading import current_thread +import threading +publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' +subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' +secret_key = len(sys.argv) > 3 and sys.argv[3] or 'demo' +cipher_key = len(sys.argv) > 4 and sys.argv[4] or None +ssl_on = len(sys.argv) > 5 and bool(sys.argv[5]) or False + +## ----------------------------------------------------------------------- +## Initiate Pubnub State +## ----------------------------------------------------------------------- +#pubnub = Pubnub( publish_key, subscribe_key, secret_key, cipher_key, ssl_on ) +pubnub = Pubnub(publish_key, subscribe_key, secret_key, ssl_on) +crazy = 'hello_world' + +current = -1 + +errors = 0 +received = 0 + +## ----------------------------------------------------------------------- +## Subscribe Example +## ----------------------------------------------------------------------- + + +def message_received(message): + print(message) + + +def check_received(message): + global current + global errors + global received + print(message) + print(current) + if message <= current: + print('ERROR') + #sys.exit() + errors += 1 + else: + received += 1 + print('active thread count : ' + str(threading.activeCount())) + print('errors = ' + str(errors)) + print(current_thread().getName() + ' , ' + 'received = ' + str(received)) + + if received != message: + print('********** MISSED **************** ' + str(message - received)) + current = message + + +def connected_test(ch): + print('Connected ' + ch) + + +def connected(ch): + pass + + +''' +pubnub.subscribe({ + 'channel' : 'abcd1', + 'connect' : connected, + 'callback' : message_received +}) +''' + + +def cb1(): + pubnub.subscribe({ + 'channel': 'efgh1', + 'connect': connected, + 'callback': message_received + }) + + +def cb2(): + pubnub.subscribe({ + 'channel': 'dsm-test', + 'connect': connected_test, + 'callback': check_received + }) + + +def cb3(): + pubnub.unsubscribe({'channel': 'efgh1'}) + + +def cb4(): + pubnub.unsubscribe({'channel': 'abcd1'}) + + +def subscribe(channel): + pubnub.subscribe({ + 'channel': channel, + 'connect': connected, + 'callback': message_received + }) + + +pubnub.timeout(15, cb1) + +pubnub.timeout(30, cb2) + + +pubnub.timeout(45, cb3) + +pubnub.timeout(60, cb4) + +#''' +for x in range(1, 1000): + #print x + def y(t): + subscribe('channel-' + str(t)) + + def z(t): + pubnub.unsubscribe({'channel': 'channel-' + str(t)}) + + pubnub.timeout(x + 5, partial(y, x)) + pubnub.timeout(x + 25, partial(z, x)) + x += 10 +#''' + +''' +for x in range(1,1000): + def cb(r): print r , ' : ', threading.activeCount() + def y(t): + pubnub.publish({ + 'message' : t, + 'callback' : cb, + 'channel' : 'dsm-test' + }) + + + pubnub.timeout(x + 1, partial(y,x)) + x += 1 +''' + + +pubnub.start() diff --git a/python/tests/test_grant.py b/python/tests/test_grant.py new file mode 100644 index 0000000..6826335 --- /dev/null +++ b/python/tests/test_grant.py @@ -0,0 +1,199 @@ + + +from Pubnub import Pubnub +import time + +pubnub = Pubnub("demo","demo") +pubnub_pam = Pubnub("pub-c-c077418d-f83c-4860-b213-2f6c77bde29a", + "sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe", "sec-c-OGU3Y2Q4ZWUtNDQwMC00NTI1LThjNWYtNWJmY2M4OGIwNjEy") + + +# Grant permission read true, write true, on channel ( Sync Mode ) +def test_1(): + resp = pubnub_pam.grant(channel="abcd", auth_key="abcd", read=True, write=True, ttl=1) + assert resp['message'] == 'Success' + assert resp['payload'] == { + 'auths': {'abcd': {'r': 1, 'w': 1}}, + 'subscribe_key': 'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + 'level': 'user', 'channel': 'abcd', 'ttl': 1 + } + + +# Grant permission read false, write false, on channel ( Sync Mode ) +def test_2(): + resp = pubnub_pam.grant(channel="abcd", auth_key="abcd", read=False, write=False, ttl=1) + assert resp['message'] == 'Success' + assert resp['payload'] == { + 'auths': {'abcd': {'r': 0, 'w': 0}}, + 'subscribe_key': 'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + 'level': 'user', 'channel': 'abcd', 'ttl': 1 + } + +# Grant permission read True, write false, on channel ( Sync Mode ) +def test_3(): + resp = pubnub_pam.grant(channel="abcd", auth_key="abcd", read=True, write=False, ttl=1) + assert resp['message'] == 'Success' + assert resp['payload'] == { + 'auths': {'abcd': {'r': 1, 'w': 0}}, + 'subscribe_key': 'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + 'level': 'user', 'channel': 'abcd', 'ttl': 1 + } + +# Grant permission read False, write True, on channel ( Sync Mode ) +def test_4(): + resp = pubnub_pam.grant(channel="abcd", auth_key="abcd", read=True, write=False, ttl=1) + assert resp['message'] == 'Success' + assert resp['payload'] == { + 'auths': {'abcd': {'r': 1, 'w': 0}}, + 'subscribe_key': 'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + 'level': 'user', 'channel': 'abcd', 'ttl': 1 + } + +# Grant permission read False, write True, on channel ( Sync Mode ), TTL 10 +def test_5(): + resp = pubnub_pam.grant(channel="abcd", auth_key="abcd", read=True, write=False, ttl=10) + assert resp['message'] == 'Success' + assert resp['payload'] == { + 'auths': {'abcd': {'r': 1, 'w': 0}}, + 'subscribe_key': 'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + 'level': 'user', 'channel': 'abcd', 'ttl': 10 + } + +# Grant permission read False, write True, without channel ( Sync Mode ), TTL 10 +def test_6(): + resp = pubnub_pam.grant(auth_key="abcd", read=True, write=False, ttl=10) + assert resp['message'] == 'Success' + assert resp['payload'] == { + 'subscribe_key': 'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + 'level': 'subkey' , u'r': 1, u'w': 0, 'ttl': 10 + } + + +# Grant permission read False, write False, without channel ( Sync Mode ) +def test_7(): + resp = pubnub_pam.grant(auth_key="abcd", read=False, write=False) + assert resp['message'] == 'Success' + assert resp['payload'] == { + 'subscribe_key': 'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + 'level': 'subkey' , u'r': 0, u'w': 0, 'ttl': 1 + } + + +# Complete flow , try publish on forbidden channel, grant permission to auth key and try again. ( Sync Mode) + +def test_8(): + channel = "test_8-" + str(time.time()) + message = "Hello World" + auth_key = "auth-" + channel + pubnub_pam.set_auth_key(auth_key) + resp = pubnub_pam.publish(channel=channel,message=message) + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + resp = pubnub_pam.grant(channel=channel, read=True, write=True, auth_key=auth_key, ttl=10) + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {auth_key : {u'r': 1, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': channel, u'ttl': 10} + } + resp = pubnub_pam.publish(channel=channel,message=message) + assert resp[0] == 1 + + +# Complete flow , try publish on forbidden channel, grant permission to authkey and try again. ( Sync Mode) +# then revoke and try again +def test_9(): + channel = "test_9-" + str(time.time()) + message = "Hello World" + auth_key = "auth-" + channel + pubnub_pam.set_auth_key(auth_key) + resp = pubnub_pam.publish(channel=channel,message=message) + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + resp = pubnub_pam.grant(channel=channel, read=True, write=True, auth_key=auth_key, ttl=10) + print resp + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {auth_key : {u'r': 1, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': channel, u'ttl': 10} + } + resp = pubnub_pam.publish(channel=channel,message=message) + assert resp[0] == 1 + resp = pubnub_pam.revoke(channel=channel, auth_key=auth_key) + print resp + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {auth_key : {u'r': 0, u'w': 0}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': channel, u'ttl': 1} + } + resp = pubnub_pam.publish(channel=channel,message=message) + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + +# Complete flow , try publish on forbidden channel, grant permission channel level for subkey and try again. ( Sync Mode) +# then revoke and try again +def test_10(): + channel = "test_10-" + str(time.time()) + message = "Hello World" + auth_key = "auth-" + channel + pubnub_pam.set_auth_key(auth_key) + resp = pubnub_pam.publish(channel=channel,message=message) + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + resp = pubnub_pam.grant(channel=channel, read=True, write=True, ttl=10) + print resp + assert resp == { + 'message': u'Success', + 'payload': { u'channels': {channel: {u'r': 1, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'channel', u'ttl': 10} + } + resp = pubnub_pam.publish(channel=channel,message=message) + assert resp[0] == 1 + resp = pubnub_pam.revoke(channel=channel) + print resp + assert resp == { + 'message': u'Success', + 'payload': { u'channels': {channel : {u'r': 0, u'w': 0}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'channel', u'ttl': 1} + } + resp = pubnub_pam.publish(channel=channel,message=message) + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + +# Complete flow , try publish on forbidden channel, grant permission subkey level for subkey and try again. ( Sync Mode) +# then revoke and try again +def test_11(): + channel = "test_11-" + str(time.time()) + message = "Hello World" + auth_key = "auth-" + channel + pubnub_pam.set_auth_key(auth_key) + resp = pubnub_pam.publish(channel=channel,message=message) + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + resp = pubnub_pam.grant(read=True, write=True, ttl=10) + print resp + assert resp == { + 'message': u'Success', + 'payload': { u'r': 1, u'w': 1, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'subkey', u'ttl': 10} + } + resp = pubnub_pam.publish(channel=channel,message=message) + assert resp[0] == 1 + resp = pubnub_pam.revoke() + print resp + assert resp == { + 'message': u'Success', + 'payload': {u'r': 0, u'w': 0, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'subkey', u'ttl': 1} + } + resp = pubnub_pam.publish(channel=channel,message=message) + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + + diff --git a/python/tests/test_grant_async.py b/python/tests/test_grant_async.py new file mode 100644 index 0000000..4d38a0a --- /dev/null +++ b/python/tests/test_grant_async.py @@ -0,0 +1,369 @@ + + +from Pubnub import Pubnub +import time + +pubnub = Pubnub("demo","demo") +pubnub_pam = Pubnub("pub-c-c077418d-f83c-4860-b213-2f6c77bde29a", + "sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe", "sec-c-OGU3Y2Q4ZWUtNDQwMC00NTI1LThjNWYtNWJmY2M4OGIwNjEy") + + + +# Grant permission read true, write true, on channel ( Async Mode ) +def test_1(): + resp = {'response' : None} + def _callback(response): + resp['response'] = response + + def _error(response): + resp['response'] = response + + pubnub_pam.grant(channel="abcd", auth_key="abcd", read=True, write=True, ttl=1, callback=_callback, error=_error) + time.sleep(2) + assert resp['response'] == { + 'message': u'Success', + 'payload': {u'auths': {u'abcd': {u'r': 1, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': u'abcd', u'ttl': 1} + } + + +# Grant permission read false, write false, on channel ( Async Mode ) +def test_2(): + resp = {'response' : None} + def _callback(response): + resp['response'] = response + + def _error(response): + resp['response'] = response + + pubnub_pam.grant(channel="abcd", auth_key="abcd", read=False, write=False, ttl=1, callback=_callback, error=_error) + time.sleep(2) + assert resp['response'] == { + 'message': u'Success', + 'payload': {u'auths': {u'abcd': {u'r': 0, u'w': 0}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': u'abcd', u'ttl': 1} + } + + +# Grant permission read True, write false, on channel ( Async Mode ) +def test_3(): + resp = {'response' : None} + def _callback(response): + resp['response'] = response + + def _error(response): + resp['response'] = response + + pubnub_pam.grant(channel="abcd", auth_key="abcd", read=True, write=False, ttl=1, callback=_callback, error=_error) + time.sleep(2) + assert resp['response'] == { + 'message': u'Success', + 'payload': {u'auths': {u'abcd': {u'r': 1, u'w': 0}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': u'abcd', u'ttl': 1} + } + +# Grant permission read False, write True, on channel ( Async Mode ) +def test_4(): + resp = {'response' : None} + def _callback(response): + resp['response'] = response + + def _error(response): + resp['response'] = response + + pubnub_pam.grant(channel="abcd", auth_key="abcd", read=False, write=True, ttl=1, callback=_callback, error=_error) + time.sleep(2) + assert resp['response'] == { + 'message': u'Success', + 'payload': {u'auths': {u'abcd': {u'r': 0, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': u'abcd', u'ttl': 1} + } + + +# Grant permission read False, write True, on channel ( Async Mode ), TTL 10 +def test_5(): + resp = {'response' : None} + def _callback(response): + resp['response'] = response + + def _error(response): + resp['response'] = response + + pubnub_pam.grant(channel="abcd", auth_key="abcd", read=False, write=True, ttl=10, callback=_callback, error=_error) + time.sleep(2) + assert resp['response'] == { + 'message': u'Success', + 'payload': {u'auths': {u'abcd': {u'r': 0, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': u'abcd', u'ttl': 10} + } + + +# Grant permission read False, write True, without channel ( Async Mode ), TTL 10 +def test_6(): + resp = {'response' : None} + def _callback(response): + resp['response'] = response + + def _error(response): + resp['response'] = response + + pubnub_pam.grant(auth_key="abcd", read=False, write=True, ttl=10, callback=_callback, error=_error) + time.sleep(2) + assert resp['response'] == { + 'message': u'Success', + 'payload': { u'r': 0, u'w': 1, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'subkey', u'ttl': 10} + } + + +# Grant permission read False, write False, without channel ( Async Mode ) +def test_7(): + resp = {'response' : None} + def _callback(response): + resp['response'] = response + + def _error(response): + resp['response'] = response + + pubnub_pam.grant(auth_key="abcd", read=False, write=False, callback=_callback, error=_error) + time.sleep(2) + assert resp['response'] == { + 'message': u'Success', + 'payload': { u'r': 0, u'w': 0, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'subkey', u'ttl': 1} + } + + +# Complete flow , try publish on forbidden channel, grant permission to subkey and try again. ( Sync Mode) + +def test_8(): + channel = "test_8-" + str(time.time()) + message = "Hello World" + auth_key = "auth-" + channel + pubnub_pam.set_auth_key(auth_key) + + + + def _cb1(resp, ch=None): + assert False + def _err1(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + pubnub_pam.publish(channel=channel,message=message, callback=_cb1, error=_err1) + time.sleep(2) + + + def _cb2(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {auth_key : {u'r': 1, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': channel, u'ttl': 10} + } + def _err2(resp): + assert False + + + resp = pubnub_pam.grant(channel=channel, read=True, write=True, auth_key=auth_key, ttl=10, callback=_cb2, error=_err2) + time.sleep(2) + + def _cb3(resp, ch=None): + assert resp[0] == 1 + def _err3(resp): + assert False + + pubnub_pam.publish(channel=channel,message=message, callback=_cb3, error=_err3) + time.sleep(2) + + + + + +# Complete flow , try publish on forbidden channel, grant permission to authkey and try again. +# then revoke and try again +def test_9(): + channel = "test_9-" + str(time.time()) + message = "Hello World" + auth_key = "auth-" + channel + pubnub_pam.set_auth_key(auth_key) + + def _cb1(resp, ch=None): + assert False + def _err1(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + pubnub_pam.publish(channel=channel,message=message, callback=_cb1, error=_err1) + time.sleep(2) + + + def _cb2(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {auth_key : {u'r': 1, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': channel, u'ttl': 10} + } + def _err2(resp): + assert False + + + pubnub_pam.grant(channel=channel, read=True, write=True, auth_key=auth_key, ttl=10, callback=_cb2, error=_err2) + time.sleep(2) + + def _cb3(resp, ch=None): + assert resp[0] == 1 + def _err3(resp): + assert False + + pubnub_pam.publish(channel=channel,message=message, callback=_cb3, error=_err3) + time.sleep(2) + + def _cb4(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'auths': {auth_key : {u'r': 0, u'w': 0}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'user', u'channel': channel, u'ttl': 1} + } + def _err4(resp): + assert False + pubnub_pam.revoke(channel=channel, auth_key=auth_key, callback=_cb4, error=_err4) + time.sleep(2) + + def _cb5(resp, ch=None): + assert False + def _err5(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + pubnub_pam.publish(channel=channel,message=message, callback=_cb5, error=_err5) + time.sleep(2) + + + + +# Complete flow , try publish on forbidden channel, grant permission channel level for subkey and try again. +# then revoke and try again +def test_10(): + channel = "test_10-" + str(time.time()) + message = "Hello World" + auth_key = "auth-" + channel + pubnub_pam.set_auth_key(auth_key) + + def _cb1(resp, ch=None): + assert False + def _err1(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + pubnub_pam.publish(channel=channel,message=message, callback=_cb1, error=_err1) + time.sleep(2) + + + def _cb2(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': { u'channels': {channel: {u'r': 1, u'w': 1}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'channel', u'ttl': 10} + } + def _err2(resp): + assert False + + + pubnub_pam.grant(channel=channel, read=True, write=True, ttl=10, callback=_cb2, error=_err2) + time.sleep(2) + + def _cb3(resp, ch=None): + assert resp[0] == 1 + def _err3(resp): + assert False + + pubnub_pam.publish(channel=channel,message=message, callback=_cb3, error=_err3) + time.sleep(2) + + def _cb4(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': { u'channels': {channel : {u'r': 0, u'w': 0}}, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'channel', u'ttl': 1} + } + def _err4(resp): + assert False + pubnub_pam.revoke(channel=channel, callback=_cb4, error=_err4) + time.sleep(2) + + def _cb5(resp, ch=None): + assert False + def _err5(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + pubnub_pam.publish(channel=channel,message=message, callback=_cb5, error=_err5) + time.sleep(2) + + + +# Complete flow , try publish on forbidden channel, grant permission subkey level for subkey and try again. +# then revoke and try again +def test_11(): + channel = "test_11-" + str(time.time()) + message = "Hello World" + auth_key = "auth-" + channel + pubnub_pam.set_auth_key(auth_key) + + def _cb1(resp, ch=None): + assert False + def _err1(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + pubnub_pam.publish(channel=channel,message=message, callback=_cb1, error=_err1) + time.sleep(2) + + + def _cb2(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': { u'r': 1, u'w': 1, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'subkey', u'ttl': 10} + } + def _err2(resp): + assert False + + + pubnub_pam.grant(read=True, write=True, ttl=10, callback=_cb2, error=_err2) + time.sleep(2) + + def _cb3(resp, ch=None): + assert resp[0] == 1 + def _err3(resp): + assert False + + pubnub_pam.publish(channel=channel,message=message, callback=_cb3, error=_err3) + time.sleep(2) + + def _cb4(resp, ch=None): + assert resp == { + 'message': u'Success', + 'payload': {u'r': 0, u'w': 0, + u'subscribe_key': u'sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe', + u'level': u'subkey', u'ttl': 1} + } + def _err4(resp): + assert False + pubnub_pam.revoke(callback=_cb4, error=_err4) + time.sleep(2) + + def _cb5(resp, ch=None): + assert False + def _err5(resp): + assert resp['message'] == 'Forbidden' + assert resp['payload'] == {u'channels': [channel]} + pubnub_pam.publish(channel=channel,message=message, callback=_cb5, error=_err5) + time.sleep(2) diff --git a/python/tests/test_publish_async.py b/python/tests/test_publish_async.py new file mode 100644 index 0000000..7270727 --- /dev/null +++ b/python/tests/test_publish_async.py @@ -0,0 +1,228 @@ + + +from Pubnub import Pubnub +import time + +pubnub = Pubnub("demo","demo") +pubnub_enc = Pubnub("demo", "demo", cipher_key="enigma") +pubnub_pam = Pubnub("pub-c-c077418d-f83c-4860-b213-2f6c77bde29a", + "sub-c-e8839098-f568-11e2-a11a-02ee2ddab7fe", "sec-c-OGU3Y2Q4ZWUtNDQwMC00NTI1LThjNWYtNWJmY2M4OGIwNjEy") + + + +# Publish and receive string +def test_1(): + + channel = "test_1-" + str(time.time()) + message = "I am a string" + + def _cb(resp, ch=None): + assert resp == message + pubnub.unsubscribe(channel) + + def _connect(resp): + pubnub.publish(channel,message) + + def _error(resp): + assert False + + pubnub.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive array +def test_2(): + + channel = "test_2-" + str(time.time()) + message = [1,2] + + def _cb(resp, ch=None): + assert resp == message + pubnub.unsubscribe(channel) + + def _connect(resp): + pubnub.publish(channel,message) + + def _error(resp): + assert False + + pubnub.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive json object +def test_3(): + + channel = "test_2-" + str(time.time()) + message = { "a" : "b" } + + def _cb(resp, ch=None): + assert resp == message + pubnub.unsubscribe(channel) + + def _connect(resp): + pubnub.publish(channel,message) + + def _error(resp): + assert False + + pubnub.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive number +def test_4(): + + channel = "test_2-" + str(time.time()) + message = 100 + + def _cb(resp, ch=None): + assert resp == message + pubnub.unsubscribe(channel) + + def _connect(resp): + pubnub.publish(channel,message) + + def _error(resp): + assert False + + pubnub.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive number string +def test_5(): + + channel = "test_5-" + str(time.time()) + message = "100" + + def _cb(resp, ch=None): + assert resp == message + pubnub.unsubscribe(channel) + + def _connect(resp): + pubnub.publish(channel,message) + + def _error(resp): + assert False + + pubnub.subscribe(channel, callback=_cb, connect=_connect, error=_error) + + +# Publish and receive string (Encryption enabled) +def test_6(): + + channel = "test_6-" + str(time.time()) + message = "I am a string" + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + pubnub_enc.publish(channel,message) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive array (Encryption enabled) +def test_7(): + + channel = "test_7-" + str(time.time()) + message = [1,2] + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + pubnub.publish(channel,message) + + def _error(resp): + assert False + + pubnub.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive json object (Encryption enabled) +def test_8(): + + channel = "test_8-" + str(time.time()) + message = { "a" : "b" } + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + pubnub_enc.publish(channel,message) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive number (Encryption enabled) +def test_9(): + + channel = "test_9-" + str(time.time()) + message = 100 + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + pubnub_enc.publish(channel,message) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive number string (Encryption enabled) +def test_10(): + + channel = "test_10-" + str(time.time()) + message = "100" + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + pubnub_enc.publish(channel,message) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive object string (Encryption enabled) +def test_11(): + + channel = "test_11-" + str(time.time()) + message = '{"a" : "b"}' + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + pubnub_enc.publish(channel,message) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) + +# Publish and receive array string (Encryption enabled) +def test_12(): + + channel = "test_12-" + str(time.time()) + message = '[1,2]' + + def _cb(resp, ch=None): + assert resp == message + pubnub_enc.unsubscribe(channel) + + def _connect(resp): + pubnub_enc.publish(channel,message) + + def _error(resp): + assert False + + pubnub_enc.subscribe(channel, callback=_cb, connect=_connect, error=_error) diff --git a/python/tests/unit-test.py b/python/tests/unit-test.py deleted file mode 100755 index 1737ace..0000000 --- a/python/tests/unit-test.py +++ /dev/null @@ -1,66 +0,0 @@ -## www.pubnub.com - PubNub Real-time push service in the cloud. -# coding=utf8 - -## PubNub Real-time Push APIs and Notifications Framework -## Copyright (c) 2010 Stephen Blum -## http://www.pubnub.com/ - -## ----------------------------------- -## PubNub 3.0 Real-time Push Cloud API -## ----------------------------------- - -import sys -sys.path.append('.') -sys.path.append('..') -sys.path.append('../common') -from Pubnub import Pubnub - -publish_key = len(sys.argv) > 1 and sys.argv[1] or 'demo' -subscribe_key = len(sys.argv) > 2 and sys.argv[2] or 'demo' -secret_key = len(sys.argv) > 3 and sys.argv[3] or None -ssl_on = len(sys.argv) > 4 and bool(sys.argv[4]) or False - - -## ----------------------------------------------------------------------- -## Initiat Class -## ----------------------------------------------------------------------- - -pubnub = Pubnub( publish_key, subscribe_key, secret_key, ssl_on ) -crazy = 'demo' - -## --------------------------------------------------------------------------- -## Unit Test Function -## --------------------------------------------------------------------------- -def test( trial, name ) : - if trial : - print( 'PASS: ' + name ) - else : - print( 'FAIL: ' + name ) - -## ----------------------------------------------------------------------- -## Publish Example -## ----------------------------------------------------------------------- -publish_success = pubnub.publish({ - 'channel' : crazy, - 'message' : crazy -}) -test( publish_success[0] == 1, 'Publish First Message Success' ) - -## ----------------------------------------------------------------------- -## History Example -## ----------------------------------------------------------------------- -history = pubnub.history({ - 'channel' : crazy, - 'limit' : 1 -}) -test( - history[0].encode('utf-8') == crazy, - 'History Message: ' + history[0] -) -test( len(history) == 1, 'History Message Count' ) - -## ----------------------------------------------------------------------- -## PubNub Server Time Example -## ----------------------------------------------------------------------- -timestamp = pubnub.time() -test( timestamp > 0, 'PubNub Server Time: ' + str(timestamp) ) diff --git a/python/unassembled/Platform.py b/python/unassembled/Platform.py deleted file mode 100644 index f598a98..0000000 --- a/python/unassembled/Platform.py +++ /dev/null @@ -1,40 +0,0 @@ - -class Pubnub(PubnubCore): - def __init__( - self, - publish_key, - subscribe_key, - secret_key = False, - cipher_key = False, - ssl_on = False, - origin = 'pubsub.pubnub.com', - pres_uuid = None - ) : - super(Pubnub, self).__init__( - publish_key = publish_key, - subscribe_key = subscribe_key, - secret_key = secret_key, - cipher_key = cipher_key, - ssl_on = ssl_on, - origin = origin, - uuid = pres_uuid - ) - - def _request( self, request, callback = None ) : - ## Build URL - url = self.getUrl(request) - - ## Send Request Expecting JSONP Response - try: - try: usock = urllib2.urlopen( url, None, 310 ) - except TypeError: usock = urllib2.urlopen( url, None ) - response = usock.read() - usock.close() - resp_json = json.loads(response) - except: - return None - - if (callback): - callback(resp_json) - else: - return resp_json diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..ee01836 --- /dev/null +++ b/setup.py @@ -0,0 +1,26 @@ +from setuptools import setup, find_packages + +setup( + name='pubnub', + version='3.5.0', + description='PubNub Real-time push service in the cloud', + author='Stephen Blum', + author_email='support@pubnub.com', + url='http://pubnub.com', + py_modules=['Pubnub'], + license='MIT', + classifiers=( + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'Programming Language :: Python', + 'License :: OSI Approved :: MIT License', + 'Operating System :: OS Independent', + 'Topic :: Internet :: WWW/HTTP', + 'Topic :: Software Development :: Libraries :: Python Modules', + ), + install_requires=[ + 'pycrypto>=2.6.1', + 'requests>=2.3.0' + ], + zip_safe=False, +) |
