Types of Errors¶
While developing an application that uses pubsub, calls to pubsub functions and methods may raise an exception, in the following circumstances:
the listener given to pub.subscribe() is not valid:
pub.ListenerMismatchError
ValueError
the data sent via pub.sendMessage() does not satisfy the topic’s MDS:
pub.SenderMissingReqdMsgDataError
pub.SenderUnknownMsgDataError
pub.SenderTooManyKwargs
pub.SenderWrongKwargName
there is a problem with a topic name:
pub.TopicNameError
pub.TopicDefnError
ValueError
a callback registered via pub.setListenerExcHandler() raises an exception while handling an exception raised by a listener:
pub.ExcHandlerError
a subclass derived from a pubsub core or utils base class is missing some implementation:
NotImplementedError
a topic’s MDS, defined explicitly via TopicDefnProvider, is not valid:
pub.MessageDataSpecError
pub.UnrecognizedSourceFormatError
For basic pubsub usage, the most common ones are ListenerMismatchError
and the Sender...
exceptions. All others are relevant to usage of
more advanced pubsub features such as topic tree specification,
listener exception trapping, and pubsub notification trapping.
Listener Mismatch Errors¶
The most common type of error results from attempting to subscribe an invalid
listener: one that does not have a signature (call protocol) compatible with the
topic’s MDS. When this happens, pubsub raises a
pub.ListenerMismatchError
exception.
By default, pubsub infers topic MDSs. In that case, the error typically happens when more than one listener is registered for a given topic, and introspection of the listener identifies that it does not satisfy the topic’s MDS. For example, consider
def listener0(arg1, arg2=default0): pass
def listener1(arg1=val, arg2=default3): pass
def listener2(arg1): pass
def listener3(arg1, arg2): pass
pub.subscribe(listener0, "topic") // OK: infers MDS
pub.subscribe(listener1, "topic") // OK: satisfies MDS
pub.subscribe(listener2, "topic") // FAIL: violates MDS
Pubsub will raise a ListenerMismatchError exception on the last line since arg2 was inferred in the first subscription, from listener0, as being part of the MDS, yet listener2 does not accept this data.
Similarly, if the last line had been
pub.subscribe(listener3, "topic")
a pub.ListenerMismatchError
exception would get raised because listener3
requires arg2,
yet the MDS inferred from listener0 has it as optional, indicating the sender
may not provide it. Pubsub is flagging the fact that listener3 is “more demanding”
than the MDS can guarantee.
Sender Exceptions¶
The sender exceptions are very useful as they indicate clearly what message data is wrong:
pub.SenderMissingReqdMsgDataError
: some required data is missing
pub.SenderUnknownMsgDataError
: one of the keyword arguments is not part of MDS
For example, given the previous code involving a topic “topic” MDS inferred
from listener0, the following code would raise a
pub.SenderUnknownMsgDataError
pub.sendMessage("topic", arg1=1, arg3=3)
because arg3 is not part of the MDS.
When transitioning from arg1 to kwargs messaging protocol, two more exceptions are possible:
pub.SenderTooManyKwargs
pub.SenderWrongKwargName
See section Transition from Arg1 to Kwargs as well as functions
pubsub.setuparg1.enforceArgName()
and
pubsub.setupkwargs.transitionFromArg1()
.
Topic Name Errors¶
A topic name must satisfy the following:
is not empty: ‘’ or None
is not a reserved name: the only one currently is the value of
pub.ALL_TOPICS
starts with any of ‘-’, 0-9, a-z, A-Z (so UNDERSCORE ‘_’ not allowed; it is reserved)
This applies to all levels of a topic path, i.e. the items between ‘.’. For example the following are not allowed: ‘a.’, ‘.a’, ‘.’, ‘a..b’, etc.
If a topic name does not satisfy the above, pubsub raises pub.TopicNameError
.
Some functions in pubsub raise an exception if the topic doesn’t exist:
pub.isValid(listener, topicName)()
pub.validate(listener, topicName)()
pub.isSubscribed(listener, topicName)()
pub.unsubscribe(listener, topicName)()
pub.unsubAll(topicName)()
since the operation does not make sense: it does not make sense, for example, to test if given listener is valid if topic does not exist!
By default,
pubsub does not complain about topic names that have never been subscribed to.
subscribing a listener to a topic never used before ‘creates’ the topic.
Hence there is, by default, no way of trapping the following mistakes:
pub.subscribe(listener1, 'topic') # creates 'topic' topic
# next line has typo in topic name:
pub.subscribe(listener2, 'tpic') # creates 'tpic' topic
pub.sendMessage('topic') # only listener1 will receive
# next line has typo in topic name:
pub.sendMessage('topc') # creates 'topc' topic; no listener will receive
These can lead to hard-to-isolate bugs as some listeners never get the messages.
To trap such typos, use pub.setTopicUnspecifiedFatal(true)()
, and
specify all allowed topics at application startup by registering a Topic
Definition Provider via pub.addTopidDefnProvider()
. Both above
typos will then lead to pubsub
raising TopicDefnError
. Note: a provider can easily be created via the
pub.exportTopicTreeSpec()
.