Package: jetblack-messagebus-python3
jetblack-messagebus-python3OverviewThis is a Python 3.7+ client for thejetblack-messagebus.It follows the publish-subscribe pattern, and includes support for "notification" of
a subscription by another client. This allows it to provide data on-demand.See the server documentation for more detailed information.ExampleThe client below subscribes on feed "TEST" to topic "FOO" and prints out
the data it receives.importasynciofromjetblack_messagebusimportCallbackClientasyncdefon_data(user,host,feed,topic,data_packets,is_image):print(f'data: user="{user}",host="{host}",feed="{feed}",topic="{topic}",is_image={is_image}')ifnotdata_packets:print("no data")else:forpacketindata_packets:message=packet.data.decode('utf8')ifpacket.dataelseNoneprint(f'packet: entitlements={packet.entitlements},message={message}')asyncdefmain():client=awaitCallbackClient.create('localhost',9001)client.data_handlers.append(on_data)awaitclient.add_subscription('TEST','FOO')awaitclient.start()if__name__=='__main__':asyncio.run(main())SSLTo create an SSL subscriber, pass in the ssl context.importsslfromjetblack_messagebusimportCallbackClient...asyncdefmain():"""Start the demo"""ssl_context=ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)client=awaitCallbackClient.create('myhost.example.com',9001,ssl=ssl_context)awaitclient.add_subscription('TEST','FOO')awaitclient.start()AuthenticationThe message bus currently supports the following authentication methods:Password FileLDAPJWTPassword File and LDAPBoth the password file and LDAP methods require a username and password. This
is provided by the basic authenticator.importsslfromjetblack_messagebusimportCallbackClientfromjetblack_messagebus.authenticationimportBasicAuthenticator...asyncdefmain():authenticator=BasicAuthenticator("john.doe@example.com","pa$$word")ssl_context=ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)client=awaitCallbackClient.create('myhost.example.com',9001,ssl=ssl_context,authenticator=authenticator)awaitclient.add_subscription('TEST','FOO')awaitclient.start()JWTJWT authentication requires a valid token to be passed by the client. This
is provided by the token authenticator.importsslfromjetblack_messagebusimportCallbackClientfromjetblack_messagebus.authenticationimportTokenAuthenticator...asyncdefmain():authenticator=TokenAuthenticator("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJqb2huLmRvZUBleGFtcGxlLmNvbSIsIm5hbWUiOiJKb2huIERvZSIsImlhdCI6MTUxNjIzOTAyMiwiZXhwIjoxNTE3MTgzNTAxfQ.wLSGBcNUT8r1DqQvaBrrGY4NHiiVOpoxrgeoPsSsJkY")ssl_context=ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)client=awaitCallbackClient.create('myhost.example.com',9001,ssl=ssl_context,authenticator=authenticator)awaitclient.add_subscription('TEST','FOO')awaitclient.start()Message handlersThere are three types of messages that can be received:DataSubscription notificationsAuthorization requests.DataA data handler looks like this:# A data handler.asyncdefon_data(user:str,host:str,feed:str,topic:str,data_packets:Optional[List[DataPacket]],is_image:bool)->None:"""Called when data is received"""pass# Add the handler to the client.client.data_handlers.append(on_data)# Remove the handlerclient.data_handlers.remove(on_data)The data packets have two fields:entitlementsanddata.Theentitlementsis a optional set of ints which express the entitlements that were
required for the data to have been received.Thedatais an optionalbytesholding the encoded data. What this represents
is agreed by the sender and receiver. For example it might be a simple string, some
JSON text, or a protocol buffer.Subscription notificationsA subscription notification handler looks like this:# A notification handler.asyncdefon_notification(client_id:UUID,user:str,host:str,feed:str,topic:str,is_add:bool)->None:"""Called for a notification"""pass# Add the handler to the client.client.notification_handlers.append(on_notification)# Remove the handlerclient.notification_handlers.remove(on_notification)Authorization requests# An authorization handler.asyncdefon_authorization(client_id:UUID,host:str,user:str,feed:str,topic:str)->None:"""Called when authorization is requested"""pass# Add the handler to the client.client._authorization_handlers.append(on_authorization)# Remove the handlerclient._authorization_handlers.remove(on_authorization)