Skip to content

Commit

Permalink
PubNub SDK v4.7.0 release.
Browse files Browse the repository at this point in the history
  • Loading branch information
client-engineering-bot committed Nov 19, 2020
1 parent 11a2249 commit 75a79dd
Show file tree
Hide file tree
Showing 40 changed files with 901 additions and 383 deletions.
8 changes: 7 additions & 1 deletion .pubnub.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
name: python
version: 4.6.1
version: 4.7.0
schema: 1
scm: github.com/pubnub/python
changelog:
- version: v4
date: Nov 19, 2020
changes:
-
text: "Within this release problems with double PAM calls encoding and Publish oriented bugs were fixed."
type: bug
- version: v4.6.1
date: Oct 27, 2020
changes:
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## [v4](https://github.com/pubnub/python/releases/tag/v4)

[Full Changelog](https://github.com/pubnub/python/compare/v4.6.1...v4)

- 🐛 Within this release problems with double PAM calls encoding and Publish oriented bugs were fixed.

## [v4.6.1](https://github.com/pubnub/python/releases/tag/v4.6.1)

[Full Changelog](https://github.com/pubnub/python/compare/v4.6.0...v4.6.1)
Expand Down
84 changes: 80 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,92 @@
# PubNub Python SDK (V4)

[![Build Status](https://travis-ci.org/pubnub/python.svg?branch=master)](https://travis-ci.org/pubnub/python)
[![codecov](https://codecov.io/gh/pubnub/python/branch/master/graph/badge.svg)](https://codecov.io/gh/pubnub/python)
[![PyPI](https://img.shields.io/pypi/v/pubnub.svg)](https://pypi.python.org/pypi/pubnub/)
[![PyPI](https://img.shields.io/pypi/pyversions/pubnub.svg)](https://pypi.python.org/pypi/pubnub/)
[![Docs](https://img.shields.io/badge/docs-online-blue.svg)](https://www.pubnub.com/docs/python/pubnub-python-sdk-v4)

The SDK supports Python 2.7, 3.4, 3.5, 3.6, 3.7 and pypy.
This is the official PubNub Python SDK repository.

PubNub takes care of the infrastructure and APIs needed for the realtime communication layer of your application. Work on your app's logic and let PubNub handle sending and receiving data across the world in less than 100ms.

## Get keys

You will need the publish and subscribe keys to authenticate your app. Get your keys from the [Admin Portal](https://dashboard.pubnub.com/login).

## Configure PubNub

1. Integrate the Python SDK into your project using `pip`:

```bash
pip install pubnub
```

2. Configure your keys:

```python
pnconfig = PNConfiguration()
pnconfig.subscribe_key = 'mySubscribeKey'
pnconfig.publish_key = 'myPublishKey'
pnconfig.uuid = 'myUniqueUUID'
pubnub = PubNub(pnconfig)
```

## Add event listeners

```python
class SubscribeHandler(SubscribeCallback):
def status(self, pubnub, event):
print("Is there an error? ", event.is_error())
print("Status value for category: %s" % event.category)
print("Status value for error_data: %s" % event.error_data)
print("Status value for error: %s" % event.error)
print("Status value for status_code: %s" % event.status_code)
print("Status value for operation: %s" % event.operation)
print("Status value for tls_enabled: %s" % event.tls_enabled)
print("Status value for uuid: %s" % event.uuid)
print("Status value for auth_key: %s" % event.auth_key)
print("Status value for origin: %s" % event.origin)
print("Status value for client_request: %s" % event.client_request)
print("Status value for client_response: %s" % event.client_response)
print("Status value for original_response: %s" % event.original_response)
print("Status value for affected_channels: %s" % event.affected_channels)
print("Status value for affected_groups: %s" % event.affected_groups)
def presence(self, pubnub, presence):
pass # Handle incoming presence data
def message(self, pubnub, message):
pass # Handle incoming messages
def signal(self, pubnub, signal):
pass # Handle incoming signals
pubnub.add_listener(SubscribeHandler())
```
## Publish/subscribe
```python
def my_publish_callback(envelope, status):
if status.is_error():
... #handle error here
else:
... #handle result here
pubnub.publish().channel('my_channel').message('Hello world!').pn_async(my_publish_callback)
pubnub.subscribe().channels('my_channel').execute()
```
## Documentation
Please review our documentation and examples on the [PubNub Website](https://www.pubnub.com/docs/python/pubnub-python-sdk-v4)
* [Build your first realtime Python app with PubNub](https://www.pubnub.com/docs/platform/quickstarts/python)
* [API reference for Python](https://www.pubnub.com/docs/python/pubnub-python-sdk)
* [API reference for Python (Tornado)](https://www.pubnub.com/docs/python-tornado/pubnub-python-sdk)
* [API reference for Python (asyncio)](https://www.pubnub.com/docs/python-aiohttp/pubnub-python-sdk)
## Communication
## Support
- If you **need help** or have a **general question**, contact <support@pubnub.com>
If you **need help** or have a **general question**, contact support@pubnub.com.
22 changes: 18 additions & 4 deletions pubnub/endpoints/access/grant.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,20 @@ def ttl(self, ttl):
self._ttl = ttl
return self

def encoded_params(self):
params = {}

if self._auth_keys:
params['auth'] = utils.join_items_and_encode(self._auth_keys)

if self._channels:
params['channel'] = utils.join_channels(self._channels)

if self._groups:
params['channel-group'] = utils.join_items_and_encode(self._groups)

return params

def custom_params(self):
params = {}

Expand All @@ -66,13 +80,13 @@ def custom_params(self):
if self._delete is not None:
params['d'] = '1' if self._delete is True else '0'

if len(self._auth_keys) > 0:
params['auth'] = utils.join_items_and_encode(self._auth_keys)
if self._auth_keys:
params['auth'] = utils.join_items(self._auth_keys)

if len(self._channels) > 0:
if self._channels:
params['channel'] = utils.join_items(self._channels)

if len(self._groups) > 0:
if self._groups:
params['channel-group'] = utils.join_items(self._groups)

if self._ttl is not None:
Expand Down
14 changes: 6 additions & 8 deletions pubnub/endpoints/endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import logging

from pubnub import utils
from pubnub.enums import PNStatusCategory, PNOperationType
from pubnub.enums import PNStatusCategory
from pubnub.errors import (
PNERR_SUBSCRIBE_KEY_MISSING, PNERR_PUBLISH_KEY_MISSING, PNERR_CHANNEL_OR_GROUP_MISSING,
PNERR_SECRET_KEY_MISSING, PNERR_CHANNEL_MISSING, PNERR_FILE_OBJECT_MISSING,
Expand Down Expand Up @@ -99,6 +99,9 @@ def build_file_upload_request(self):
def non_json_response(self):
return False

def encoded_params(self):
return {}

def options(self):
return RequestOptions(
path=self.build_path(),
Expand Down Expand Up @@ -171,7 +174,6 @@ def handler():

def build_params_callback(self):
def callback(params_to_merge):
operation_type = self.operation_type()
custom_params = self.custom_params()
custom_params.update(params_to_merge)

Expand All @@ -196,11 +198,7 @@ def callback(params_to_merge):
if self.pubnub.config.secret_key is not None:
utils.sign_request(self, self.pubnub, custom_params, self.http_method(), self.build_data())

# REVIEW: add encoder map to not hardcode encoding here
if operation_type == PNOperationType.PNPublishOperation and 'meta' in custom_params:
custom_params['meta'] = utils.url_encode(custom_params['meta'])
if operation_type == PNOperationType.PNSetStateOperation and 'state' in custom_params:
custom_params['state'] = utils.url_encode(custom_params['state'])
custom_params.update(self.encoded_params())

# reassign since pnsdk should be signed unencoded
custom_params['pnsdk'] = utils.url_encode(self.pubnub.sdk_name)
Expand Down Expand Up @@ -268,7 +266,7 @@ def create_status(self, category, response, response_info, exception):
pn_status.operation = self.operation_type()
pn_status.category = category
pn_status.affected_channels = self.affected_channels()
pn_status.affected_channels_groups = self.affected_channels_groups()
pn_status.affected_groups = self.affected_channels_groups()

return pn_status

Expand Down
15 changes: 10 additions & 5 deletions pubnub/endpoints/file_operations/publish_file_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
from pubnub.enums import HttpMethod, PNOperationType
from pubnub import utils
from pubnub.models.consumer.file import PNPublishFileMessageResult
from pubnub.endpoints.mixins import TimeTokenOverrideMixin


class PublishFileMessage(FileOperationEndpoint):
class PublishFileMessage(FileOperationEndpoint, TimeTokenOverrideMixin):
PUBLISH_FILE_MESSAGE = "/v1/files/publish-file/%s/%s/0/%s/0/%s"

def __init__(self, pubnub):
FileOperationEndpoint.__init__(self, pubnub)
super(PublishFileMessage, self).__init__(pubnub)
self._file_id = None
self._file_name = None
self._pubnub = pubnub
Expand All @@ -17,6 +18,8 @@ def __init__(self, pubnub):
self._ttl = 0
self._meta = None
self._cipher_key = None
self._replicate = None
self._ptto = None

def meta(self, meta):
self._meta = meta
Expand Down Expand Up @@ -79,11 +82,13 @@ def http_method(self):
return HttpMethod.GET

def custom_params(self):
return {
params = TimeTokenOverrideMixin.custom_params(self)
params.update({
"meta": utils.url_write(self._meta),
"ttl": self._ttl,
"store": self._should_store
}
"store": 1 if self._should_store else 0
})
return params

def is_auth_required(self):
return True
Expand Down
9 changes: 7 additions & 2 deletions pubnub/endpoints/file_operations/send_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
from pubnub.endpoints.file_operations.publish_file_message import PublishFileMessage
from pubnub.endpoints.file_operations.fetch_upload_details import FetchFileUploadS3Data
from pubnub.request_handlers.requests_handler import RequestsRequestHandler
from pubnub.endpoints.mixins import TimeTokenOverrideMixin


class SendFileNative(FileOperationEndpoint):
class SendFileNative(FileOperationEndpoint, TimeTokenOverrideMixin):
def __init__(self, pubnub):
FileOperationEndpoint.__init__(self, pubnub)
super(SendFileNative, self).__init__(pubnub)
self._file_name = None
self._pubnub = pubnub
self._file_upload_envelope = None
Expand All @@ -21,6 +22,8 @@ def __init__(self, pubnub):
self._meta = None
self._cipher_key = None
self._file_object = None
self._replicate = None
self._ptto = None

def file_object(self, fd):
self._file_object = fd
Expand Down Expand Up @@ -128,6 +131,8 @@ def sync(self):
file_name(response_envelope.result.name).\
should_store(self._should_store).\
ttl(self._ttl).\
replicate(self._replicate).\
ptto(self._ptto).\
cipher_key(self._cipher_key).sync()

response_envelope.result.timestamp = publish_file_response.result.timestamp
Expand Down
35 changes: 35 additions & 0 deletions pubnub/endpoints/mixins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import six

from pubnub.errors import PNERR_UUID_MISSING
from pubnub.exceptions import PubNubException


class UUIDValidatorMixin:
def validate_uuid(self):
if self._uuid is None or not isinstance(self._uuid, six.string_types):
raise PubNubException(pn_error=PNERR_UUID_MISSING)


class TimeTokenOverrideMixin:
def replicate(self, replicate):
self._replicate = replicate
return self

def ptto(self, timetoken):
if timetoken:
assert isinstance(timetoken, six.integer_types)
self._ptto = timetoken
return self

def custom_params(self):
params = {}
if self._replicate is not None:
if self._replicate:
params["norep"] = "false"
else:
params["norep"] = "true"

if self._ptto:
params["ptto"] = self._ptto

return params
2 changes: 1 addition & 1 deletion pubnub/endpoints/presence/get_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from pubnub.endpoints.endpoint import Endpoint
from pubnub.enums import HttpMethod, PNOperationType
from pubnub.models.consumer.presence import PNGetStateResult
from pubnub.endpoints.validators import UUIDValidatorMixin
from pubnub.endpoints.mixins import UUIDValidatorMixin


class GetState(Endpoint, UUIDValidatorMixin):
Expand Down
5 changes: 5 additions & 0 deletions pubnub/endpoints/presence/set_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ def state(self, state):
self._state = state
return self

def encoded_params(self):
return {
"state": utils.url_write(self._state)
}

def custom_params(self):
if self._subscription_manager is not None:
self._subscription_manager.adapt_state_builder(StateOperation(
Expand Down
2 changes: 1 addition & 1 deletion pubnub/endpoints/presence/where_now.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from pubnub.endpoints.endpoint import Endpoint
from pubnub.enums import HttpMethod, PNOperationType
from pubnub.models.consumer.presence import PNWhereNowResult
from pubnub.endpoints.validators import UUIDValidatorMixin
from pubnub.endpoints.mixins import UUIDValidatorMixin


class WhereNow(Endpoint, UUIDValidatorMixin):
Expand Down
Loading

0 comments on commit 75a79dd

Please sign in to comment.