Example #1
0
    def isTopicSpecified(self, name):
        '''Returns true if the topic has already been specified, false 
        otherwise. If the return value is true, it is in fact an integer > 0 
        that says in what way it is specified: 
        
        - TOPIC_SPEC_ALREADY_DEFINED: as a definition in one of the registered
          topic definition providers
        - TOPIC_SPEC_ALREADY_CREATED: as an object in the topic tree, having a 
          complete specification
        
        So if caller just wants yes/no, just use return value as boolean as in

            if topicMgr.isTopicSpecified(name): pass

        but if reason matters, caller could use (for instance)

            if topicMgr.isTopicSpecified(name) == topicMgr.TOPIC_SPEC_ALREADY_DEFINED: pass

        NOTE: if a topic object of given 'name' exists in topic tree, but
        it does *not* have a complete specification, the return value will
        be false.
        '''
        alreadyCreated = self.getTopic(name, okIfNone=True)
        if alreadyCreated is not None and alreadyCreated.isSendable():
            return self.TOPIC_SPEC_ALREADY_CREATED

        # get definition from provider if required, or raise
        nameTuple = tupleize(name)
        if self.__defnProvider.isDefined(nameTuple):
            return self.TOPIC_SPEC_ALREADY_DEFINED

        return self.TOPIC_SPEC_NOT_SPECIFIED
Example #2
0
    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)
Example #3
0
    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)
Example #4
0
 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)
Example #5
0
    def newTopic(self, _name, _desc, _required=(), 
                 _argsSpec=ARGS_SPEC_SUBONLY, **args):
        '''Create a new topic of given _name, with description desc explaining 
        the topic (for documentation purposes). The **args defines the data 
        that can be given as part of messages of this topic: the keys define 
        what arguments names must be present for listeners of this topic, 
        whereas the values describe each argument (for documentation purposes).  

        Returns True only if a new topic was created, False if it already 
        existed identically (same description, same args -- in which case 
        the operation is a no-op). Otherwise raises ValueError. ''' 
        # check _name
        topicTuple = tupleize(_name)

        # create only if doesn't exist:
        nameDotted = stringize(_name)
        #print 'Checking for "%s"' % nameDotted
        if self._topicsMap.has_key(nameDotted):
            msg = 'Topic "%s" already exists' % nameDotted
            raise TopicAlreadyDefined(msg)
        
        # get parent in which to create topic
        path = topicTuple[:-1]
        if path:
            pathDotted = stringize(path)
            parent = self._topicsMap.get(pathDotted, None)
            if parent is None:
                msg = 'Parent topic "%s" does not exist, cannot create'
                raise UndefinedTopic(pathDotted)
        else:
            parent = self._rootTopic

        # ok to create!
        newTopicObj = self.__createTopic(
                          topicTuple, desc=_desc, 
                          parent=parent, argsSpec=_argsSpec,
                          argsDocs=args, reqdArgs=_required) 

        return newTopicObj