def getOrCreateTopic(self, name, protoListener=None): '''Get the topic object for topic of given name, creating it (and any of its missing parent topics) as necessary. This should be useful mostly to TopicManager itself. Topic creation: The topic definition will be obtained from the first registered TopicDefnProvider (see addTopicDefnProvider() method) that can provide it. If none is found, then protoListener, if given, will be used to extract the specification for the topic message arguments. So the topic object returned will be either 1. an existing one 2. a new one whose specification was obtained from a TopicDefnProvider 3. a new one whose specification was inferred from protoListener 4. a new one without any specification For the first three cases, the Topic is ready for sending messages. In the last case, topic.isSendable() is false and the specification will be set by the first call to subscribe() (unless you call topicObj.setMsgArgSpec() first to set it yourself). Note that if the topic gets created, missing intervening parents will be created with an empty specification. For instance, if topic A exists, and name="A.B.C", then A.B will also be created. It will only be complete (sendable) if a topic definition provider had its definition. Note also that if protoListener given, and topic already defined, the method does not check whether protoListener adheres to the specification.''' obj = self.getTopic(name, okIfNone=True) if obj: # if object is not sendable but a proto listener was given, # update its specification so that it is sendable if (protoListener is not None) and not obj.isSendable(): allArgsDocs, required = topicArgsFromCallable(protoListener) obj.setMsgArgSpec(allArgsDocs, required) return obj # create missing parents nameTuple = tupleize(name) parentObj = self.__createParentTopics(nameTuple) # now the final topic object, args from listener if provided desc, specGiven = self.__defnProvider.getDefn(nameTuple) # POLICY: protoListener is used only if no definition available if specGiven is None: if protoListener is None: desc = 'UNDOCUMENTED: created without spec' else: allArgsDocs, required = topicArgsFromCallable(protoListener) specGiven = ArgSpecGiven(allArgsDocs, required) desc = 'UNDOCUMENTED: created from protoListener "%s" in module %s' % getID( protoListener) return self.__createTopic(nameTuple, desc, parent=parentObj, specGiven=specGiven)
def getOrCreateTopic(self, name, protoListener=None): '''Get the topic object for topic of given name, creating it (and any of its missing parent topics) as necessary. This should be useful mostly to TopicManager itself. Topic creation: The topic definition will be obtained from the first registered TopicDefnProvider (see addTopicDefnProvider() method) that can provide it. If none is found, then protoListener, if given, will be used to extract the specification for the topic message arguments. So the topic object returned will be either 1. an existing one 2. a new one whose specification was obtained from a TopicDefnProvider 3. a new one whose specification was inferred from protoListener 4. a new one without any specification For the first three cases, the Topic is ready for sending messages. In the last case, topic.isSendable() is false and the specification will be set by the first call to subscribe() (unless you call topicObj.setMsgArgSpec() first to set it yourself). Note that if the topic gets created, missing intervening parents will be created with an empty specification. For instance, if topic A exists, and name="A.B.C", then A.B will also be created. It will only be complete (sendable) if a topic definition provider had its definition. Note also that if protoListener given, and topic already defined, the method does not check whether protoListener adheres to the specification.''' obj = self.getTopic(name, okIfNone=True) if obj: # if object is not sendable but a proto listener was given, # update its specification so that it is sendable if (protoListener is not None) and not obj.isSendable(): allArgsDocs, required = topicArgsFromCallable(protoListener) obj.setMsgArgSpec(allArgsDocs, required) return obj # create missing parents nameTuple = tupleize(name) parentObj = self.__createParentTopics(nameTuple) # now the final topic object, args from listener if provided desc, specGiven = self.__defnProvider.getDefn(nameTuple) # POLICY: protoListener is used only if no definition available if specGiven is None: if protoListener is None: desc = 'UNDOCUMENTED: created without spec' else: allArgsDocs, required = topicArgsFromCallable(protoListener) specGiven = ArgSpecGiven(allArgsDocs, required) desc = 'UNDOCUMENTED: created from protoListener "%s" in module %s' % getID(protoListener) return self.__createTopic(nameTuple, desc, parent = parentObj, specGiven = specGiven)
def _updateArgsSpec_(self, usingCallable, topicMgr): '''Update the argument spec of topic using given callable. ''' assert self.__parentTopic is not None assert not self.argsSpecComplete() argsDocs, required = topicArgsFromCallable(usingCallable) getArgsSpec = topicMgr._getDefnProvider_().getSubSpec self.__msgArgs = ArgsInfo(getArgsSpec, self.getName(), self.__parentTopic(), argsDocs, required, ARGS_SPEC_ALL) self.argsSpec = self.__msgArgs # validate that our new spec agrees with complete children for child in self.getSubtopics(): # get difference between child and our parent # this must contain our difference from our parent pass if self.__msgArgs.isComplete(): self.__finalize()
def _newTopicFromTemplate_(self, topicName, desc, usingCallable=None): '''Return a new topic object created from protocol of callable referenced by usingCallable. Creates missing parents.''' assert not self._topicsMap.has_key( stringize(topicName) ) topicNameTuple = tupleize(topicName) parentObj = self.__createParentTopics(topicName) # now the final topic object, args from listener if provided allArgsDocs, required, argsSpec = None, None, ARGS_SPEC_NONE if usingCallable is not None: allArgsDocs, required = topicArgsFromCallable(usingCallable) argsSpec=ARGS_SPEC_ALL # if user description exists, use it rather than desc: desc = self.__defnProvider.getDescription(topicNameTuple) or desc return self.__createTopic( topicNameTuple, desc, parent=parentObj, argsSpec=argsSpec, argsDocs=allArgsDocs, reqdArgs=required)
def getNextTopic(self): '''Get next topic defined by this provider. Returns None when no topics are left. May call resetIter() to restart the iteration.''' self.__iterStarted = True try: topicNameTuple, topicClassObj = self.__nextTopic.next() except StopIteration: return None # ok get the info from class if hasattr(topicClassObj, SPEC_METHOD_NAME): protoListener = getattr(topicClassObj, SPEC_METHOD_NAME) argsDocs, required = topicArgsFromCallable(protoListener) if protoListener.__doc__: self.__setArgsDocsFromProtoDocs(argsDocs, protoListener.__doc__) else: # assume definition is implicitly that listener has no args argsDocs = {} required = () desc = None if topicClassObj.__doc__: desc = dedent(topicClassObj.__doc__) return self.TopicDefn(topicNameTuple, desc, argsDocs, required)