
    M/e>              	          d Z ddlZddlZddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlm	Z	 dd	lm
Z
 dd
lmZ ddlmZ  ej                  e      ZdZdegZ G d d      Z G d de      Zde	e   dee   fdZ G d de      Z G d de      ZdedefdZdedefdZd#dededefdZdededefdZd$d edee   d!edefd"Zy)%zx This file contains parsing routines and object classes to help derive meaning from
raw lists of tokens from pyparsing.     N)Any)Callable)Iterator)List)Optional)Sequence)Tuple)Type)errorsz managed by Certbot#c            	          e Zd ZdZej
                  Zdded    fdZe	de
ed   ed   ed   f   fd	       Zeej                  d
edefd              Zej                  ddee   deddfd       Zej                  	 	 ddedeed gef      dee   fd       Zej                  defd       Zej                  ddeddfd       Zddedee   fdZy)Parsablez Abstract base class for "Parsable" objects whose underlying representation
    is a tree of lists.

    :param .Parsable parent: This object's parsed parent in the tree
    Nparentc                 .    g | _         d | _        || _        y N)_data_tabsr   )selfr   s     D/usr/lib/python3/dist-packages/certbot_nginx/_internal/parser_obj.py__init__zParsable.__init__"   s     "

    returnBlockSentence
Statementsc                 $    t         t        t        fS )a
  Returns object types that this class should be able to `parse` recusrively.
        The order of the objects indicates the order in which the parser should
        try to parse each subitem.
        :returns: A list of Parsable classes.
        :rtype list:
        )r   r   r   )clss    r   parsing_hookszParsable.parsing_hooks'   s     h
**r   listsc                     t               )z Returns whether the contents of `lists` can be parsed into this object.

        :returns: Whether `lists` can be parsed as this object.
        :rtype bool:
        NotImplementedErrorr   s    r   should_parsezParsable.should_parse1        "##r   raw_list
add_spacesc                     t               )aZ   Loads information into this object from underlying raw_list structure.
        Each Parsable object might make different assumptions about the structure of
        raw_list.

        :param list raw_list: A list or sublist of tokens from pyparsing, containing whitespace
            as separate tokens.
        :param bool add_spaces: If set, the method can and should manipulate and insert spacing
            between non-whitespace tokens and lists to delimit them.
        :raises .errors.MisconfigurationError: when the assumptions about the structure of
            raw_list are not met.
        r!   r   r&   r'   s      r   parsezParsable.parse;   s     "##r   expandedmatchc                     t               )a   Iterates across this object. If this object is a leaf object, only yields
        itself. If it contains references other parsing objects, and `expanded` is set,
        this function should first yield itself, then recursively iterate across all of them.
        :param bool expanded: Whether to recursively iterate on possible children.
        :param callable match: If provided, an object is only iterated if this callable
            returns True when called on that object.

        :returns: Iterator over desired objects.
        r!   r   r+   r,   s      r   iteratezParsable.iterateJ   s     "##r   c                     t               )a   Guess at the tabbing style of this parsed object, based on whitespace.

        If this object is a leaf, it deducts the tabbing based on its own contents.
        Other objects may guess by calling `get_tabs` recursively on child objects.

        :returns: Guess at tabbing for this object. Should only return whitespace strings
            that does not contain newlines.
        :rtype str:
        r!   r   s    r   get_tabszParsable.get_tabsX   s     "##r   tabsc                     t               )a!  This tries to set and alter the tabbing of the current object to a desired
        whitespace string. Primarily meant for objects that were constructed, so they
        can conform to surrounding whitespace.

        :param str tabs: A whitespace string (not containing newlines).
        r!   r   r3   s     r   set_tabszParsable.set_tabse   r%   r   include_spacesc                 ^    | j                   D cg c]  }|j                  |       c}S c c}w )a   Dumps back to pyparsing-like list tree. The opposite of `parse`.

        Note: if this object has not been modified, `dump` with `include_spaces=True`
        should always return the original input of `parse`.

        :param bool include_spaces: If set to False, magically hides whitespace tokens from
            dumped output.

        :returns: Pyparsing-like list tree.
        :rtype list:
        )r   dump)r   r7   elems      r   r9   zParsable.dumpo   s%     7;jjAd		.)AAAs   *r   FFN    )__name__
__module____qualname____doc__abcABCMeta__metaclass__r   r   classmethodr	   r
   r   staticmethodabstractmethodr   boolr$   r   r*   r   r   r/   strr2   r6   r9    r   r   r   r      sk    KKMx
3 
 +eDM4
3CT,EW$WX + + $C $D $  $ 	$d3i $T $d $ $ 	',@D$ $*t); <=$IQRU$ $ 	
$# 
$ 
$ 	$S $d $ $B4 BDI Br   r   c                        e Zd ZdZddee   f fdZedede	fd       Z
ddeddfd	Zdd
ee   de	ddfdZdefdZdde	dee   f fdZ	 	 dde	deedge	f      dee   fdZ xZS )r   a"   A group or list of "Statements". A Statement is either a Block or a Sentence.

    The underlying representation is simply a list of these Statement objects, with
    an extra `_trailing_whitespace` string to keep track of the whitespace that does not
    precede any more statements.
    Nr   c                 2    t         |   |       d | _        y r   )superr   _trailing_whitespacer   r   	__class__s     r   r   zStatements.__init__   s     $(!r   r   r   c                 "    t        | t              S r   )
isinstancelistr#   s    r   r$   zStatements.should_parse   s    %&&r   r3   c                     | j                   D ]  }|j                  |        | j                  #d| j                  j                         z   | _        yy)aE   Sets the tabbing for this set of statements. Does this by calling `set_tabs`
        on each of the child statements.

        Then, if a parent is present, sets trailing whitespace to parent tabbing. This
        is so that the trailing } of any Block that contains Statements lines up
        with parent tabbing.
        N
)r   r6   r   r2   rO   )r   r3   	statements      r   r6   zStatements.set_tabs   sN      	%It$	%;;"(,t{{/C/C/E(ED% #r   r&   r'   c                    t        |t              st        j                  d      |r5t        |d   t              r"|d   j                         r|d   | _        |dd }|D cg c]  }t        || |       c}| _        yc c}w )z Parses a list of statements.
        Expects all elements in `raw_list` to be parseable by `type(self).parsing_hooks`,
        with an optional whitespace string at the last index of `raw_list`.
        z"Statements parsing expects a list!N)	rS   rT   r   MisconfigurationErrorrJ   isspacerO   	parse_rawr   )r   r&   r'   r:   s       r   r*   zStatements.parse   st    
 (D)../STT
8B<5(2,:N:N:P(0D%}HDLMDidJ7M
Ms   !A>c                 V    | j                   r| j                   d   j                         S y)zs Takes a guess at the tabbing of all contained Statements by retrieving the
        tabbing of the first Statement.r    )r   r2   r1   s    r   r2   zStatements.get_tabs   s%     ::::a=))++r   r7   c                 b    t         |   |      }|r| j                  || j                  gz   S |S )z Dumps this object by first dumping each statement, then appending its
        trailing whitespace (if `include_spaces` is set) )rN   r9   rO   )r   r7   datarQ   s      r   r9   zStatements.dump   s:     w|N+d77C444555r   r+   r,   r   c              #   d   K   | j                   D ]  }|j                  ||      D ]  }|   yw)z& Combines each statement's iterator.  N)r   r/   )r   r+   r,   r:   sub_elems        r   r/   zStatements.iterate   s:      JJ 	D LL59 	s   .0r   r=   r;   r<   )r?   r@   rA   rB   r   r   r   rG   r   rI   r$   rJ   r6   r   r*   r2   r9   r   r   r/   __classcell__rQ   s   @r   r   r   ~   s    )x1 ) 'C 'D ' 'FS Fd FNd3i NT Nd N# 4 DI  (-@D *t); <=IQRUr   r   list_r   c                     g }t        t        t        |                   D ]Z  }|j                  d| |          |dkD  s| |   j	                         r2| |dz
     j	                         rI|j                  dd       \ |S )z< Inserts whitespace between adjacent non-whitespace tokens. r       )reversedrangeleninsertr[   )re   spaced_statementis      r   _space_listro      sz    "$eCJ'( ,58,q5q))+E!A#J4F4F4H##As+, r   c                       e Zd ZdZededefd       Zddee   deddfdZ		 	 dd	ed
e
eegef      dee   fdZddeddfdZddedee   fdZdefdZedee   fd       ZdedefdZdedefdZy)r   zW A list of words. Non-whitespace words are typically separated with whitespace tokens. r   r   c                 j    t        | t              xr" t        |       dkD  xr t        d | D              S )z Returns True if `lists` can be parseable as a `Sentence`-- that is,
        every element is a string type.

        :param list lists: The raw unparsed list to check.

        :returns: whether this lists is parseable by `Sentence`.
        r   c              3   <   K   | ]  }t        |t                y wr   rS   rJ   .0r:   s     r   	<genexpr>z(Sentence.should_parse.<locals>.<genexpr>   s     <dJtS)<s   )rS   rT   rk   allr#   s    r   r$   zSentence.should_parse   s5     5$' =CJN =<e<<	>r   r&   r'   Nc                     |rt        |      }t        |t              rt        d |D              rt	        j
                  d      || _        y)z Parses a list of string types into this object.
        If add_spaces is set, adds whitespace tokens between adjacent non-whitespace tokens.c              3   >   K   | ]  }t        |t                 y wr   rs   rt   s     r   rv   z!Sentence.parse.<locals>.<genexpr>   s     FT:dC00Fs   z0Sentence parsing expects a list of string types.N)ro   rS   rT   anyr   rZ   r   r)   s      r   r*   zSentence.parse   sB     "8,H8T*FXFF../abb
r   r+   r,   c              #   *   K   | ||       r|  yyw)z Simply yields itself. NrK   r.   s      r   r/   zSentence.iterate   s      =E$KJ (s   r3   c                 ~    | j                   d   j                         ry| j                   j                  dd|z          y)zk Sets the tabbing on this sentence. Inserts a newline and `tabs` at the
        beginning of `self._data`. r   NrV   )r   r[   rl   r5   s     r   r6   zSentence.set_tabs   s3     ::a=  "

!TD[)r   r7   c                 6    |s| j                   S | j                  S )zK Dumps this sentence. If include_spaces is set, includes whitespace tokens.)wordsr   )r   r7   s     r   r9   zSentence.dump   s    ::zzr   c                 t    | j                   d   }|j                         sy|j                  d      }||dz   d S )z Guesses at the tabbing of this sentence. If the first element is whitespace,
        returns the whitespace after the rightmost newline in the string. r   r^   rV   rg   N)r   r[   rfind)r   firstrindexs      r   r2   zSentence.get_tabs   s<     

1}}T"VAXYr   c                     | j                   D cg c]$  }|j                         r|j                  d      & c}S c c}w )z> Iterates over words, but without spaces. Like Unspaced List. z"')r   r[   stripr   words     r   r~   zSentence.words  s-     04zzPt

6"PPPs   ;;indexc                      | j                   |   S r   r~   )r   r   s     r   __getitem__zSentence.__getitem__
  s    zz%  r   r   c                     || j                   v S r   r   r   s     r   __contains__zSentence.__contains__  s    tzz!!r   r;   r<   r=   )r?   r@   rA   rB   rG   r   rI   r$   r   r*   r   r   r   r   r/   rJ   r6   r9   r2   propertyr~   intr   r   rK   r   r   r   r      s    a 	>C 	>D 	> 	>d3i T d  (->B (T)9 :;GOPS}*S *d *4 DI  #   QtCy Q Q! ! !" " "r   r   c                        e Zd ZdZddee   ddf fdZedede	fd       Z
ddeddfd	Z	 	 dd
e	deeege	f      dee   fdZddee   de	ddfdZdefdZ xZS )r   as   Any sort of block, denoted by a block name and curly braces, like so:
    The parsed block:
        block name {
            content 1;
            content 2;
        }
    might be represented with the list [names, contents], where
        names = ["block", " ", "name", " "]
        contents = [["
    ", "content", " ", "1"], ["
    ", "content", " ", "2"], "
"]
    Nr   r   c                 @    t         |   |       d | _        d | _        y r   )rN   r   namescontentsrP   s     r   r   zBlock.__init__  s     )-
)-r   r   c                     t        | t              xr= t        |       dk(  xr- t        j	                  | d         xr t        | d   t              S )a-   Returns True if `lists` can be parseable as a `Block`-- that is,
        it's got a length of 2, the first element is a `Sentence` and the second can be
        a `Statements`.

        :param list lists: The raw unparsed list to check.

        :returns: whether this lists is parseable by `Block`.    r   rg   )rS   rT   rk   r   r$   r#   s    r   r$   zBlock.should_parse!  sP     %& N3u:? N$$U1X.N3=eAh3M	Nr   r3   c                 v    | j                   j                  |       | j                  j                  |dz          y)z[ Sets tabs by setting equivalent tabbing on names, then adding tabbing
        to contents.r>   N)r   r6   r   r5   s     r   r6   zBlock.set_tabs-  s,     	

D!tf}-r   r+   r,   c              #   x   K   | ||       r|  |r&| j                   j                  ||      D ]  }|  yyw)z@ Iterator over self, and if expanded is set, over its contents. N)r   r/   )r   r+   r,   r:   s       r   r/   zBlock.iterate3  sE      =E$KJ--h> 
 s   8:r&   r'   c                 z   t         j                  |      st        j                  d      t	        |       | _        |r|d   j                  d       | j
                  j                  |d   |       t        |       | _	        | j                  j                  |d   |       | j
                  | j                  g| _
        y)a   Parses a list that resembles a block.

        The assumptions that this routine makes are:
            1. the first element of `raw_list` is a valid Sentence.
            2. the second element of `raw_list` is a valid Statement.
        If add_spaces is set, we call it recursively on `names` and `contents`, and
        add an extra trailing space to `names` (to separate the block's opening bracket
        and the block name).
        zBlock parsing expects a list of length 2. First element should be a list of string types (the block names), and second should be another list of statements (the block content).r   rh   rg   N)r   r$   r   rZ   r   r   appendr*   r   r   r   r)   s      r   r*   zBlock.parse<  s     !!(+.. 0W X X d^
QKs#

!j1"4(HQK4jj$--0
r   c                 6    | j                   j                         S )z< Guesses tabbing by retrieving tabbing guess of self.names. )r   r2   r1   s    r   r2   zBlock.get_tabsR  s    zz""$$r   r   r=   r<   r;   )r?   r@   rA   rB   r   r   r   rG   r   rI   r$   rJ   r6   r   r   r/   r   r*   r2   rc   rd   s   @r   r   r     s    	.x1 .T .
 	NC 	ND 	N 	N.S .d . (->B (T)9 :;GOPS}1d3i 1T 1d 1,%# %r   r   
parsed_objc                 H    t        | t              sy| j                  d   dk(  S )z Checks whether parsed_obj is a comment.

    :param .Parsable parsed_obj:

    :returns: whether parsed_obj represents a comment sentence.
    :rtype bool:
    Fr   r   )rS   r   r~   )r   s    r   _is_commentr   W  s'     j(+A#%%r   c                     t        |       syt        | j                        t        t              k7  ryt	        | j                        D ]  \  }}|t        |   k7  s y y)z Checks whether parsed_obj is a "managed by Certbot" comment.

    :param .Parsable parsed_obj:

    :returns: whether parsed_obj is a "managed by Certbot" comment.
    :rtype bool:
    FT)r   rk   r~   COMMENT_BLOCK	enumerate)r   rn   r   s      r   _is_certbot_commentr   d  s]     z"
:M 22Z--. 4=## r   r   preceding_spacesc                 T    t        |       }|j                  d|z  gt        z          |S )z A "Managed by Certbot" comment.
    :param int preceding_spaces: Number of spaces between the end of the previous
        statement and the comment.
    :returns: Sentence containing the comment.
    :rtype: .Sentence
    rh   )r   r*   r   )r   r   results      r   _certbot_commentr   v  s-     fF
LL#(()M9:Mr   c                     t         j                         }| rt        |       j                         }|D ]  }|j                  |      s ||       c S  t	        j
                  d      )zf Choose a parser from type(parent).parsing_hooks, depending on whichever hook
    returns True first. zUNone of the parsing hooks succeeded, so we don't know how to parse this set of lists.)r   r   typer$   r   rZ   )r   re   hookstype_s       r   _choose_parserr     sh     ""$EV**, !e$= ! 
&
&_a ar   lists_r'   c                 B    t        ||       }|j                  | |       |S )a   Primary parsing factory function.

    :param list lists_: raw lists from pyparsing to parse.
    :param .Parent parent: The parent containing this object.
    :param bool add_spaces: Whether to pass add_spaces to the parser.

    :returns .Parsable: The parsed object.

    :raises errors.MisconfigurationError: If no parsing hook passes, and we can't
        determine which type to parse the raw lists into.
    )r   r*   )r   r   r'   parsers       r   r\   r\     s#     FF+F
LL$Mr   )   )NF) rB   rC   loggingtypingr   r   r   r   r   r   r	   r
   certbotr   	getLoggerr?   loggerCOMMENTr   r   r   rJ   ro   r   r   rI   r   r   r   r   r   r\   rK   r   r   <module>r      s'  (           			8	$
gbB bBJ? ?Hx} c B"x B"JC%H C%L
&H 
& 
&H  $	X 	 	X 	
a8 
aC 
aH 
ac 8H#5 $ [c r   