B
    lßU\±!  ã               @   sÖ   d Z dZdZdZddlmZ ddlmZmZm	Z	 yddl
mZ W nF ek
r†   yddlmZ W n  ek
r€   ddlmZ Y nX Y nX d	d
dgZdd„ ZdZG dd	„ d	eƒZG dd„ deƒZddd„Zddd
„ZdS )a3  
Contributed by Joshua R English, adapted by Oliver Schoenborn to be
consistent with pubsub API.

An extension for pubsub (http://pubsub.sourceforge.net) so topic tree
specification can be encoded in XML format rather than pubsub's default
Python nested class format.

To use:

    xml = '''
        <topicdefntree>
        <description>Test showing topic hierarchy and inheritance</description>
        <topic id="parent">
            <description>Parent with a parameter and subtopics</description>
            <listenerspec>
                <arg id="name" optional="true">given name</arg>
                <arg id="lastname">surname</arg>
            </listenerspec>

            <topic id="child">
                <description>This is the first child</description>
                <listenerspec>
                    <arg id="nick">A nickname</arg>
                </listenerspec>
            </topic>
        </topic>
        </topicdefntree>
    '''

These topic definitions are loaded through an XmlTopicDefnProvider:

    pub.addTopicDefnProvider( XmlTopicDefnProvider(xml) )

The XmlTopicDefnProvider also accepts a filename instead of XML string:

    provider = XmlTopicDefnProvider("path/to/XMLfile.xml", TOPIC_TREE_FROM_FILE)
    pub.addTopicDefnProvider( provider )

Topics can be exported to an XML file using the exportTopicTreeSpecXml function.
This will create a text file for the XML and return the string representation
of the XML tree.

:copyright: Copyright since 2013 by Oliver Schoenborn, all rights reserved.
:license: BSD, see LICENSE_BSD_Simple.txt for details.
zJoshua R Englishé   z
2013-07-27é   )ÚITopicTreeVisitor)ÚITopicDefnProviderÚArgSpecGivenÚTOPIC_TREE_FROM_STRINGé    )ÚElementTreeÚXmlTopicDefnProviderÚexportTopicTreeSpecXmlÚTOPIC_TREE_FROM_FILEc             C   s<   t  | ¡s8yt  | ¡} W n   td| ƒ tdƒ‚Y nX | S )zh
    Assume an ETree.Element object or a string representation.
    Return the ETree.Element object
    zValue ErrorzCannot convert to element)ÚETZ	iselementZ
fromstringÚprintÚ
ValueError)Úelem© r   ú@lib/python3.7/site-packages/pubsub/utils/xmltopicdefnprovider.pyÚ	_get_elemJ   s    

r   Úfilec               @   sb   e Zd ZG dd„ deƒZG dd„ deƒZefdd„Zdd„ Z	dd
d„Z
dd„ Zdd„ Zdd„ Zd	S )r	   c               @   s   e Zd ZdS )z#XmlTopicDefnProvider.XmlParserErrorN)Ú__name__Ú
__module__Ú__qualname__r   r   r   r   ÚXmlParserError\   s   r   c               @   s   e Zd ZdS )z2XmlTopicDefnProvider.UnrecognizedSourceFormatErrorN)r   r   r   r   r   r   r   ÚUnrecognizedSourceFormatError_   s   r   c             C   sR   i | _ d| _|tkr0|  tt|dd ¡ ƒ¡ n|tkrH|  t|ƒ¡ ntƒ ‚d S )NÚ Úr)Úmode)	Ú_topicsÚ_treeDocr   Ú_parse_treer   ÚopenÚreadr   r   )ÚselfZxmlÚformatr   r   r   Ú__init__b   s    zXmlTopicDefnProvider.__init__c             C   sN   |  d¡}|d krd| _nd |j ¡ ¡| _x| d¡D ]}|  |¡ q8W d S )NÚdescriptionÚUNDOCUMENTEDú Útopic)Úfindr   ÚjoinÚtextÚsplitÚfindallÚ_parse_topic)r!   ÚtreeZdoc_nodeÚnoder   r   r   r   l   s    
z XmlTopicDefnProvider._parse_treeNc          	   C   s<  |pg }|pi }|pg }|  d¡}|d kr0d}nd |j ¡ ¡}| d¡}|d krZtdƒ‚xr| d¡D ]d}| d¡}	|	d kr„tdƒ‚|j ¡ }
|
p”d}
d |
 ¡ ¡}
|
||	< | dd	¡ ¡ d
krf| 	|	¡ qfW t
|t|ƒƒ}| 	| d¡¡ ||f| jt|ƒ< x8| d¡D ]*}|  ||d d … | ¡ |d d … ¡ q
W d S )Nr$   r%   r&   Úidz'topic element must have an id attributezlistenerspec/argz%arg element must have an id attributeÚoptionalr   )ÚtrueÚtZyesÚyr'   )r(   r)   r*   r+   Úgetr   r,   ÚstripÚlowerÚappendr   Útupler   r-   Úcopy)r!   r/   ÚparentsZspecsZreqlistZdescNodeZdescZnode_idÚthisZthis_idZ	this_descZdefnZsubtopicr   r   r   r-   w   s2    



z!XmlTopicDefnProvider._parse_topicc             C   s   | j  |d¡S )N)NN)r   r5   )r!   ZtopicNameTupler   r   r   ÚgetDefnž   s    zXmlTopicDefnProvider.getDefnc             C   s
   | j  ¡ S )N)r   Úkeys)r!   r   r   r   Ú
topicNames¡   s    zXmlTopicDefnProvider.topicNamesc             C   s   | j S )N)r   )r!   r   r   r   Ú
getTreeDoc¤   s    zXmlTopicDefnProvider.getTreeDoc)NNN)r   r   r   ÚRuntimeErrorr   r   r   r   r#   r   r-   r=   r?   r@   r   r   r   r   r	   [   s   

'c               @   s4   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ ZdS )Ú
XmlVisitorc             C   s   || _ g | _d S )N)r.   Úknown_topics)r!   r   r   r   r   r#   ©   s    zXmlVisitor.__init__c             C   s   | j g| _d S )N)r.   Úroots)r!   r   r   r   Ú_startTraversal­   s    zXmlVisitor._startTraversalc             C   s®  |  ¡ r| j| _d S | jr8t | jd dd| ¡ i¡}nt dd| ¡ i¡}| ¡ \}}|p^d}|pfd}t |d¡}| 	¡ }|r’d 
| ¡ ¡|_nd|_| ¡ }g }| ¡ }	xB|	rî|	| jkrä|	 ¡ \}
}|
rÖ| |
¡ |rä| |¡ |	 ¡ }	q®W |sú|r˜t |d¡}xF|D ]>}||krqt |d	d|i¡}d 
| |d¡ ¡ ¡|_qW xH|D ]@}||krfqTt |d	|d
dœ¡}d 
| |d¡ ¡ ¡|_qTW || _| j |¡ d S )Néÿÿÿÿr'   r0   r   r$   r&   r%   ZlistenerspecÚargÚTrue)r0   r1   )ZisAllr.   Ú	last_elemrD   r   Ú
SubElementZgetNodeNameÚElementZgetArgsZgetDescriptionr)   r+   r*   ZgetArgDescriptionsZ	getParentrC   Úextendr5   r8   )r!   ZtopicObjZ	this_elemZreqÚoptZ	desc_elemZ	topicDescZargDescriptionsZ
known_argsÚparentZp_reqZp_optÚspecrG   Zarg_elemr   r   r   Ú_onTopic°   sP    







zXmlVisitor._onTopicc             C   s   | j  | j¡ d S )N)rD   r8   rI   )r!   r   r   r   Ú_startChildrená   s    zXmlVisitor._startChildrenc             C   s   | j  ¡  d S )N)rD   Úpop)r!   r   r   r   Ú_endChildrenä   s    zXmlVisitor._endChildrenN)r   r   r   r#   rE   rP   rQ   rS   r   r   r   r   rB   ¨   s
   1rB   c             C   s¢   d|d  }t | ƒr|| jr$| j ¡ s.|d | _x4| D ],}t||d ƒ |jrV|j ¡ s4|d |_q4W |jrt|j ¡ sž||_n"|r˜| jr| j ¡ s˜|| _nd| _d S )NÚ
z    z  é   )Úlenr*   r6   ÚindentÚtail)r   ÚlevelÚiÚer   r   r   rW   é   s    

rW   NÚbakc       
      C   sÆ   |dkrddl m} | ¡ }n t|tƒr>ddl m} | |¡}t d¡}|rht |d¡}d 	| 
¡ ¡|_| t|ƒ¡}| |¡ t|ƒ | r¼d|  }|r¤| ||¡ t |¡}	|	 |dd	¡ t |¡S )
zN
    If rootTopic is None, then pub.getDefaultTopicTreeRoot() is assumed.
    Nr   )ÚpubZtopicdefntreer$   r&   z%s.xmlzutf-8T)r   r]   ZgetDefaultTopicTreeRootÚ
isinstanceÚstrZgetTopicr   rK   rJ   r)   r+   r*   ZTopicTreeTraverserrB   ZtraverserW   Z_backupIfExistsr   ÚwriteZtostring)
Z
moduleNameZ	rootTopicr\   Z	moduleDocr]   r.   Zmod_descZ	traverserÚfilenameZfulltreer   r   r   r
   û   s(    





)r   )NNr\   N)Ú__doc__Ú
__author__Z__revision__Z__date__Zcore.topictreetraverserr   Zcore.topicdefnproviderr   r   r   Zelementtreer   r   ÚImportErrorZ	xml.etreeZcElementTreeÚ__all__r   r   r	   rB   rW   r
   r   r   r   r   Ú<module>.   s*   MA
