diff options
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, +) | 
