a
    Z,É_|2  ã                   @   sl   d Z ddlmZ ddlmZ ddlmZ G dd„ deƒZG dd„ deƒZG d	d
„ d
eƒZG dd„ deƒZ	dS )z  Dual ParserNode implementation é    )Ú
assertions)Úaugeasparser)Úapacheparserc                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )ÚDualNodeBasez³ Dual parser interface for in development testing. This is used as the
    base class for dual parser interface classes. This class handles runtime
    attribute value assertions.c                 C   s   | j  |¡ | j |¡ dS )z Call save for both parsers N)ÚprimaryÚsaveÚ	secondary)ÚselfÚmsg© r   úE/usr/lib/python3/dist-packages/certbot_apache/_internal/dualparser.pyr      s    zDualNodeBase.savec                 C   s@   t | j|ƒ}t | j|ƒ}|dkt|ƒg}t|ƒs<t ||¡ |S )z Attribute value assertion Úmetadata)Úgetattrr   r   ÚcallableÚanyr   ÚassertEqualSimple)r	   ZanameZfirstvalZ	secondvalZ
exclusionsr   r   r   Ú__getattr__   s    üzDualNodeBase.__getattr__c                 C   s   |   td|¡S )zA Traverses the ancestor tree and returns ancestors matching name Úfind_ancestors©Ú_find_helperÚDualBlockNode)r	   Únamer   r   r   r      s    zDualNodeBase.find_ancestorsc                 K   sü   t | j|ƒ|fi |¤Ž}t | j|ƒ|fi |¤Ž}t |¡}t |¡}g }	|rl|rl|	 ||d |d d¡ nŒ|r’|D ]}
|	 ||d |
d¡ qtnf|r¸|D ]}
|	 ||
|d d¡ qšn@t|ƒt|ƒksÌJ ‚|  ||¡}|D ]\}}|	 |||d¡ qÜ|	S )a.  A helper for find_* functions. The function specific attributes should
        be passed as keyword arguments.

        :param interfaces.ParserNode nodeclass: The node class for results.
        :param str findfunc: Name of the find function to call
        :param str search: The search term
        r   ©r   r   )r   r   r   r   ZisPassNodeListÚappendÚlenÚ_create_matching_list)r	   Z	nodeclassZfindfuncÚsearchÚkwargsZprimary_resZsecondary_resZpass_primaryZpass_secondaryZ	new_nodesÚcZmatchesÚpÚsr   r   r   r   #   s0    	

ÿ
ÿÿzDualNodeBase._find_helperN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   r   r   r   r      s
   r   c                   @   s   e Zd ZdZdd„ ZdS )ÚDualCommentNodez5 Dual parser implementation of CommentNode interface c                 K   s†   |  dd¡ |  dd¡ | d¡}| d¡}|s4|rN|r<|s@J ‚|| _|| _n$tjf i |¤Ž| _tjf i |¤Ž| _t 	| j| j¡ dS )a<   This initialization implementation allows ordinary initialization
        of CommentNode objects as well as creating a DualCommentNode object
        using precreated or fetched CommentNode objects if provided as optional
        arguments primary and secondary.

        Parameters other than the following are from interfaces.CommentNode:

        :param CommentNode primary: Primary pre-created CommentNode, mainly
            used when creating new DualParser nodes using add_* methods.
        :param CommentNode secondary: Secondary pre-created CommentNode
        r   Nr   )
Ú
setdefaultÚpopr   r   r   ZAugeasCommentNoder   ZApacheCommentNoder   ÚassertEqual©r	   r   r   r   r   r   r   Ú__init__N   s    

zDualCommentNode.__init__N)r!   r"   r#   r$   r*   r   r   r   r   r%   K   s   r%   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚDualDirectiveNodez7 Dual parser implementation of DirectiveNode interface c                 K   s†   |  dd¡ |  dd¡ | d¡}| d¡}|s4|rN|r<|s@J ‚|| _|| _n$tjf i |¤Ž| _tjf i |¤Ž| _t 	| j| j¡ dS )aN   This initialization implementation allows ordinary initialization
        of DirectiveNode objects as well as creating a DualDirectiveNode object
        using precreated or fetched DirectiveNode objects if provided as optional
        arguments primary and secondary.

        Parameters other than the following are from interfaces.DirectiveNode:

        :param DirectiveNode primary: Primary pre-created DirectiveNode, mainly
            used when creating new DualParser nodes using add_* methods.
        :param DirectiveNode secondary: Secondary pre-created DirectiveNode


        r   Nr   )
r&   r'   r   r   r   ZAugeasDirectiveNoder   ZApacheDirectiveNoder   r(   r)   r   r   r   r*   n   s    

zDualDirectiveNode.__init__c                 C   s,   | j  |¡ | j |¡ t | j | j¡ dS )zf Sets parameters and asserts that both implementation successfully
        set the parameter sequence N)r   Úset_parametersr   r   r(   )r	   Ú
parametersr   r   r   r,   Œ   s    z DualDirectiveNode.set_parametersN)r!   r"   r#   r$   r*   r,   r   r   r   r   r+   k   s   r+   c                   @   sr   e Zd ZdZdd„ Zddd„Zddd„Zdd
d„Zdd„ Zddd„Z	ddd„Z
dd„ Zdd„ Zdd„ Zdd„ ZdS ) r   z3 Dual parser implementation of BlockNode interface c                 K   s†   |  dd¡ |  dd¡ | d¡}| d¡}|s4|rN|r<|s@J ‚|| _|| _n$tjf i |¤Ž| _tjf i |¤Ž| _t 	| j| j¡ dS )a,   This initialization implementation allows ordinary initialization
        of BlockNode objects as well as creating a DualBlockNode object
        using precreated or fetched BlockNode objects if provided as optional
        arguments primary and secondary.

        Parameters other than the following are from interfaces.BlockNode:

        :param BlockNode primary: Primary pre-created BlockNode, mainly
            used when creating new DualParser nodes using add_* methods.
        :param BlockNode secondary: Secondary pre-created BlockNode
        r   Nr   )
r&   r'   r   r   r   ZAugeasBlockNoder   ZApacheBlockNoder   r(   r)   r   r   r   r*   ˜   s    

zDualBlockNode.__init__Nc                 C   s<   | j  |||¡}| j |||¡}t ||¡ t||d}|S )zÌ Creates a new child BlockNode, asserts that both implementations
        did it in a similar way, and returns a newly created DualBlockNode object
        encapsulating both of the newly created objects r   )r   Úadd_child_blockr   r   r(   r   )r	   r   r-   ÚpositionÚprimary_newÚsecondary_newZ	new_blockr   r   r   r.   ´   s
    zDualBlockNode.add_child_blockc                 C   s<   | j  |||¡}| j |||¡}t ||¡ t||d}|S )zÔ Creates a new child DirectiveNode, asserts that both implementations
        did it in a similar way, and returns a newly created DualDirectiveNode
        object encapsulating both of the newly created objects r   )r   Úadd_child_directiver   r   r(   r+   )r	   r   r-   r/   r0   r1   Znew_dirr   r   r   r2   ¿   s
    z!DualBlockNode.add_child_directiveÚ c                 C   s8   | j  ||¡}| j ||¡}t ||¡ t||d}|S )zÐ Creates a new child CommentNode, asserts that both implementations
        did it in a similar way, and returns a newly created DualCommentNode
        object encapsulating both of the newly created objects r   )r   Úadd_child_commentr   r   r(   r%   )r	   Úcommentr/   r0   r1   Znew_commentr   r   r   r4   Ê   s
    zDualBlockNode.add_child_commentc              
   C   sn   g }|D ]`}d}|D ]6}zt  ||¡ |}W  qLW q tyH   Y qY q0 q|r`| ||f¡ qtdƒ‚q|S )aÂ   Matches the list of primary_list to a list of secondary_list and
        returns a list of tuples. This is used to create results for find_
        methods.

        This helper function exists, because we cannot ensure that the list of
        search results returned by primary.find_* and secondary.find_* are ordered
        in a same way. The function pairs the same search results from both
        implementations to a list of tuples.
        NzCould not find a matching node.)r   r(   ÚAssertionErrorr   )r	   Zprimary_listZsecondary_listZmatchedr   Úmatchr    r   r   r   r   Õ   s    

z#DualBlockNode._create_matching_listTc                 C   s   | j td||dS )a•  
        Performs a search for BlockNodes using both implementations and does simple
        checks for results. This is built upon the assumption that unimplemented
        find_* methods return a list with a single assertion passing object.
        After the assertion, it creates a list of newly created DualBlockNode
        instances that encapsulate the pairs of returned BlockNode objects.
        Úfind_blocks©Úexcluder   ©r	   r   r:   r   r   r   r8   ð   s    	
ÿzDualBlockNode.find_blocksc                 C   s   | j td||dS )a•  
        Performs a search for DirectiveNodes using both implementations and
        checks the results. This is built upon the assumption that unimplemented
        find_* methods return a list with a single assertion passing object.
        After the assertion, it creates a list of newly created DualDirectiveNode
        instances that encapsulate the pairs of returned DirectiveNode objects.
        Úfind_directivesr9   )r   r+   r;   r   r   r   r<   ü   s    	
ÿzDualBlockNode.find_directivesc                 C   s   |   td|¡S )a  
        Performs a search for CommentNodes using both implementations and
        checks the results. This is built upon the assumption that unimplemented
        find_* methods return a list with a single assertion passing object.
        After the assertion, it creates a list of newly created DualCommentNode
        instances that encapsulate the pairs of returned CommentNode objects.
        Úfind_comments)r   r%   )r	   r5   r   r   r   r=     s    	zDualBlockNode.find_commentsc                 C   s    | j  |j ¡ | j |j¡ dS )z¿Deletes a child from the ParserNode implementations. The actual
        ParserNode implementations are used here directly in order to be able
        to match a child to the list of children.N)r   Údelete_childr   )r	   Úchildr   r   r   r>     s    zDualBlockNode.delete_childc                 C   s$   | j  ¡ }| j ¡ }t ||¡ |S )zQ Fetches the list of unsaved file paths and asserts that the lists
        match )r   Úunsaved_filesr   r   r   )r	   Zprimary_filesZsecondary_filesr   r   r   r@     s    

zDualBlockNode.unsaved_filesc                 C   s$   | j  ¡ }| j ¡ }t ||¡ |S )an  
        Returns a list of file paths that have currently been parsed into the parser
        tree. The returned list may include paths with wildcard characters, for
        example: ['/etc/apache2/conf.d/*.load']

        This is typically called on the root node of the ParserNode tree.

        :returns: list of file paths of files that have been parsed
        )r   Úparsed_pathsr   r   ZassertEqualPathsList)r	   Zprimary_pathsZsecondary_pathsr   r   r   rA   $  s    

zDualBlockNode.parsed_paths)NN)NN)r3   N)T)T)r!   r"   r#   r$   r*   r.   r2   r4   r   r8   r<   r=   r>   r@   rA   r   r   r   r   r   •   s   




	r   N)
r$   Zcertbot_apache._internalr   r   r   Úobjectr   r%   r+   r   r   r   r   r   Ú<module>   s   D *