Maintainabiity ================= .. contents:: In this section: :depth: 2 :local: Specify topic tree def ------------------------ *Topic Specification* can be used to have better control over your topic hierarchy. If you don't specify your application's topics, pubsub infers them from the first subscribed listener of each topic. E.g.:: def listener1(arg1, arg2=None): pass def listener2(arg1=None, arg2=None): pass pub.subscribe(listener1, 'topic.sub') pub.subscribe(listener2, 'topic.sub') Because listener1 is the first to be subscribed to 'topic.sub' topic, pubsub uses it to infer the specification of 'topic.sub': the specification is "messages of that topic *must* provide data for arg1, and *may* provide data for arg2". The second listener subscribed, listener2, is allowed to subscribe because it is compatible with the topic's specification created at the previous call. What if your intent was that arg1 is optional as well, i.e. the signature of listener1 is wrong (it should provide a default value for arg1)? Or what if per chance listener2 gets subscribed first (could happen if both are subscribed in different modules whose load order changes)? There are two ways to go about this: - Call ``pub.getDefaultTopicMgr().newTopic()`` to explicitly create the topic; this must happen before any listener subscribes to it - Use one or more *Topic definition providers* (TDP). This is described below. Topic Definition Providers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The easiest way to understand a topic tree definition is to get pubsub to output one for your application via ``pub.exportTopicTreeSpec()``. Here is an example, taken from the file examples/advanced/kwargs_topics.py generated by that function, assuming two root topics 'topic_1' and 'topic_2' and the call ``pub.exportTopicTreeSpec('kwargs_topics')``: .. literalinclude:: ../../examples/advanced/kwargs_topics.py This shows how the topic definition tree is defined using a Python module with a nested class tree that represents the topics, and msgDataSpec() functions that represent the listener signatures for the given topics. This also shows how it is possible to document each topic and message datum. An application uses the above module via the following:: import kwargs_topics pub.addTopicDefnProvider( kwargs_topics, pub.TOPIC_TREE_FROM_CLASS ) The format type is ``pub.TOPIC_TREE_FROM_CLASS`` because once imported, the kwargs_topics object is a module containing topic definitions as classes; based on that setting, pubsub will look for all classes in the kwargs_topics object, and instantiate one topic definition for each one. See examples/advanced/main_kwargs.py for an example of using a topic tree definition in an application. It is possible to support other formats for topic tree definition. For example, ``pubsub.utils.XmlTopicDefnProvider`` was contributed to pubsub by one of its devoted users. A new type of provider need only adhere to the ``pub.ITopicTreeDefnProvider`` interface; ``pub.addTopicDefnProvider()`` accepts any instance that implements from that interface:: xmlString = open('xml_topics.xml', 'r').read() provider = XmlTopicDefnProvider(xmlString) pub.addTopicDefnProvider( provider ) It is typically useful to combine topic tree definition with the following call, placed once at the beginning of an application:: pub.setTopicUnspecifiedFatal(True) Then any attempt to use a topic that is not defined in the topic tree definition will raise an ``pub.TopicUnspecifiedError``. Note that any topic that does not have a docstring is not considered to be defined. This may allow for some temporary "undefining" of topics.