B
    lU\4                 @   s   d Z ddlmZmZmZmZ ddlmZmZm	Z	m
Z
mZ G dd deZG dd deZG d	d
 d
eZeeef edddZdeedddZdeeeedddZdS )a  
Provide an interface class for handling pubsub notification messages, 
and an example class (though very useful in practice) showing how to 
use it. 

Notification messages are generated by pubsub

- if a handler has been configured via pub.addNotificationHandler()
- when pubsub does certain tasks, such as when a listener subscribes to
  or unsubscribes from a topic
  
Derive from this class to handle notification events from 
various parts of pubsub. E.g. when a listener subscribes, 
unsubscribes, or dies, a notification handler, if you 
specified one via pub.addNotificationHandler(), is given the 
relevant information. 

:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
:license: BSD, see LICENSE_BSD_Simple.txt for details.
    )ListMappingAnyTextIO   )TopicManagerINotificationHandlerListenerTopic	Publisherc               @   s   e Zd ZdZeeedddZeedddZeeddd	Z	de
eedddZee
ee
 ee
e
f dddZe
dddZd
S )IgnoreNotificationsMixinz
    Derive your Notifications handler from this class if your handler
    just wants to be notified of one or two types of pubsub events.
    Then just override the desired methods. The rest of the notifications
    will automatically be ignored.
    )pubListenertopicObjnewSubc             C   s   d S )N )selfr   r   r   r   r   8lib/python3.7/site-packages/pubsub/utils/notification.pynotifySubscribe#   s    z(IgnoreNotificationsMixin.notifySubscribe)r   r   c             C   s   d S )Nr   )r   r   r   r   r   r   notifyUnsubscribe&   s    z*IgnoreNotificationsMixin.notifyUnsubscribec             C   s   d S )Nr   )r   r   r   r   r   r   notifyDeadListener)   s    z+IgnoreNotificationsMixin.notifyDeadListenerN)stager   r   c             C   s   d S )Nr   )r   r   r   r   r   r   r   
notifySend,   s    z#IgnoreNotificationsMixin.notifySend)r   descriptionrequiredargsDocsc             C   s   d S )Nr   )r   r   r   r   r   r   r   r   notifyNewTopic/   s    z'IgnoreNotificationsMixin.notifyNewTopic)	topicNamec             C   s   d S )Nr   )r   r   r   r   r   notifyDelTopic2   s    z'IgnoreNotificationsMixin.notifyDelTopic)N)__name__
__module____qualname____doc__r	   r
   boolr   r   r   strr   r   r   r   r   r   r   r   r   r      s    r   c               @   s   e Zd ZdZdZdeedddZdd Ze	e
ed	d
dZe	e
dddZe	e
dddZdee
e	dddZe
eee eeef dddZedddZdS )NotifyByWriteFilezE
    Print a message to stdout when a notification is received. 
    zPUBSUB:N)fileObjprefixc             C   s0   |p| j | _|dkr&ddl}|j| _n|| _dS )z
        Will write to stdout unless fileObj given. Will use
        defaultPrefix as prefix for each line output, unless prefix
        specified.
        Nr   )defaultPrefix_NotifyByWriteFile__presysstdout_NotifyByWriteFile__fileObj)r   r%   r&   r)   r   r   r   __init__=   s
    
zNotifyByWriteFile.__init__c             C   s
   || _ d S )N)r+   )r   r%   r   r   r   
changeFileK   s    zNotifyByWriteFile.changeFile)r   r   r   c             C   s2   |r
d}nd}|| j || f }| j| d S )Nz*%s Subscribed listener "%s" to topic "%s"
z0%s Subscription of "%s" to topic "%s" redundant
)r(   getNamer+   write)r   r   r   r   msgr   r   r   r   N   s
    z!NotifyByWriteFile.notifySubscribe)r   r   c             C   s(   d}|| j || f }| j| d S )Nz.%s Unsubscribed listener "%s" from topic "%s"
)r(   r.   r+   r/   )r   r   r   r0   r   r   r   r   V   s    z#NotifyByWriteFile.notifyUnsubscribec             C   s$   d| j || f }| j| d S )Nz(%s Listener "%s" of Topic "%s" has died
)r(   r.   r+   r/   )r   r   r   r0   r   r   r   r   [   s    z$NotifyByWriteFile.notifyDeadListener)r   r   r   c             C   s\   |dkrd| j | |f }n.|dkr:d| j | f }nd| j | f }| j| d S )Ninz0%s Sending message of topic "%s" to listener %s
prez'%s Start sending message of topic "%s"
z&%s Done sending message of topic "%s"
)r(   r.   r+   r/   )r   r   r   r   r0   r   r   r   r   b   s    zNotifyByWriteFile.notifySend)r   r   r   r   c             C   s"   d| j | f }| j| d S )Nz%s New topic "%s" created
)r(   r.   r+   r/   )r   r   r   r   r   r0   r   r   r   r   k   s    z NotifyByWriteFile.notifyNewTopic)r   c             C   s   d| j |f }| j| d S )Nz%s Topic "%s" destroyed
)r(   r+   r/   )r   r   r0   r   r   r   r   o   s    z NotifyByWriteFile.notifyDelTopic)NN)N)r   r   r    r!   r'   r   r#   r,   r-   r	   r
   r"   r   r   r   r   r   r   r   r   r   r   r   r   r$   6   s   	 r$   c               @   s   e Zd ZdZdZede de de de de de d	Zd$edddZedddZ	e
eedddZe
edddZe
edddZd%eee
dddZeeee eeef dddZeddd Zeeeef d!d"d#Zd
S )&NotifyByPubsubMessageaF  
    Handle pubsub notification messages by generating
    messages of a 'pubsub.' subtopic. Also provides
    an example of how to create a notification handler.  
    
    Use it by calling::
    
        import pubsub.utils
        pubsub.utils.useNotifyByPubsubMessage()
        ...
        pub.setNotificationFlags(...) # optional
        
    E.g. whenever a listener is unsubscribed, a 'pubsub.unsubscribe'
    message is generated. If you have subscribed a listener of 
    this topic, your listener will be notified of what listener 
    unsubscribed from what topic. 
    Zpubsubz%s.sendMessagez%s.subscribez%s.unsubscribez%s.newTopicz%s.delTopicz%s.deadListener)send	subscribeunsubscribenewTopicdelTopicdeadListenerN)topicMgrc             C   s"   d | _ d| _|d k	r| | d S )NF)	_pubTopic_NotifyByPubsubMessage__sendingcreateNotificationTopics)r   r:   r   r   r   r,      s    zNotifyByPubsubMessage.__init__c             C   sP   y| | j W n: tk
rJ   || j| _| jd t| j| Y nX dS )z
        Create the notification topics. The root of the topics created
        is self.topicRoot. The topicMgr is (usually) pub.topicMgr.
        z"root of all pubsub-specific topicsN)ZgetTopic	topicRoot
ValueErrorgetOrCreateTopicr;   setDescription_createTopicstopics)r   r:   r   r   r   r=      s    z.NotifyByPubsubMessage.createNotificationTopics)r   r   r   c             C   sF   | j d ks| jrd S | j d}||k	rBt|||d}| || d S )Nr5   )listenertopicr   )r;   r<   getSubtopicdict&_NotifyByPubsubMessage__doNotification)r   r   r   r   pubTopickwargsr   r   r   r      s    z%NotifyByPubsubMessage.notifySubscribe)r   r   c             C   sJ   | j d ks| jrd S | j d}||k	rFt|| |d}| || d S )Nr6   )rE   listenerRawrD   )r;   r<   rF   rG   ZgetCallablerH   )r   r   r   rI   rJ   r   r   r   r      s    z'NotifyByPubsubMessage.notifyUnsubscribec             C   s<   | j d ks| jrd S | j d}t||d}| || d S )Nr9   )rE   rD   )r;   r<   rF   rG   rH   )r   r   r   rI   rJ   r   r   r   r      s
    z(NotifyByPubsubMessage.notifyDeadListener)r   r   r   c             C   s\   | j dks| jrdS | j d}|dkrD||krDd|  }t|| |t||d dS )a  
        Stage must be 'pre' or 'post'. Note that any pubsub sendMessage
        operation resulting from this notification (which sends a message; 
        listener could handle by sending another message!) will NOT themselves
        lead to a send notification.
        NZsendMessager2   z(Not allowed to send messages of topic %s)rE   r   )r;   r<   rF   r.   r?   rH   rG   )r   r   r   r   ZsendMsgTopicr0   r   r   r   r      s    z NotifyByPubsubMessage.notifySend)r   r   r   r   c             C   s@   | j d ks| jrd S | j d}t||||d}| || d S )Nr7   )rE   r   r   args)r;   r<   rF   rG   rH   )r   r   r   r   r   rI   rJ   r   r   r   r      s
    z$NotifyByPubsubMessage.notifyNewTopic)r   c             C   s6   | j d ks| jrd S | j d}| |t|d d S )Nr8   )name)r;   r<   rF   rH   rG   )r   r   rI   r   r   r   r      s    z$NotifyByPubsubMessage.notifyDelTopic)rI   rJ   c             C   s$   d| _ z|jf | W d d| _ X d S )NTF)r<   Zpublish)r   rI   rJ   r   r   r   Z__doNotification   s    z&NotifyByPubsubMessage.__doNotification)N)N)r   r   r    r!   r>   rG   rC   r   r,   r=   r	   r
   r"   r   r   r   r#   r   r   r   r   r   r   rH   r   r   r   r   r3   t   s$   	 r3   )topicMapr:   c                s   d& fdd	}|| d ddddd	 || d
 ddddd || d ddddd || d dddddd || d ddd  || d! d"d#d$d% dS )'al  
    Create notification topics. These are used when some of the notification flags have been set to True (see
    pub.setNotificationFlags(). The topicMap is a dict where key is the notification type, and value is the topic
    name to create. Notification type is a string in ('send', 'subscribe', 'unsubscribe', 'newTopic', 'delTopic',
    'deadListener').
    Nc                s$     | }|| ||| d S )N)r@   rA   ZsetMsgArgSpec)_name_descZ	_requiredr   rE   )r:   r   r   r7      s    

z_createTopics.<locals>.newTopicr5   z,whenever a listener is subscribed to a topicz%topic that listener has subscribed toz,instance of pub.Listener containing listenerz8false if listener was already subscribed, true otherwise)rO   rP   rE   rD   r   r6   z0whenever a listener is unsubscribed from a topicz:instance of Topic that listener has been unsubscribed fromzAinstance of pub.Listener unsubscribed; None if listener not foundzlistener unsubscribed)rO   rP   rE   rD   rK   r4   z*sent at beginning and end of sendMessage()z(instance of topic for message being sentz0stage of send operation: "pre" or "post" or "in"zwhich listener being sent to)rO   rP   rE   r   rD   r7   zwhenever a new topic is definedzinstance of Topic createdzdescription of topic (use)zHthe argument names/descriptions for arguments that listeners must acceptz1which args are required (all others are optional))rO   rP   rE   r   rL   r   r8   zwhenever a topic is deletedz2full name of the Topic instance that was destroyed)rO   rP   rM   r9   z4whenever a listener dies without having unsubscribedz1instance of Topic that listener was subscribed toz1instance of pub.Listener containing dead listener)rO   rP   rE   rD   )Nr   )rN   r:   r7   r   )r:   r   rB      sF    rB   NT)	publisherallc             K   sN   | dkrddl m} | } |  }t|}| | | jf d|i| dS )a[  
    Will cause all of pubsub's notifications of pubsub "actions" (such as
    new topic created, message sent, listener subscribed, etc) to be sent
    out as messages. Topic will be 'pubsub' subtopics, such as
    'pubsub.newTopic', 'pubsub.delTopic', 'pubsub.sendMessage', etc.

    The 'all' and kwargs args are the same as pubsub's setNotificationFlags(), 
    except that 'all' defaults to True.
    
    The publisher is rarely needed:

    * The publisher must be specfied if pubsub is not installed
      on the system search path (ie from pubsub import ... would fail or
      import wrong pubsub -- such as if pubsub is within wxPython's
      wx.lib package). Then pbuModule is the pub module to use::

        from wx.lib.pubsub import pub
        from wx.lib.pubsub.utils import notification
        notification.useNotifyByPubsubMessage()

    Nr   )pubrR   ) rS   getDefaultPublisherZgetTopicMgrr3   addNotificationHandlersetNotificationFlags)rQ   rR   rJ   rS   r:   notifHandlerr   r   r   useNotifyByPubsubMessage"  s    
rY   )r%   r&   rQ   rR   c             K   sH   |dkrddl m} | }t| |}|| |jf d|i| dS )a?  
    Will cause all pubsub notifications of pubsub "actions" (such as new topic created, message sent, listener died
    etc) to be written to specified file (or stdout if none given). The fileObj need only provide a 'write(string)'
    method.
    
    The first two arguments are the same as those of NotifyByWriteFile constructor. The 'all' and kwargs arguments
    are those of pubsub's setNotificationFlags(), except that 'all' defaults to True.  See useNotifyByPubsubMessage()
    for an explanation of pubModule (typically only if pubsub inside wxPython's wx.lib)
    Nr   )rS   rR   )rT   rS   rU   r$   rV   rW   )r%   r&   rQ   rR   rJ   rS   rX   r   r   r   useNotifyByWriteFileB  s    

rZ   )NT)NNNT)r!   typingr   r   r   r   Zcorer   r   r	   r
   r   r   r$   r3   r#   rB   r"   rY   rZ   r   r   r   r   <module>   s   >x6 