From 4ad0b6681b94ab9a2b8bdb0561ab9b78e8cef1ea Mon Sep 17 00:00:00 2001 From: QSD_s Date: Fri, 21 Feb 2020 05:37:55 +0100 Subject: [PATCH 1/5] Add APNS2 Push support --- .pubnub.yml | 14 ++++++- CHANGELOG.md | 6 +++ pubnub/endpoints/push/add_channels_to_push.py | 39 +++++++++++++++--- pubnub/endpoints/push/list_push_provisions.py | 37 ++++++++++++++--- .../push/remove_channels_from_push.py | 40 ++++++++++++++++--- pubnub/endpoints/push/remove_device.py | 37 ++++++++++++++--- pubnub/enums.py | 6 +++ pubnub/errors.py | 2 + pubnub/pubnub_core.py | 2 +- setup.py | 2 +- 10 files changed, 162 insertions(+), 23 deletions(-) diff --git a/.pubnub.yml b/.pubnub.yml index ace3b9b8..ec23fc64 100644 --- a/.pubnub.yml +++ b/.pubnub.yml @@ -1,8 +1,13 @@ name: python -version: 4.3.0 +version: 4.3.1 schema: 1 scm: github.com/pubnub/python changelog: + - version: v4.3.1 + date: Feb 20, 2020 + changes: + - type: feature + text: Add support for APNS2 Push API - version: v4.3.0 date: Jan 28, 2020 changes: @@ -178,11 +183,18 @@ features: - CHANNEL-GROUPS-REMOVE-CHANNELS - CHANNEL-GROUPS-REMOVE-GROUPS - CHANNEL-GROUPS-LIST-CHANNELS-IN-GROUP + others: + - TELEMETRY + - CREATE-PUSH-PAYLOAD push: - PUSH-ADD-DEVICE-TO-CHANNELS - PUSH-REMOVE-DEVICE-FROM-CHANNELS - PUSH-LIST-CHANNELS-FROM-DEVICE - PUSH-REMOVE-DEVICE + - PUSH-TYPE-APNS + - PUSH-TYPE-APNS2 + - PUSH-TYPE-FCM + - PUSH-TYPE-MPNS presence: - PRESENCE-HERE-NOW - PRESENCE-WHERE-NOW diff --git a/CHANGELOG.md b/CHANGELOG.md index 69a39427..cfa4004e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [4.3.1](https://github.com/pubnub/python/tree/v4.3.1) + + [Full Changelog](https://github.com/pubnub/python/compare/v4.3.0...v4.3.1) + +- 🌟 Add support for APNS2 Push API + ## [4.3.0](https://github.com/pubnub/python/tree/v4.3.0) [Full Changelog](https://github.com/pubnub/python/compare/v4.2.1...v4.3.0) diff --git a/pubnub/endpoints/push/add_channels_to_push.py b/pubnub/endpoints/push/add_channels_to_push.py index 50d94b63..db131f1c 100644 --- a/pubnub/endpoints/push/add_channels_to_push.py +++ b/pubnub/endpoints/push/add_channels_to_push.py @@ -1,9 +1,10 @@ import six from pubnub.endpoints.endpoint import Endpoint -from pubnub.errors import PNERR_CHANNEL_MISSING, PNERR_PUSH_DEVICE_MISSING, PNERROR_PUSH_TYPE_MISSING +from pubnub.errors import PNERR_CHANNEL_MISSING, PNERR_PUSH_DEVICE_MISSING, PNERROR_PUSH_TYPE_MISSING, \ + PNERR_PUSH_TOPIC_MISSING from pubnub.exceptions import PubNubException -from pubnub.enums import HttpMethod, PNOperationType +from pubnub.enums import HttpMethod, PNOperationType, PNPushType, PNPushEnvironment from pubnub.models.consumer.push import PNPushAddChannelResult from pubnub import utils @@ -11,12 +12,16 @@ class AddChannelsToPush(Endpoint): # v1/push/sub-key/{subKey}/devices/{pushToken} ADD_PATH = "/v1/push/sub-key/%s/devices/%s" + # v2/push/sub-key/{subKey}/devices-apns2/{deviceApns2} + ADD_PATH_APNS2 = "/v2/push/sub-key/%s/devices-apns2/%s" def __init__(self, pubnub): Endpoint.__init__(self, pubnub) self._channels = None self._device_id = None self._push_type = None + self._topic = None + self._environment = None def channels(self, channels): self._channels = channels @@ -30,17 +35,34 @@ def push_type(self, push_type): self._push_type = push_type return self + def topic(self, topic): + self._topic = topic + return self + + def environment(self, environment): + self._environment = environment + return self + def custom_params(self): params = {} params['add'] = utils.join_items(self._channels) - params['type'] = utils.push_type_to_string(self._push_type) + + if self._push_type != PNPushType.APNS2: + params['type'] = utils.push_type_to_string(self._push_type) + else: + params['environment'] = self._environment + params['topic'] = self._topic return params def build_path(self): - return AddChannelsToPush.ADD_PATH % ( - self.pubnub.config.subscribe_key, self._device_id) + if self._push_type != PNPushType.APNS2: + return AddChannelsToPush.ADD_PATH % ( + self.pubnub.config.subscribe_key, self._device_id) + else: + return AddChannelsToPush.ADD_PATH_APNS2 % ( + self.pubnub.config.subscribe_key, self._device_id) def http_method(self): return HttpMethod.GET @@ -57,6 +79,13 @@ def validate_params(self): if self._push_type is None: raise PubNubException(pn_error=PNERROR_PUSH_TYPE_MISSING) + if self._push_type == PNPushType.APNS2: + if not isinstance(self._topic, six.string_types) or len(self._topic) == 0: + raise PubNubException(pn_error=PNERR_PUSH_TOPIC_MISSING) + + if self._environment is None: + self._environment = PNPushEnvironment.DEVELOPMENT + def create_response(self, envelope): return PNPushAddChannelResult() diff --git a/pubnub/endpoints/push/list_push_provisions.py b/pubnub/endpoints/push/list_push_provisions.py index 04c78a46..bbfb0ddd 100644 --- a/pubnub/endpoints/push/list_push_provisions.py +++ b/pubnub/endpoints/push/list_push_provisions.py @@ -1,9 +1,9 @@ import six from pubnub.endpoints.endpoint import Endpoint -from pubnub.errors import PNERR_PUSH_DEVICE_MISSING, PNERROR_PUSH_TYPE_MISSING +from pubnub.errors import PNERR_PUSH_DEVICE_MISSING, PNERROR_PUSH_TYPE_MISSING, PNERR_PUSH_TOPIC_MISSING from pubnub.exceptions import PubNubException -from pubnub.enums import HttpMethod, PNOperationType +from pubnub.enums import HttpMethod, PNOperationType, PNPushType, PNPushEnvironment from pubnub.models.consumer.push import PNPushListProvisionsResult from pubnub import utils @@ -11,11 +11,15 @@ class ListPushProvisions(Endpoint): # v1/push/sub-key/{subKey}/devices/{pushToken} LIST_PATH = "/v1/push/sub-key/%s/devices/%s" + # v2/push/sub-key/{subKey}/devices-apns2/{deviceApns2} + LIST_PATH_APNS2 = "/v2/push/sub-key/%s/devices-apns2/%s" def __init__(self, pubnub): Endpoint.__init__(self, pubnub) self._device_id = None self._push_type = None + self._topic = None + self._environment = None def device_id(self, device_id): self._device_id = device_id @@ -25,16 +29,32 @@ def push_type(self, push_type): self._push_type = push_type return self + def topic(self, topic): + self._topic = topic + return self + + def environment(self, environment): + self._environment = environment + return self + def custom_params(self): params = {} - params['type'] = utils.push_type_to_string(self._push_type) + if self._push_type != PNPushType.APNS2: + params['type'] = utils.push_type_to_string(self._push_type) + else: + params['environment'] = self._environment + params['topic'] = self._topic return params def build_path(self): - return ListPushProvisions.LIST_PATH % ( - self.pubnub.config.subscribe_key, self._device_id) + if self._push_type != PNPushType.APNS2: + return ListPushProvisions.LIST_PATH % ( + self.pubnub.config.subscribe_key, self._device_id) + else: + return ListPushProvisions.LIST_PATH_APNS2 % ( + self.pubnub.config.subscribe_key, self._device_id) def http_method(self): return HttpMethod.GET @@ -48,6 +68,13 @@ def validate_params(self): if self._push_type is None: raise PubNubException(pn_error=PNERROR_PUSH_TYPE_MISSING) + if self._push_type == PNPushType.APNS2: + if not isinstance(self._topic, six.string_types) or len(self._topic) == 0: + raise PubNubException(pn_error=PNERR_PUSH_TOPIC_MISSING) + + if self._environment is None: + self._environment = PNPushEnvironment.DEVELOPMENT + def create_response(self, channels): if channels is not None and len(channels) > 0 and isinstance(channels, list): return PNPushListProvisionsResult(channels) diff --git a/pubnub/endpoints/push/remove_channels_from_push.py b/pubnub/endpoints/push/remove_channels_from_push.py index 063d4151..5d1a5563 100644 --- a/pubnub/endpoints/push/remove_channels_from_push.py +++ b/pubnub/endpoints/push/remove_channels_from_push.py @@ -1,9 +1,10 @@ import six from pubnub.endpoints.endpoint import Endpoint -from pubnub.errors import PNERR_CHANNEL_MISSING, PNERR_PUSH_DEVICE_MISSING, PNERROR_PUSH_TYPE_MISSING +from pubnub.errors import PNERR_CHANNEL_MISSING, PNERR_PUSH_DEVICE_MISSING, PNERROR_PUSH_TYPE_MISSING, \ + PNERR_PUSH_TOPIC_MISSING from pubnub.exceptions import PubNubException -from pubnub.enums import HttpMethod, PNOperationType +from pubnub.enums import HttpMethod, PNOperationType, PNPushType, PNPushEnvironment from pubnub.models.consumer.push import PNPushRemoveChannelResult from pubnub import utils @@ -11,12 +12,16 @@ class RemoveChannelsFromPush(Endpoint): # v1/push/sub-key/{subKey}/devices/{pushToken} REMOVE_PATH = "/v1/push/sub-key/%s/devices/%s" + # v2/push/sub-key/{subKey}/devices-apns2/{deviceApns2} + REMOVE_PATH_APNS2 = "/v2/push/sub-key/%s/devices-apns2/%s" def __init__(self, pubnub): Endpoint.__init__(self, pubnub) self._channels = None self._device_id = None self._push_type = None + self._topic = None + self._environment = None def channels(self, channels): self._channels = channels @@ -30,14 +35,32 @@ def push_type(self, push_type): self._push_type = push_type return self + def topic(self, topic): + self._topic = topic + return self + + def environment(self, environment): + self._environment = environment + return self + def custom_params(self): - params = {'remove': utils.join_items(self._channels), 'type': utils.push_type_to_string(self._push_type)} + params = {'remove': utils.join_items(self._channels)} + + if self._push_type != PNPushType.APNS2: + params['type'] = utils.push_type_to_string(self._push_type) + else: + params['environment'] = self._environment + params['topic'] = self._topic return params def build_path(self): - return RemoveChannelsFromPush.REMOVE_PATH % ( - self.pubnub.config.subscribe_key, self._device_id) + if self._push_type != PNPushType.APNS2: + return RemoveChannelsFromPush.REMOVE_PATH % ( + self.pubnub.config.subscribe_key, self._device_id) + else: + return RemoveChannelsFromPush.REMOVE_PATH_APNS2 % ( + self.pubnub.config.subscribe_key, self._device_id) def http_method(self): return HttpMethod.GET @@ -54,6 +77,13 @@ def validate_params(self): if self._push_type is None: raise PubNubException(pn_error=PNERROR_PUSH_TYPE_MISSING) + if self._push_type == PNPushType.APNS2: + if not isinstance(self._topic, six.string_types) or len(self._topic) == 0: + raise PubNubException(pn_error=PNERR_PUSH_TOPIC_MISSING) + + if self._environment is None: + self._environment = PNPushEnvironment.DEVELOPMENT + def create_response(self, envelope): return PNPushRemoveChannelResult() diff --git a/pubnub/endpoints/push/remove_device.py b/pubnub/endpoints/push/remove_device.py index 2c4c6924..4fa6fe2f 100644 --- a/pubnub/endpoints/push/remove_device.py +++ b/pubnub/endpoints/push/remove_device.py @@ -1,9 +1,9 @@ import six from pubnub.endpoints.endpoint import Endpoint -from pubnub.errors import PNERR_PUSH_DEVICE_MISSING, PNERROR_PUSH_TYPE_MISSING +from pubnub.errors import PNERR_PUSH_DEVICE_MISSING, PNERROR_PUSH_TYPE_MISSING, PNERR_PUSH_TOPIC_MISSING from pubnub.exceptions import PubNubException -from pubnub.enums import HttpMethod, PNOperationType +from pubnub.enums import HttpMethod, PNOperationType, PNPushType, PNPushEnvironment from pubnub.models.consumer.push import PNPushRemoveAllChannelsResult from pubnub import utils @@ -11,11 +11,15 @@ class RemoveDeviceFromPush(Endpoint): # v1/push/sub-key/{subKey}/devices/{pushToken}/remove REMOVE_PATH = "/v1/push/sub-key/%s/devices/%s/remove" + # v2/push/sub-key/{subKey}/devices-apns2/{deviceApns2}/remove + REMOVE_PATH_APNS2 = "/v2/push/sub-key/%s/devices-apns2/%s/remove" def __init__(self, pubnub): Endpoint.__init__(self, pubnub) self._device_id = None self._push_type = None + self._topic = None + self._environment = None def device_id(self, device_id): self._device_id = device_id @@ -25,16 +29,32 @@ def push_type(self, push_type): self._push_type = push_type return self + def topic(self, topic): + self._topic = topic + return self + + def environment(self, environment): + self._environment = environment + return self + def custom_params(self): params = {} - params['type'] = utils.push_type_to_string(self._push_type) + if self._push_type != PNPushType.APNS2: + params['type'] = utils.push_type_to_string(self._push_type) + else: + params['environment'] = self._environment + params['topic'] = self._topic return params def build_path(self): - return RemoveDeviceFromPush.REMOVE_PATH % ( - self.pubnub.config.subscribe_key, self._device_id) + if self._push_type != PNPushType.APNS2: + return RemoveDeviceFromPush.REMOVE_PATH % ( + self.pubnub.config.subscribe_key, self._device_id) + else: + return RemoveDeviceFromPush.REMOVE_PATH_APNS2 % ( + self.pubnub.config.subscribe_key, self._device_id) def http_method(self): return HttpMethod.GET @@ -48,6 +68,13 @@ def validate_params(self): if self._push_type is None: raise PubNubException(pn_error=PNERROR_PUSH_TYPE_MISSING) + if self._push_type == PNPushType.APNS2: + if not isinstance(self._topic, six.string_types) or len(self._topic) == 0: + raise PubNubException(pn_error=PNERR_PUSH_TOPIC_MISSING) + + if self._environment is None: + self._environment = PNPushEnvironment.DEVELOPMENT + def create_response(self, envelope): return PNPushRemoveAllChannelsResult() diff --git a/pubnub/enums.py b/pubnub/enums.py index 57ce831b..f9ec0355 100644 --- a/pubnub/enums.py +++ b/pubnub/enums.py @@ -103,6 +103,7 @@ class PNPushType(object): APNS = 1 MPNS = 2 GCM = 3 + APNS2 = 4 class PNResourceType(object): @@ -115,3 +116,8 @@ class PNResourceType(object): class PNMatchType(object): RESOURCE = "resource" PATTERN = "pattern" + + +class PNPushEnvironment(object): + DEVELOPMENT = "development" + PRODUCTION = "production" diff --git a/pubnub/errors.py b/pubnub/errors.py index dc6b8fe8..b81b7082 100644 --- a/pubnub/errors.py +++ b/pubnub/errors.py @@ -41,3 +41,5 @@ PNERR_HISTORY_MESSAGE_ACTIONS_MULTIPLE_CHANNELS = "History can return message action data for a single channel only. " \ "Either pass a single channel or disable the include_message_action" \ "s flag. " + +PNERR_PUSH_TOPIC_MISSING = "Push notification topic is missing. Required only if push type is APNS2." diff --git a/pubnub/pubnub_core.py b/pubnub/pubnub_core.py index e5827662..9363d6c6 100644 --- a/pubnub/pubnub_core.py +++ b/pubnub/pubnub_core.py @@ -56,7 +56,7 @@ class PubNubCore: """A base class for PubNub Python API implementations""" - SDK_VERSION = "4.3.0" + SDK_VERSION = "4.3.1" SDK_NAME = "PubNub-Python" TIMESTAMP_DIVIDER = 1000 diff --git a/setup.py b/setup.py index 05487a0e..62f04d6f 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name='pubnub', - version='4.3.0', + version='4.3.1', description='PubNub Real-time push service in the cloud', author='PubNub', author_email='support@pubnub.com', From 6002fd89d05a271eb8d8aa4f65807958e5ce306d Mon Sep 17 00:00:00 2001 From: QSD_s Date: Fri, 21 Feb 2020 05:58:09 +0100 Subject: [PATCH 2/5] Update functional tests with APNS2 builder method tests. --- .../push/test_add_channels_to_push.py | 17 +++++++++++++++++ .../push/test_list_push_provisions.py | 18 ++++++++++++++++++ .../push/test_remove_channels_from_push.py | 17 +++++++++++++++++ .../push/test_remove_device_from_push.py | 14 ++++++++++++++ 4 files changed, 66 insertions(+) diff --git a/tests/functional/push/test_add_channels_to_push.py b/tests/functional/push/test_add_channels_to_push.py index e3bd8542..b2a86c3c 100644 --- a/tests/functional/push/test_add_channels_to_push.py +++ b/tests/functional/push/test_add_channels_to_push.py @@ -71,3 +71,20 @@ def test_push_add_google(self): }) self.assertEqual(self.add_channels._channels, ['ch1', 'ch2', 'ch3']) + + def test_push_add_single_channel_apns2(self): + self.add_channels.channels(['ch']).push_type(pubnub.enums.PNPushType.APNS2).device_id("coolDevice")\ + .environment(pubnub.enums.PNPushEnvironment.PRODUCTION).topic("testTopic") + + params = (pnconf.subscribe_key, "coolDevice") + self.assertEqual(self.add_channels.build_path(), AddChannelsToPush.ADD_PATH_APNS2 % params) + + self.assertEqual(self.add_channels.build_params_callback()({}), { + 'pnsdk': sdk_name, + 'uuid': self.pubnub.uuid, + 'add': 'ch', + 'environment': pubnub.enums.PNPushEnvironment.PRODUCTION, + 'topic': 'testTopic' + }) + + self.assertEqual(self.add_channels._channels, ['ch']) diff --git a/tests/functional/push/test_list_push_provisions.py b/tests/functional/push/test_list_push_provisions.py index 94296dca..171d6acb 100644 --- a/tests/functional/push/test_list_push_provisions.py +++ b/tests/functional/push/test_list_push_provisions.py @@ -9,6 +9,9 @@ from unittest.mock import MagicMock from pubnub.pubnub import PubNub + +import pubnub.enums + from tests.helper import pnconf, sdk_name from pubnub.managers import TelemetryManager @@ -63,3 +66,18 @@ def test_list_channel_group_mpns(self): 'uuid': self.pubnub.uuid, 'type': 'mpns' }) + + def test_list_channel_group_apns2(self): + self.list_push.push_type(PNPushType.APNS2).device_id('coolDevice')\ + .environment(pubnub.enums.PNPushEnvironment.PRODUCTION).topic("testTopic") + + self.assertEqual(self.list_push.build_path(), + ListPushProvisions.LIST_PATH_APNS2 % ( + pnconf.subscribe_key, "coolDevice")) + + self.assertEqual(self.list_push.build_params_callback()({}), { + 'pnsdk': sdk_name, + 'uuid': self.pubnub.uuid, + 'environment': pubnub.enums.PNPushEnvironment.PRODUCTION, + 'topic': 'testTopic' + }) diff --git a/tests/functional/push/test_remove_channels_from_push.py b/tests/functional/push/test_remove_channels_from_push.py index c5faeca6..1e03bbec 100644 --- a/tests/functional/push/test_remove_channels_from_push.py +++ b/tests/functional/push/test_remove_channels_from_push.py @@ -72,3 +72,20 @@ def test_push_remove_google(self): }) self.assertEqual(self.remove_channels._channels, ['ch1', 'ch2', 'ch3']) + + def test_push_remove_single_channel_apns2(self): + self.remove_channels.channels(['ch']).push_type(pubnub.enums.PNPushType.APNS2).device_id("coolDevice")\ + .environment(pubnub.enums.PNPushEnvironment.PRODUCTION).topic("testTopic") + + params = (pnconf.subscribe_key, "coolDevice") + self.assertEqual(self.remove_channels.build_path(), RemoveChannelsFromPush.REMOVE_PATH_APNS2 % params) + + self.assertEqual(self.remove_channels.build_params_callback()({}), { + 'pnsdk': sdk_name, + 'uuid': self.pubnub.uuid, + 'remove': 'ch', + 'environment': pubnub.enums.PNPushEnvironment.PRODUCTION, + 'topic': 'testTopic' + }) + + self.assertEqual(self.remove_channels._channels, ['ch']) diff --git a/tests/functional/push/test_remove_device_from_push.py b/tests/functional/push/test_remove_device_from_push.py index e8d633c4..0f38c944 100644 --- a/tests/functional/push/test_remove_device_from_push.py +++ b/tests/functional/push/test_remove_device_from_push.py @@ -62,3 +62,17 @@ def test_remove_push_mpns(self): 'uuid': self.pubnub.uuid, 'type': 'mpns', }) + + def test_remove_push_apns2(self): + self.remove_device.push_type(pubnub.enums.PNPushType.APNS2).device_id("coolDevice")\ + .environment(pubnub.enums.PNPushEnvironment.PRODUCTION).topic("testTopic") + + params = (pnconf.subscribe_key, "coolDevice") + self.assertEqual(self.remove_device.build_path(), RemoveDeviceFromPush.REMOVE_PATH_APNS2 % params) + + self.assertEqual(self.remove_device.build_params_callback()({}), { + 'pnsdk': sdk_name, + 'uuid': self.pubnub.uuid, + 'environment': pubnub.enums.PNPushEnvironment.PRODUCTION, + 'topic': 'testTopic' + }) From 37b378c433fd3520982c428c1bb038421c3aea0c Mon Sep 17 00:00:00 2001 From: QSD_s Date: Fri, 21 Feb 2020 06:12:50 +0100 Subject: [PATCH 3/5] Set default environment to development for APNS2 push. --- pubnub/endpoints/push/add_channels_to_push.py | 6 +++--- pubnub/endpoints/push/list_push_provisions.py | 6 +++--- pubnub/endpoints/push/remove_channels_from_push.py | 6 +++--- pubnub/endpoints/push/remove_device.py | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/pubnub/endpoints/push/add_channels_to_push.py b/pubnub/endpoints/push/add_channels_to_push.py index db131f1c..9d3f7569 100644 --- a/pubnub/endpoints/push/add_channels_to_push.py +++ b/pubnub/endpoints/push/add_channels_to_push.py @@ -51,6 +51,9 @@ def custom_params(self): if self._push_type != PNPushType.APNS2: params['type'] = utils.push_type_to_string(self._push_type) else: + if self._environment is None: + self._environment = PNPushEnvironment.DEVELOPMENT + params['environment'] = self._environment params['topic'] = self._topic @@ -83,9 +86,6 @@ def validate_params(self): if not isinstance(self._topic, six.string_types) or len(self._topic) == 0: raise PubNubException(pn_error=PNERR_PUSH_TOPIC_MISSING) - if self._environment is None: - self._environment = PNPushEnvironment.DEVELOPMENT - def create_response(self, envelope): return PNPushAddChannelResult() diff --git a/pubnub/endpoints/push/list_push_provisions.py b/pubnub/endpoints/push/list_push_provisions.py index bbfb0ddd..3b8ae01f 100644 --- a/pubnub/endpoints/push/list_push_provisions.py +++ b/pubnub/endpoints/push/list_push_provisions.py @@ -43,6 +43,9 @@ def custom_params(self): if self._push_type != PNPushType.APNS2: params['type'] = utils.push_type_to_string(self._push_type) else: + if self._environment is None: + self._environment = PNPushEnvironment.DEVELOPMENT + params['environment'] = self._environment params['topic'] = self._topic @@ -72,9 +75,6 @@ def validate_params(self): if not isinstance(self._topic, six.string_types) or len(self._topic) == 0: raise PubNubException(pn_error=PNERR_PUSH_TOPIC_MISSING) - if self._environment is None: - self._environment = PNPushEnvironment.DEVELOPMENT - def create_response(self, channels): if channels is not None and len(channels) > 0 and isinstance(channels, list): return PNPushListProvisionsResult(channels) diff --git a/pubnub/endpoints/push/remove_channels_from_push.py b/pubnub/endpoints/push/remove_channels_from_push.py index 5d1a5563..622ef832 100644 --- a/pubnub/endpoints/push/remove_channels_from_push.py +++ b/pubnub/endpoints/push/remove_channels_from_push.py @@ -49,6 +49,9 @@ def custom_params(self): if self._push_type != PNPushType.APNS2: params['type'] = utils.push_type_to_string(self._push_type) else: + if self._environment is None: + self._environment = PNPushEnvironment.DEVELOPMENT + params['environment'] = self._environment params['topic'] = self._topic @@ -81,9 +84,6 @@ def validate_params(self): if not isinstance(self._topic, six.string_types) or len(self._topic) == 0: raise PubNubException(pn_error=PNERR_PUSH_TOPIC_MISSING) - if self._environment is None: - self._environment = PNPushEnvironment.DEVELOPMENT - def create_response(self, envelope): return PNPushRemoveChannelResult() diff --git a/pubnub/endpoints/push/remove_device.py b/pubnub/endpoints/push/remove_device.py index 4fa6fe2f..b021e4ce 100644 --- a/pubnub/endpoints/push/remove_device.py +++ b/pubnub/endpoints/push/remove_device.py @@ -43,6 +43,9 @@ def custom_params(self): if self._push_type != PNPushType.APNS2: params['type'] = utils.push_type_to_string(self._push_type) else: + if self._environment is None: + self._environment = PNPushEnvironment.DEVELOPMENT + params['environment'] = self._environment params['topic'] = self._topic @@ -72,9 +75,6 @@ def validate_params(self): if not isinstance(self._topic, six.string_types) or len(self._topic) == 0: raise PubNubException(pn_error=PNERR_PUSH_TOPIC_MISSING) - if self._environment is None: - self._environment = PNPushEnvironment.DEVELOPMENT - def create_response(self, envelope): return PNPushRemoveAllChannelsResult() From f5e14566266795a4b137cdb5fd160df50b225c42 Mon Sep 17 00:00:00 2001 From: QSD_s Date: Fri, 21 Feb 2020 06:17:56 +0100 Subject: [PATCH 4/5] Add additional functional tests for APNS2 feature. --- .../push/test_list_push_provisions.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/functional/push/test_list_push_provisions.py b/tests/functional/push/test_list_push_provisions.py index 171d6acb..111a6152 100644 --- a/tests/functional/push/test_list_push_provisions.py +++ b/tests/functional/push/test_list_push_provisions.py @@ -1,7 +1,9 @@ import unittest +import pytest from pubnub.endpoints.push.list_push_provisions import ListPushProvisions from pubnub.enums import PNPushType +from pubnub.exceptions import PubNubException try: from mock import MagicMock @@ -81,3 +83,23 @@ def test_list_channel_group_apns2(self): 'environment': pubnub.enums.PNPushEnvironment.PRODUCTION, 'topic': 'testTopic' }) + + def test_apns2_no_topic(self): + push = self.list_push.push_type(PNPushType.APNS2).device_id('coolDevice') + + with pytest.raises(PubNubException): + push.validate_params() + + def test_apns2_default_environment(self): + self.list_push.push_type(PNPushType.APNS2).device_id('coolDevice').topic("testTopic") + + self.assertEqual(self.list_push.build_path(), + ListPushProvisions.LIST_PATH_APNS2 % ( + pnconf.subscribe_key, "coolDevice")) + + self.assertEqual(self.list_push.build_params_callback()({}), { + 'pnsdk': sdk_name, + 'uuid': self.pubnub.uuid, + 'environment': pubnub.enums.PNPushEnvironment.DEVELOPMENT, + 'topic': 'testTopic' + }) From edf963993393eed13acd6e469af6641992398ebe Mon Sep 17 00:00:00 2001 From: QSD_s Date: Fri, 21 Feb 2020 13:38:58 +0100 Subject: [PATCH 5/5] Bump version to 4.4.0. --- .pubnub.yml | 4 ++-- CHANGELOG.md | 4 ++-- pubnub/pubnub_core.py | 2 +- setup.py | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.pubnub.yml b/.pubnub.yml index ec23fc64..b31d8da2 100644 --- a/.pubnub.yml +++ b/.pubnub.yml @@ -1,9 +1,9 @@ name: python -version: 4.3.1 +version: 4.4.0 schema: 1 scm: github.com/pubnub/python changelog: - - version: v4.3.1 + - version: v4.4.0 date: Feb 20, 2020 changes: - type: feature diff --git a/CHANGELOG.md b/CHANGELOG.md index cfa4004e..de7044f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ -## [4.3.1](https://github.com/pubnub/python/tree/v4.3.1) +## [4.4.0](https://github.com/pubnub/python/tree/v4.4.0) - [Full Changelog](https://github.com/pubnub/python/compare/v4.3.0...v4.3.1) + [Full Changelog](https://github.com/pubnub/python/compare/v4.3.0...v4.4.0) - 🌟 Add support for APNS2 Push API diff --git a/pubnub/pubnub_core.py b/pubnub/pubnub_core.py index 9363d6c6..133559eb 100644 --- a/pubnub/pubnub_core.py +++ b/pubnub/pubnub_core.py @@ -56,7 +56,7 @@ class PubNubCore: """A base class for PubNub Python API implementations""" - SDK_VERSION = "4.3.1" + SDK_VERSION = "4.4.0" SDK_NAME = "PubNub-Python" TIMESTAMP_DIVIDER = 1000 diff --git a/setup.py b/setup.py index 62f04d6f..87d5e184 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name='pubnub', - version='4.3.1', + version='4.4.0', description='PubNub Real-time push service in the cloud', author='PubNub', author_email='support@pubnub.com',