U
    ÔZj«:  ã                   @   sÂ   d Z ddlZddlZddlZddlmZ ddlmZ e e	¡Z
dZdegZG dd„ deƒZG d	d
„ d
eƒZdd„ ZG dd„ deƒZG dd„ deƒZdd„ Zdd„ Zddd„Zdd„ Zddd„ZdS )zx This file contains parsing routines and object classes to help derive meaning from
raw lists of tokens from pyparsing. é    N)Úerrors)ÚListz managed by Certbotú#c                   @   s†   e Zd ZdZejZddd„Zedd„ ƒZ	e
ejdd„ ƒƒZejdd
d„ƒZejddd„ƒZejdd„ ƒZejddd„ƒZddd„ZdS )Ú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
    Nc                 C   s   g | _ d | _|| _d S ©N)Ú_dataZ_tabsÚparent©Úselfr   © r   ú[/var/www/html/TRUCKING_PROJECT/venv/lib/python3.8/site-packages/certbot_nginx/parser_obj.pyÚ__init__   s    zParsable.__init__c                 C   s
   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:
        )ÚBlockÚSentenceÚ
Statements)Úclsr   r   r   Úparsing_hooks   s    zParsable.parsing_hooksc                 C   s
   t ƒ ‚dS )z§ Returns whether the contents of `lists` can be parsed into this object.

        :returns: Whether `lists` can be parsed as this object.
        :rtype bool:
        N©ÚNotImplementedError©Úlistsr   r   r   Úshould_parse)   s    zParsable.should_parseFc                 C   s
   t ƒ ‚dS )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.
        Nr   ©r
   Zraw_listÚ
add_spacesr   r   r   Úparse3   s    zParsable.parsec                 C   s
   t ƒ ‚dS )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.
        Nr   ©r
   ÚexpandedÚmatchr   r   r   ÚiterateB   s    zParsable.iteratec                 C   s
   t ƒ ‚dS )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:
        Nr   ©r
   r   r   r   Úget_tabsO   s    zParsable.get_tabsú    c                 C   s
   t ƒ ‚dS )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).
        Nr   ©r
   Útabsr   r   r   Úset_tabs\   s    zParsable.set_tabsc                    s   ‡ fdd„| j D ƒS )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:
        c                    s   g | ]}|  ˆ ¡‘qS r   )Údump©Ú.0Úelem©Úinclude_spacesr   r   Ú
<listcomp>r   s     z!Parsable.dump.<locals>.<listcomp>©r   ©r
   r*   r   r)   r   r%   f   s    zParsable.dump)N)F)FN)r!   )F)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚabcÚABCMetaZ__metaclass__r   Úclassmethodr   ÚstaticmethodÚabstractmethodr   r   r   r    r$   r%   r   r   r   r   r      s"   

	
	r   c                       sb   e Zd ZdZd‡ fdd„	Zedd„ ƒZddd	„Zddd„Zdd„ Z	d‡ fdd„	Z
ddd„Z‡  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.
    Nc                    s   t t| ƒ |¡ d | _d S r   )Úsuperr   r   Ú_trailing_whitespacer	   ©Ú	__class__r   r   r   |   s    zStatements.__init__c                 C   s
   t | tƒS r   )Ú
isinstanceÚlistr   r   r   r   r   ‚   s    zStatements.should_parser!   c                 C   s4   | j D ]}| |¡ q| jdk	r0d| j ¡  | _dS )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   r$   r   r    r8   )r
   r#   Z	statementr   r   r   r$   †   s    

zStatements.set_tabsFc                    sd   t |tƒst d¡‚|rJt |d tjƒrJ|d  ¡ rJ|d ˆ_|dd… }‡ ‡fdd„|D ƒˆ_dS )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!éÿÿÿÿNc                    s   g | ]}t |ˆˆ ƒ‘qS r   )Ú	parse_rawr&   ©r   r
   r   r   r+   ž   s     z$Statements.parse.<locals>.<listcomp>)	r;   r<   r   ÚMisconfigurationErrorÚsixÚstring_typesÚisspacer8   r   r   r   r@   r   r   “   s    

 
zStatements.parsec                 C   s   | j r| j d  ¡ S dS )zs Takes a guess at the tabbing of all contained Statements by retrieving the
        tabbing of the first Statement.r   Ú )r   r    r   r   r   r   r        s    zStatements.get_tabsc                    s.   t t| ƒ |¡}|r*| jdk	r*|| jg S |S )z€ Dumps this object by first dumping each statement, then appending its
        trailing whitespace (if `include_spaces` is set) N)r7   r   r%   r8   )r
   r*   Údatar9   r   r   r%   §   s    zStatements.dumpc                 c   s(   | j D ]}| ||¡D ]
}|V  qqdS )z& Combines each statement's iterator.  N)r   r   )r
   r   r   r(   Zsub_elemr   r   r   r   ¯   s    
zStatements.iterate)N)r!   )F)F)FN)r.   r/   r0   r1   r   r5   r   r$   r   r    r%   r   Ú__classcell__r   r   r9   r   r   u   s   


r   c                 C   sb   g }t tj t| ƒ¡ƒD ]D}| d| | ¡ |dkr| |  ¡ s| |d   ¡ s| dd¡ q|S )z< Inserts whitespace between adjacent non-whitespace tokens. r   é   ú )ÚreversedrB   ÚmovesÚxrangeÚlenÚinsertrD   )Úlist_Zspaced_statementÚir   r   r   Ú_space_list¸   s    $rQ   c                   @   sh   e Zd ZdZedd„ ƒZddd„Zddd	„Zddd„Zddd„Z	dd„ Z
edd„ ƒZdd„ Zdd„ ZdS )r   zW A list of words. Non-whitespace words are typically separated with whitespace tokens. c                 C   s(   t | tƒo&t| ƒdko&td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                 S   s   g | ]}t |tjƒ‘qS r   ©r;   rB   rC   r&   r   r   r   r+   Ñ   s     z)Sentence.should_parse.<locals>.<listcomp>)r;   r<   rM   Úallr   r   r   r   r   Ç   s    	ÿzSentence.should_parseFc                 C   s<   |rt |ƒ}t|tƒr(tdd„ |D ƒƒr2t d¡‚|| _dS )z� Parses a list of string types into this object.
        If add_spaces is set, adds whitespace tokens between adjacent non-whitespace tokens.c                 S   s   g | ]}t |tjƒ ‘qS r   rR   r&   r   r   r   r+   Ù   s     z"Sentence.parse.<locals>.<listcomp>z0Sentence parsing expects a list of string types.N)rQ   r;   r<   Úanyr   rA   r   r   r   r   r   r   Ó   s    
ÿ
zSentence.parseNc                 c   s   |dks|| ƒr| V  dS )z Simply yields itself. Nr   r   r   r   r   r   Ý   s    zSentence.iterater!   c                 C   s(   | j d  ¡ rdS | j  dd| ¡ dS )zk Sets the tabbing on this sentence. Inserts a newline and `tabs` at the
        beginning of `self._data`. r   Nr=   )r   rD   rN   r"   r   r   r   r$   â   s    zSentence.set_tabsc                 C   s   |s
| j S | jS )zK Dumps this sentence. If include_spaces is set, includes whitespace tokens.)Úwordsr   r-   r   r   r   r%   é   s    zSentence.dumpc                 C   s0   | j d }| ¡ sdS | d¡}||d 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   rE   r=   rH   N)r   rD   Úrfind)r
   ÚfirstÚrindexr   r   r   r    ï   s
    

zSentence.get_tabsc                 C   s   dd„ | j D ƒS )z> Iterates over words, but without spaces. Like Unspaced List. c                 S   s   g | ]}|  ¡ s| d ¡‘qS )z"')rD   Ústrip)r'   Úwordr   r   r   r+   ý   s      z"Sentence.words.<locals>.<listcomp>r,   r   r   r   r   rU   ú   s    zSentence.wordsc                 C   s
   | j | S r   ©rU   )r
   Úindexr   r   r   Ú__getitem__ÿ   s    zSentence.__getitem__c                 C   s
   || j kS r   r[   )r
   rZ   r   r   r   Ú__contains__  s    zSentence.__contains__)F)FN)r!   )F)r.   r/   r0   r1   r5   r   r   r   r$   r%   r    ÚpropertyrU   r]   r^   r   r   r   r   r   Â   s   






r   c                       sT   e Zd ZdZd‡ fdd„	Zedd„ ƒZddd	„Zddd„Zddd„Z	dd„ Z
‡  ZS )r   ar   Any sort of bloc, 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"], "
"]
    Nc                    s    t t| ƒ |¡ d | _d | _d S r   )r7   r   r   ÚnamesÚcontentsr	   r9   r   r   r     s    zBlock.__init__c                 C   s2   t | tƒo0t| ƒdko0t | d ¡o0t | 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   rH   )r;   r<   rM   r   r   r   r   r   r   r     s
    	ÿÿzBlock.should_parser!   c                 C   s    | j  |¡ | j |d ¡ dS )z[ Sets tabs by setting equivalent tabbing on names, then adding tabbing
        to contents.r!   N)r`   r$   ra   r"   r   r   r   r$   "  s    zBlock.set_tabsFc                 c   s8   |dks|| ƒr| V  |r4| j  ||¡D ]
}|V  q(dS )z@ Iterator over self, and if expanded is set, over its contents. N)ra   r   )r
   r   r   r(   r   r   r   r   (  s
    zBlock.iteratec                 C   sp   t  |¡st d¡‚t| ƒ| _|r0|d  d¡ | j |d |¡ t| ƒ| _	| j	 |d |¡ | j| j	g| _
dS )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).
        z®Block parsing expects a list of length 2. First element should be a list of string types (the bloc names), and second should be another list of statements (the bloc content).r   rI   rH   N)r   r   r   rA   r   r`   Úappendr   r   ra   r   r   r   r   r   r   0  s    




zBlock.parsec                 C   s
   | j  ¡ S )z< Guesses tabbing by retrieving tabbing guess of self.names. )r`   r    r   r   r   r   r    F  s    zBlock.get_tabs)N)r!   )FN)F)r.   r/   r0   r1   r   r5   r   r$   r   r   r    rG   r   r   r9   r   r     s   




r   c                 C   s   t | tƒsdS | 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   )r;   r   rU   )Ú
parsed_objr   r   r   Ú_is_commentJ  s    
re   c                 C   sL   t | ƒsdS t| jƒttƒkr"dS t| jƒD ]\}}|t| kr, dS q,dS )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)re   rM   rU   ÚCOMMENT_BLOCKÚ	enumerate)rd   rP   rZ   r   r   r   Ú_is_certbot_commentV  s    rh   é   c                 C   s    t | ƒ}| d| gt ¡ |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
    rI   )r   r   rf   )r   Zpreceding_spacesÚresultr   r   r   Ú_certbot_commentg  s    rk   c                 C   sF   t  ¡ }| rt| ƒ ¡ }|D ]}| |¡r|| ƒ  S qt d¡‚dS )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.N)r   r   Útyper   r   rA   )r   rO   ÚhooksÚtype_r   r   r   Ú_choose_parserr  s    
ÿro   Fc                 C   s   t || ƒ}| | |¡ |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.
    )ro   r   )Zlists_r   r   Úparserr   r   r   r?   ~  s    
r?   )ri   )NF)r1   r2   ÚloggingrB   Zcertbotr   Zacme.magic_typingr   Ú	getLoggerr.   ÚloggerÚCOMMENTrf   Úobjectr   r   rQ   r   r   re   rh   rk   ro   r?   r   r   r   r   Ú<module>   s$   
dC
DD
