Skip to content

Commit

Permalink
Feat/listeners (#186)
Browse files Browse the repository at this point in the history
* PubNub Entrypoint

* Fixes from tests. 

* Listeners

* Refactor names, add SubscriptionSet, remove debug

* Event engine as a default subscription manager

* Update runner

* move tt, tr and with_presence to subscribe method

* Rework subscriptionSet to use PubNubSubscriptions

* remove type from subscriptionset

* Fixed subscription set and examples

* Add subscription set and subscription item level listeners

* Fix in example

* PubNub SDK v8.0.0 release.

---------

Co-authored-by: PubNub Release Bot <[email protected]>
  • Loading branch information
seba-aln and pubnub-release-bot authored May 9, 2024
1 parent 7053332 commit cf8cbed
Show file tree
Hide file tree
Showing 26 changed files with 961 additions and 159 deletions.
12 changes: 6 additions & 6 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ defaults:
run:
shell: bash
env:
PN_KEY_PUBLISH: ${{ secrets.PN_KEY_PUBLISH }}
PN_KEY_SUBSCRIBE: ${{ secrets.PN_KEY_SUBSCRIBE }}
PN_KEY_SECRET: ${{ secrets.PN_KEY_SECRET }}
PN_KEY_PAM_PUBLISH: ${{ secrets.PN_KEY_PAM_PUBLISH }}
PN_KEY_PAM_SUBSCRIBE: ${{ secrets.PN_KEY_PAM_SUBSCRIBE }}
PN_KEY_PAM_SECRET: ${{ secrets.PN_KEY_PAM_SECRET }}
PN_KEY_PUBLISH: ${{ secrets.SDK_PUB_KEY }}
PN_KEY_SUBSCRIBE: ${{ secrets.SDK_SUB_KEY }}
PN_KEY_SECRET: ${{ secrets.SDK_SEC_KEY }}
PN_KEY_PAM_PUBLISH: ${{ secrets.SDK_PAM_PUB_KEY }}
PN_KEY_PAM_SUBSCRIBE: ${{ secrets.SDK_PAM_SUB_KEY }}
PN_KEY_PAM_SECRET: ${{ secrets.SDK_PAM_SEC_KEY }}

jobs:
tests:
Expand Down
15 changes: 11 additions & 4 deletions .pubnub.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: python
version: 7.4.4
version: 8.0.0
schema: 1
scm: github.com/pubnub/python
sdks:
Expand All @@ -18,7 +18,7 @@ sdks:
distributions:
- distribution-type: library
distribution-repository: package
package-name: pubnub-7.4.4
package-name: pubnub-8.0.0
location: https://pypi.org/project/pubnub/
supported-platforms:
supported-operating-systems:
Expand Down Expand Up @@ -97,8 +97,8 @@ sdks:
-
distribution-type: library
distribution-repository: git release
package-name: pubnub-7.4.4
location: https://github.com/pubnub/python/releases/download/v7.4.4/pubnub-7.4.4.tar.gz
package-name: pubnub-8.0.0
location: https://github.com/pubnub/python/releases/download/v8.0.0/pubnub-8.0.0.tar.gz
supported-platforms:
supported-operating-systems:
Linux:
Expand Down Expand Up @@ -169,6 +169,13 @@ sdks:
license-url: https://github.com/aio-libs/aiohttp/blob/master/LICENSE.txt
is-required: Required
changelog:
- date: 2024-05-09
version: v8.0.0
changes:
- type: feature
text: "A new version of subscription and presence handling is enabled by default (enableEventEngine flag is set to true). Please consult the documentation for new PNStatus values that are emitted for subscriptions, as code changes might be required to support this change."
- type: feature
text: "Channels, ChannelGroups, ChannelMetadata and UserMetadata."
- date: 2024-04-10
version: v7.4.4
changes:
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## v8.0.0
May 09 2024

#### Added
- A new version of subscription and presence handling is enabled by default (enableEventEngine flag is set to true). Please consult the documentation for new PNStatus values that are emitted for subscriptions, as code changes might be required to support this change.
- Channels, ChannelGroups, ChannelMetadata and UserMetadata.

## v7.4.4
April 10 2024

Expand Down
122 changes: 122 additions & 0 deletions examples/subscription_object.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import time

from os import getenv
from pubnub.callbacks import SubscribeCallback
from pubnub.pnconfiguration import PNConfiguration
from pubnub.pubnub import PubNub


# Listeners declaration
def on_message(listener):
def message_callback(message):
print(f"\033[94mMessage received on: {listener}: \n{message.message}\033[0m\n")
return message_callback


def on_message_action(listener):
def message_callback(message_action):
print(f"\033[5mMessageAction received on: {listener}: \n{message_action.value}\033[0m\n")
return message_callback


def on_presence(listener):
def presence_callback(presence):
print(f"\033[0;32mPresence received on: {listener}: \t{presence.uuid} {presence.event}s "
f"{presence.subscription or presence.channel}\033[0m")
return presence_callback


def on_status(listener):
def status_callback(status):
print(f"\033[92mStatus received on: {listener}: \t{status.category.name}\033[0m")
return status_callback


def on_signal(listener):
def signal_callback(signal):
print(f"\033[0;36mSignal received on: {listener}: \n{signal.publisher} says: \t{signal.message}\033[0m")
return signal_callback


def on_channel_metadata(listener):
def channel_metadata_callback(channel_meta):
print(f"\033[0;36mChannel metadata received on: {listener}: \n{channel_meta.__dict__}\033[0m")
return channel_metadata_callback


class PrintListener(SubscribeCallback):
def status(self, _, status):
print(f'\033[92mPrintListener.status:\n{status.category.name}\033[0m')

def message(self, _, message):
print(f'\033[94mPrintListener.message:\n{message.message}\033[0m')

def presence(self, _, presence):
print(f'PrintListener.presence:\n{presence.uuid} {presence.event}s '
f'{presence.subscription or presence.channel}\033[0m')

def signal(self, _, signal):
print(f'PrintListener.signal:\n{signal.message} from {signal.publisher}\033[0m')

def channel(self, _, channel):
print(f'\033[0;37mChannel Meta:\n{channel.__dict__}\033[0m')

def uuid(self, _, uuid):
print(f'User Meta:\n{uuid.__dict__}\033[0m')

def membership(self, _, membership):
print(f'Membership:\n{membership.__dict__}\033[0m')

def message_action(self, _, message_action):
print(f'PrintListener.message_action {message_action}\033[0m')

def file(self, _, file_message):
print(f' {file_message.__dict__}\033[0m')


channel = 'test'
group_name = 'test-group'

config = PNConfiguration()
config.subscribe_key = getenv("PN_KEY_SUBSCRIBE")
config.publish_key = getenv("PN_KEY_PUBLISH")
config.user_id = "example"
config.enable_subscribe = True
config.daemon = True

pubnub = PubNub(config)
pubnub.add_listener(PrintListener())

# Subscribing

# Channel test, no presence, first channel object
print('Creating channel object for "test"')
test1 = pubnub.channel(f'{channel}')
print('Creating subscription object for "test"')
t1_subscription = test1.subscription(with_presence=True)
t1_subscription.on_message = on_message('listener_1')
t1_subscription.on_message_action = on_message_action('listener_1')
t1_subscription.on_presence = on_presence('listener_1')
t1_subscription.on_status = on_status('listener_1')
t1_subscription.on_signal = on_signal('listener_1')

print('We\'re not yet subscribed to channel "test". So let\'s do it now.')
t1_subscription.subscribe()
print("Now we're subscribed. We should receive status: connected")

# Testing message delivery
publish_result = pubnub.publish() \
.channel(f'{channel}') \
.message('Hello channel "test" from PubNub Python SDK') \
.meta({'lang': 'en'}) \
.sync()

time.sleep(2)

print('Removing subscription object for "test"')
t1_subscription.unsubscribe()
time.sleep(2)

print('Exiting')
pubnub.stop()
exit(0)
200 changes: 200 additions & 0 deletions examples/subscription_object_threads.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
import time

from os import getenv
from pubnub.callbacks import SubscribeCallback
from pubnub.pnconfiguration import PNConfiguration
from pubnub.pubnub import PubNub


# Listeners declaration
def on_message(listener):
def message_callback(message):
print(f"\033[94mMessage received on: {listener}: \n{message.message}\033[0m\n")
return message_callback


def on_message_action(listener):
def message_callback(message_action):
print(f"\033[5mMessageAction received on: {listener}: \n{message_action.value}\033[0m\n")
return message_callback


def on_presence(listener):
def presence_callback(presence):
print(f"\033[0;32mPresence received on: {listener}: \t{presence.uuid} {presence.event}s "
f"{presence.subscription or presence.channel}\033[0m")
return presence_callback


def on_status(listener):
def status_callback(status):
print(f"\033[92mStatus received on: {listener}: \t{status.category.name}\033[0m")
return status_callback


def on_signal(listener):
def signal_callback(signal):
print(f"\033[0;36mSignal received on: {listener}: \n{signal.publisher} says: \t{signal.message}\033[0m")
return signal_callback


def on_channel_metadata(listener):
def channel_metadata_callback(channel_meta):
print(f"\033[0;36mChannel metadata received on: {listener}: \n{channel_meta.__dict__}\033[0m")
return channel_metadata_callback


class PrintListener(SubscribeCallback):
def status(self, _, status):
print(f'\033[92mPrintListener.status:\n{status.category.name}\033[0m')

def message(self, _, message):
print(f'\033[94mPrintListener.message:\n{message.message}\033[0m')

def presence(self, _, presence):
print(f'PrintListener.presence:\n{presence.uuid} {presence.event}s '
f'{presence.subscription or presence.channel}\033[0m')

def signal(self, _, signal):
print(f'PrintListener.signal:\n{signal.message} from {signal.publisher}\033[0m')

def channel(self, _, channel):
print(f'\033[0;37mChannel Meta:\n{channel.__dict__}\033[0m')

def uuid(self, _, uuid):
print(f'User Meta:\n{uuid.__dict__}\033[0m')

def membership(self, _, membership):
print(f'Membership:\n{membership.__dict__}\033[0m')

def message_action(self, _, message_action):
print(f'PrintListener.message_action {message_action}\033[0m')

def file(self, _, file_message):
print(f' {file_message.__dict__}\033[0m')


channel = 'test'
group_name = 'test-group'

config = PNConfiguration()
config.subscribe_key = getenv("PN_KEY_SUBSCRIBE")
config.publish_key = getenv("PN_KEY_PUBLISH")
config.user_id = "example"
config.enable_subscribe = True
config.daemon = True

pubnub = PubNub(config)
pubnub.add_listener(PrintListener())

# Subscribing

# Channel test, no presence, first channel object
print('Creating channel object for "test"')
test1 = pubnub.channel(f'{channel}')
print('Creating subscription object for "test"')
t1_subscription = test1.subscription(with_presence=False)
t1_subscription.on_message = on_message('listener_1')
t1_subscription.on_message_action = on_message_action('listener_1')
t1_subscription.on_presence = on_presence('listener_1')
t1_subscription.on_status = on_status('listener_1')
t1_subscription.on_signal = on_signal('listener_1')

print('We\'re not yet subscribed to channel "test". So let\'s do it now.')
t1_subscription.subscribe()
print("Now we're subscribed. We should receive status: connected")

time.sleep(3)
print("We don't see any presence event since we don't have it enabled yet")

print('Creating second subscription object for channel "test.2"')
test2 = pubnub.channel(f'{channel}.2')
print('Creating subscription object for "test"')
t2_subscription = test1.subscription(with_presence=True)

t2_subscription.on_message = on_message('listener_2')
t2_subscription.on_presence = on_presence('listener_2')
t2_subscription.on_status = on_status('listener_2')
t2_subscription.on_signal = on_signal('listener_2')
t2_subscription.subscribe()

print('Now we\'re subscribed to "test" with two listeners. one with presence and one without')
print('So we should see presence events only for listener "test2" for channel "test2"')
time.sleep(2)

# Channel test3, no presence, third channel object
print('Creating channel object for "test.3"')
test3 = pubnub.channel(f'{channel}.3')
print('Creating subscription object for "test.3"')
t3_subscription = test3.subscription()
t3_subscription.on_message = on_message('listener_3')
t3_subscription.on_presence = on_presence('listener_3')
t3_subscription.on_status = on_status('listener_3')
t3_subscription.on_signal = on_signal('listener_3')
print('We subscribe to third channel so we should see three "connected" statuses and no new presence events')
t3_subscription.subscribe()

print('Creating wildcard object for "test.*"')
wildcard_channel = pubnub.channel(f'{channel}.*')
print('Creating wildcard subscription object for "test.*"')
wildcard = wildcard_channel.subscription()
wildcard.on_message = on_message('WILDCARD')
wildcard.on_presence = on_presence('WILDCARD')
wildcard.on_status = on_status('WILDCARD')
wildcard.on_signal = on_signal('WILDCARD')
print('We subscribe to all channels "test.*"')
wildcard.subscribe()

print('Creating Group with "test.2" and "test.3"')
pubnub.add_channel_to_channel_group() \
.channels(['test']) \
.channel_group(group_name) \
.sync()

print('Creating group object for "test_group"')
group = pubnub.channel_group(f'{group_name}')
print('Creating wildcard subscription object for "group_name"')
group_subscription = group.subscription()
group_subscription.on_message = on_message('group')
group_subscription.on_presence = on_presence('group')
group_subscription.on_status = on_status('group')
group_subscription.on_signal = on_signal('group')
print('We subscribe to the channel group "test_group"')
group_subscription.subscribe()

print('Now we publish messages to each channel separately')
time.sleep(1)

# Testing message delivery
publish_result = pubnub.publish() \
.channel(f'{channel}') \
.message('Hello channel "test" from PubNub Python SDK') \
.meta({'lang': 'en'}) \
.sync()

pubnub.publish() \
.channel(f'{channel}.2') \
.message('Nau mai ki te hongere "test.2" mai i PubNub Python SDK') \
.meta({'lang': 'mi'}) \
.sync()

pubnub.publish() \
.channel(f'{channel}.3') \
.message('Bienvenido al canal "test.3" de PubNub Python SDK') \
.meta({'lang': 'es'}) \
.sync()

pubnub.publish() \
.channel(f'{channel}.4') \
.message('Ciao canale "test.4" da PubNub Python SDK') \
.meta({'lang': 'it'}) \
.sync()

time.sleep(1)

print('Removing second subscription object for "test"')
t1_subscription.unsubscribe()

print('Exiting')
pubnub.stop()
exit(0)
Loading

0 comments on commit cf8cbed

Please sign in to comment.