o
    ÖÁgF>  ã                   @   sˆ   d Z ddlmZ ddlmZmZmZ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G dd„ deƒZdS )zF
This file contains the JSON parser that works like a SAX XML parser.
é    )Úkwonly_defaultsé   )Ú	my_xrangeÚ	my_unichrÚ
my_unicodeÚutf8chr)ÚJSONConfigExceptionc                       s   e Zd Z‡ fdd„Z‡  ZS )ÚJSONConfigParserExceptionc                    sD   || _ |jd | _|jd | _d|| j| jf }tt| ƒ |¡ d S )Nr   z%s [line=%s;col=%s])Úerror_messageÚlineÚcolumnÚsuperr	   Ú__init__)ÚselfÚparserr
   Úmessage©Ú	__class__© úL/home/ubuntu/cloudmapper/venv/lib/python3.10/site-packages/jsoncfg/parser.pyr      s
   z"JSONConfigParserException.__init__)Ú__name__Ú
__module__Ú__qualname__r   Ú__classcell__r   r   r   r   r	   
   s    r	   c                       sh   e Zd ZdZd‡ fdd„	Zedd„ ƒZdd„ Zd	d
„ Zdd„ Z	dd„ Z
dd„ Zddd„Zdd„ Z‡  ZS )Ú
TextParserz}
    A base class for parsers. It handles the position in the parsed text and
    tracks the current line/column number.
    é   c                    sB   t t| ƒ ¡  || _d | _d| _d| _d| _d | _d| _	d| _
d S )Nr   )r   r   r   Útab_sizeÚtextÚposÚendr   Úprev_newline_charÚ_columnÚ_column_query_pos)r   r   r   r   r   r      s   
zTextParser.__init__c                 C   sf   t | j| jƒD ]$}| j| dkr$|  j| j7  _|  j| j| j 8  _q|  jd7  _q| j| _| jS )z[ Returns the zero based column number based on the
        current position of the parser. ú	r   )r   r"   r   r   r!   r   )r   Úir   r   r   r   #   s   zTextParser.columnc                 C   s"   | j d u sJ ‚|| _ t|ƒ| _d S ©N)r   Úlenr   )r   r   r   r   r   Úinit_text_parser0   s   zTextParser.init_text_parserc                 C   s
   t | |ƒ‚)z{ Raises an exception with the given message and with the current position of
        the parser in the parsed json string. )r	   ©r   r   r   r   r   Úerror5   s   
zTextParser.errorc                 C   s¶   | j |  kr| jksJ ‚ J ‚t|| jƒ}t| j |ƒD ]9| _ | j| j  }||ƒs, d S |dv rR| jd ur>| j|kr>d | _n
|| _|  jd7  _| j d | _d| _qd | _q|| _ d S )Nú
r   r   )	r   r   Úminr   r   r    r   r"   r!   )r   Ú
target_posÚis_char_skippable_funcÚcr   r   r   Ú
skip_chars:   s    
zTextParser.skip_charsc                 C   s   |   |dd„ ¡ dS )z”
        Moves the pointer to target_pos (if the current position is less than target_pos)
        and keeps track the current line/column.
        c                 S   s   dS ©NTr   )r.   r   r   r   Ú<lambda>T   s    z$TextParser.skip_to.<locals>.<lambda>N)r/   )r   r,   r   r   r   Úskip_toO   s   zTextParser.skip_toc                 C   s   |   | jd ¡ dS )z Skips a single character. r   N)r2   r   ©r   r   r   r   Ú	skip_charV   s   zTextParser.skip_charr   c                 C   s"   | j | }|| jkrdS | j| S )zœ Looking forward in the input text without actually stepping the current position.
        returns None if the current position is at the end of the input. N)r   r   r   )r   Úoffsetr   r   r   r   ÚpeekZ   s   


zTextParser.peekc                 C   s(   |   ¡ |kr|  d|f ¡ |  ¡  dS )zÆ
        If the current position doesn't hold the specified c character then it raises an
        exception, otherwise it skips the specified character (moves the current position forward).
        zExpected "%c"N)r6   r)   r4   ©r   r.   r   r   r   Úexpectb   s   zTextParser.expect)r   )r   )r   r   r   Ú__doc__r   Úpropertyr   r'   r)   r/   r2   r4   r6   r8   r   r   r   r   r   r      s    

r   c                   @   s   e Zd Ze		ddd„ƒZdS )ÚJSONParserParamsr   FTc                 C   s"   || _ || _|| _|| _|| _dS )aÌ  
        :param tab_size: Used when calculating the column of the error location. Defaults to 4.
        :param root_is_array: True: the root of the json hierarchy must be an object/dict.
        False: the root of the json hierarchy must be an array/list.
        :param allow_comments: True: allow single/multi-line comments.
        :param allow_unquoted_keys: Specifying true allows the json object keys to be
        specified without quotes if they don't contain spaces or special characters.
        :param allow_trailing_commas: Allow putting an optional comma after the last
        item in json objects and arrays. Comes handy when you are exchanging lines in
        the config with copy pasting.
        N)r   Úroot_is_arrayÚallow_commentsÚallow_unquoted_keysÚallow_trailing_commas)r   r   r<   r=   r>   r?   r   r   r   r   m   s
   
zJSONParserParams.__init__N)r   FTTT)r   r   r   r   r   r   r   r   r   r;   l   s
    ÿr;   c                       s¦   e Zd ZdZedƒZedƒZeeB Zeƒ f‡ fdd„	Z	dd„ Z
dd	„ Zd
d„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Z‡  ZS ) Ú
JSONParseraã  
    A simple json parser that works with a fixed sized input buffer (without input streaming) but
    this should not be a problem in case of config files that usually have a small limited size.
    This parser emits events similarly to a SAX XML parser. The user of this class can implement
    several different kind of event listeners. We will work with a listener that builds a json
    object hierarchy but later we could implement for example a json validator listener...
    z 	
z	{}[]",:/*c                    s$   t t| ƒj|jd || _d | _d S )N)r   )r   r@   r   r   ÚparamsÚlistener)r   rA   r   r   r   r   Ž   s   
zJSONParser.__init__c                 C   sÂ   |  | ¡ zV|  |¡ || _|  ¡ }|dkr$| jjr|  d¡ |  ¡  n|dkr6| jjs1|  d¡ |  ¡  n|  d| jjr?dnd ¡ |  ¡ durU|  d¡ W | 	¡  dS W | 	¡  dS | 	¡  w )a‰  
        Parses the specified json_text and emits parser events to the listener.
        If root_is_array then the root element of the json has to be an array/list,
        otherwise the expected root is a json object/dict.

        In case of python2 the json_text can be either an utf8 encoded string
        or a unicode object and the fired parser events will use the same format.
        Ú{z0The root of the json is expected to be an array!ú[z1The root of the json is expected to be an object!z&The json string should start with "%s"Nz'Garbage detected after the parsed json!)
Úbegin_parsingr'   rB   Ú_skip_spaces_and_peekrA   r<   r)   Ú_parse_objectÚ_parse_arrayÚend_parsing)r   Ú	json_textrB   r.   r   r   r   Úparse“   s*   
	




ÿýzJSONParser.parsec                    sŒ   	 ˆ   ˆ j‡ fdd„¡ ˆ  ¡ }ˆ jjs|S |dkr|S ˆ  d¡}|dkr2ˆ  ˆ jd ¡ ˆ  ¡  n|dkrCˆ  ˆ jd ¡ ˆ  ¡  n|S q)zÂ Skips all spaces and comments.
        :return: The first character that follows the skipped spaces and comments or
                None if the end of the json string has been reached.
        r   c                    s
   | ˆ j v S r%   )Úspaces)Úxr3   r   r   r1   º   s   
 z2JSONParser._skip_spaces_and_peek.<locals>.<lambda>ú/é   Ú*)	r/   r   r6   rA   r=   r2   r   Ú_skip_singleline_commentÚ_skip_multiline_comment)r   r.   Údr   r3   r   rF   ³   s    


ðz JSONParser._skip_spaces_and_peekc                 C   sF   t | j| jƒD ]}| j| dv r|  |d ¡  d S q|  | j¡ d S )Nr*   r   )r   r   r   r   r2   ©r   r   r   r   r   rQ   Ê   s   þz#JSONParser._skip_singleline_commentc                 C   sZ   t | j| jd ƒD ]}| j| dkr%| j|d  dkr%|  |d ¡  d S q	|  d¡ d S )Nr   rP   rN   rO   zMultiline comment isn't closed.)r   r   r   r   r2   r)   rT   r   r   r   rR   Ò   s    €z"JSONParser._skip_multiline_commentc                 C   sð   |   ¡ dksJ ‚| j ¡  |  ¡  d}	 |  ¡ }|dkr'|  ¡  | j ¡  d S |sJ|  d¡ |  ¡ }|dkrJ| jjs?|  	d¡ |  ¡  | j ¡  d S |  
| jj¡\}}}| j ||¡ |  |¡ |  ¡ }|dkrm|  	d¡ |  ¡  |  ¡  d	}q)
NrC   Tr   Ú}ú,ú/Trailing commas aren't enabled for this parser.ú:zExpected ":"F)r6   rB   Úbegin_objectr4   rF   Ú
end_objectr8   rA   r?   r)   Ú_parse_and_return_stringr>   Úbegin_object_itemr2   Ú_parse_value)r   Ú
first_itemr.   ÚkeyÚ
key_quotedÚpos_after_keyr   r   r   rG   Ù   s>   





ÿ

ßzJSONParser._parse_objectc                 C   s¢   |   ¡ dksJ ‚| j ¡  |  ¡  d}	 |  ¡ }|dkr'|  ¡  | j ¡  d S |sJ|  d¡ |  ¡ }|dkrJ| jjs?|  	d¡ |  ¡  | j ¡  d S |  
¡  d}q)NrD   Tr   ú]rV   rW   F)r6   rB   Úbegin_arrayr4   rF   Ú	end_arrayr8   rA   r?   r)   r]   )r   r^   r.   r   r   r   rH     s,   




ízJSONParser._parse_arrayc                 C   s<   |   ¡ }|dkr|  ¡  d S |dkr|  ¡  d S |  ¡  d S )NrC   rD   )rF   rG   rH   Ú_parse_scalarr7   r   r   r   r]     s   zJSONParser._parse_valuec                 C   s,   |   d¡\}}}| j ||¡ |  |¡ d S r0   )r[   rB   Úscalarr2   )r   Ú
scalar_strÚscalar_str_quotedÚpos_after_scalarr   r   r   re   $  s   zJSONParser._parse_scalarc                 C   s6   |   ¡ }|dk}|s|s|  d¡ |r|  ¡ S |  ¡ S )Nú"zUnquoted keys arn't allowed.)rF   r)   Ú_parse_and_return_quoted_stringÚ!_parse_and_return_unquoted_string)r   Úallow_unquotedr.   Úquotedr   r   r   r[   )  s   
z#JSONParser._parse_and_return_stringc                 C   sZ   | j }t| j | jƒD ]}| j| | jv r nq
| j}||kr#|  d¡ | j||… d|fS )zê
        Parses a string that has no quotation marks so it doesn't
        contain any special characters and we don't have to interpret
        any escape sequences.
        :return: (string, quoted=False, end_of_string_pos)
        zExpected a scalar here.F)r   r   r   r   Úspaces_and_special_charsr)   )r   Úbeginr   r   r   r   rl   3  s   ÿ
z,JSONParser._parse_and_return_unquoted_stringc                 C   sD  g }| j d }|}t| jtƒrtnt}|| jk r›| j| }|dk r0|dkr0|  |¡ |  d¡ nf|dkrN||k rB| 	| j||… ¡ |d7 }d 
|¡d|fS |dkr’||k r`| 	| j||… ¡ |d7 }|| jkrjn1| j| }|d	kr‚|  |¡\}}| 	||ƒ¡ n|  ||¡\}}| 	|¡ |}n|d7 }|| jk s|  d
¡ dS )zÁ
        Parses a string that has quotation marks so it may contain
        special characters and escape sequences.
        :return: (unescaped_string, quoted=True, end_of_string_pos)
        r   ú r#   zEEncountered a control character that isn't allowed in quoted strings.rj   Ú Tú\Úuú6Reached the end of stream while parsing quoted string.N)r   Ú
isinstancer   r   r   r   r   r2   r)   ÚappendÚjoinÚ_handle_unicode_escapeÚ_handle_escape)r   Úresultr   Úsegment_beginÚmy_chrr.   Ú
code_pointÚcharr   r   r   rk   D  s<   







çz*JSONParser._parse_and_return_quoted_stringc                 C   sR  | j | dk r|  d¡ |d7 }zt| j||d … dƒ}W n ty4   |  |d ¡ |  d¡ Y d S w |d7 }d|  krCd	k r¥n ||fS | j | d
kr¥| j| dkr¥| j|d  dkr¥zt| j|d |d
 … dƒ}W n ty…   |  |¡ |  d¡ Y ||fS w d	|  krdk r¥n ||fS |d
7 }d|d d> |d	 B  }||fS )Né   ru   r   r   é   rO   z'Error decoding unicode escape sequence.i Ø  i Ü  é   rs   rt   i à  i   é
   )r   r)   Úintr   Ú
ValueErrorr2   )r   r   r~   Úlow_surrogater   r   r   ry   j  s8   
þô  
øýÿz!JSONParser._handle_unicode_escapec              	   C   sH   ddddddddd	œ  |¡}|d u r|  |d
 ¡ |  d¡ ||d
 fS )Nrs   rN   rj   úúr#   úÚ
)rs   rN   rj   ÚbÚfÚtÚrÚnr   z2Quoted string contains an invalid escape sequence.)Úgetr2   r)   )r   r   r.   r   r   r   r   rz   ƒ  s   ø	÷

zJSONParser._handle_escape)r   r   r   r9   ÚsetrL   Úspecial_charsro   r;   r   rK   rF   rQ   rR   rG   rH   r]   re   r[   rl   rk   ry   rz   r   r   r   r   r   r@   ‚   s&     (	
&r@   c                       sh   e Zd ZdZ‡ fdd„Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Z‡  ZS )ÚParserListenerz" Base class for parser listeners. c                    s   t t| ƒ ¡  d | _d S r%   )r   r“   r   r   r3   r   r   r   r   –  s   
zParserListener.__init__c                 C   s   t | j|ƒ‚r%   )r	   r   r(   r   r   r   r)   š  s   zParserListener.errorc                 C   s
   || _ d S r%   ©r   )r   r   r   r   r   rE     ó   
zParserListener.begin_parsingc                 C   s
   d | _ d S r%   r”   r3   r   r   r   rI      r•   zParserListener.end_parsingc                 C   ó   t ƒ ‚r%   ©ÚNotImplementedErrorr3   r   r   r   rY   £  ó   zParserListener.begin_objectc                 C   r–   r%   r—   r3   r   r   r   rZ   ¦  r™   zParserListener.end_objectc                 C   r–   r%   r—   )r   r_   r`   r   r   r   r\   ©  r™   z ParserListener.begin_object_itemc                 C   r–   r%   r—   r3   r   r   r   rc   ¬  r™   zParserListener.begin_arrayc                 C   r–   r%   r—   r3   r   r   r   rd   ¯  r™   zParserListener.end_arrayc                 C   r–   r%   r—   )r   rf   Úscalar_quotedr   r   r   rf   ²  r™   zParserListener.scalar)r   r   r   r9   r   r)   rE   rI   rY   rZ   r\   rc   rd   rf   r   r   r   r   r   r“   ”  s    r“   N)r9   Úkwonly_argsr   Úcompatibilityr   r   r   r   Ú
exceptionsr   r	   Úobjectr   r;   r@   r“   r   r   r   r   Ú<module>   s    	Y  