a
    4ñ»jNU  ã                   @   s’   d dl mZmZ d dlZd dlZd dlZd dlmZmZ d dl	m
Z dZddd„Zddd	„Zdd
d„Zdd„ ZG dd„ deƒZG dd„ deƒZdS )é    )Úabsolute_importÚwith_statementN)ÚmodelÚi18n©ÚtextÚenc                 C   sD   t | dƒ�}| ¡  d¡}W d   ƒ n1 s.0    Y  t||| ƒS )NÚrbÚutf8)ÚopenÚreadÚdecodeÚparse_feature)ÚfilenameÚlanguageÚfÚdata© r   ú3E:\soccer\ml_env\Lib\site-packages\behave/parser.pyÚ
parse_file   s    ,r   c              
   C   sV   t | tjƒsJ ‚zt|ƒ | |¡}W n, tyP } z||_‚ W Y d }~n
d }~0 0 |S )N)Ú
isinstanceÚsixÚ	text_typeÚParserÚparseÚParserErrorr   )r   r   r   ÚresultÚer   r   r   r      s    r   c              
   C   sZ   t | tjƒsJ ‚zt|dd� | |¡}W n, tyT } z||_‚ W Y d}~n
d}~0 0 |S )aS  
    Parse a number of steps a multi-line text from a scenario.
    Scenario line with title and keyword is not provided.

    :param text: Multi-line text with steps to parse (as unicode).
    :param language:  i18n language identifier (optional).
    :param filename:  Filename (optional).
    :return: Parsed steps (if successful).
    Ústeps©ÚvariantN)r   r   r   r   Úparse_stepsr   r   )r   r   r   r   r   r   r   r   r!   !   s    
r!   c                 C   s   | sg S t dd� | ¡S )z¬
    Parse tags from text (one or more lines, as string).

    :param text: Multi-line text with tags to parse (as unicode).
    :return: List of tags (if successful).
    Útagsr   )r   Ú
parse_tagsr   r   r   r   r#   3   s    r#   c                       s8   e Zd Zd‡ fdd„	Zdd„ Zejr0eZdd„ Z‡  ZS )	r   Nc                    sJ   |r$|d| 7 }|r$|d|  ¡  7 }tt| ƒ |¡ || _|| _|| _d S )Nz at line %dz: "%s")ÚstripÚsuperr   Ú__init__ÚlineÚ	line_textr   )ÚselfÚmessager'   r   r(   ©Ú	__class__r   r   r&   A   s    zParserError.__init__c                 C   s<   t | jd ƒ}| jr0t | jt ¡ ƒ}d||f S d| S d S )Nr   zFailed to parse "%s": %szFailed to parse <string>: %s)Ú_textÚargsr   ÚsysÚgetfilesystemencoding)r)   Zarg0r   r   r   r   Ú__str__K   s
    zParserError.__str__c                 C   s   |   ¡  d¡S )Nzutf-8)Ú__unicode__Úencode©r)   r   r   r   Ú<lambda>U   ó    zParserError.<lambda>)NN)	Ú__name__Ú
__module__Ú__qualname__r&   r1   r   ÚPY2r2   Ú__classcell__r   r   r+   r   r   @   s
   
r   c                   @   sæ   e Zd ZdZd7dd„Zdd„ Zd8d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d#d$„ Zd%d&„ Zd'd(„ Zd)d*„ Zd+d,„ Zd-d.„ Zd/d0„ Zd1d2„ Zd3d4„ Zd9d5d6„ZdS ):r   zFeature file parser for behave.Nc                 C   s€   |sd}|| _ || _d| _d| _d | _d | _d | _d | _d | _d | _	d | _
g | _g | _d | _d | _d | _| j r|tj| j  | _d S )NÚfeatureÚinitr   )r   r    Ústater'   Ú	last_stepÚmultiline_startÚmultiline_leadingÚmultiline_terminatorr   r<   Ú	statementr"   ÚlinesÚtableÚexamplesÚkeywordsr   Ú	languages)r)   r   r    r   r   r   r&   \   s(    zParser.__init__c                 C   sn   | j rtj| j  | _nd | _d| _d| _d | _d | _d | _d | _	d | _
d | _d | _g | _g | _d | _d | _d S )Nr=   r   )r   r   rH   rG   r>   r'   r?   r@   rA   rB   r   r<   rC   r"   rD   rE   rF   r4   r   r   r   Úresett   s     zParser.resetc                 C   sv   |   ¡  || _| d¡D ]0}|  jd7  _| ¡ s>| jdkr>q|  |¡ q| jrZ|  d¡ | j	}|rj| |_
|   ¡  |S )NÚ
é   Ú	multilineÚ )rI   r   Úsplitr'   r$   r>   ÚactionrE   Úaction_tabler<   Úparser)r)   r   r   r'   r<   r   r   r   r   Š   s    
zParser.parsec                 C   sJ   |t |ƒd d …  ¡ }| jp t}tj| j| j||| j|d�| _	g | _d S )NrK   )r"   r   )
Úlenr$   r   ÚDEFAULT_LANGUAGEr   ZFeaturer   r'   r"   r<   )r)   Úkeywordr'   Únamer   r   r   r   Ú_build_featureŸ   s    
ÿzParser._build_featurec                 C   sh   | j r(dd | j ¡ }t|| j| j|ƒ‚|t|ƒd d …  ¡ }t | j| j||¡}|| _	| j	| j
_d S )Nz Background supports no tags: @%sz @rK   )r"   Újoinr   r'   r   rR   r$   r   Z
BackgroundrC   r<   Ú
background)r)   rT   r'   ÚmsgrU   rC   r   r   r   Ú_build_background_statement§   s    z"Parser._build_background_statementc                 C   sL   |t |ƒd d …  ¡ }tj| j| j||| jd�| _| j 	| j¡ g | _d S ©NrK   ©r"   )
rR   r$   r   ÚScenarior   r'   r"   rC   r<   Úadd_scenario©r)   rT   r'   rU   r   r   r   Ú_build_scenario_statement°   s    ÿz Parser._build_scenario_statementc                 C   sL   |t |ƒd d …  ¡ }tj| j| j||| jd�| _| j 	| j¡ g | _d S r[   )
rR   r$   r   ÚScenarioOutliner   r'   r"   rC   r<   r^   r_   r   r   r   Ú!_build_scenario_outline_statement¸   s    ÿz(Parser._build_scenario_outline_statementc                 C   sr   t | jtjƒs$d}t|| j| j|ƒ‚|t|ƒd d …  ¡ }tj	| j| j||| j
d�| _| jj | j¡ g | _
d S )Nz1Examples must only appear inside scenario outlinerK   r\   )r   rC   r   ra   r   r'   r   rR   r$   ZExamplesr"   rF   Úappend)r)   rT   r'   r*   rU   r   r   r   Ú_build_examplesÂ   s    ÿzParser._build_examplesc                 C   s   | j r
dS dS d S )Nz0Multiple features in one file are not supported.z Feature should not be used here.©r<   r4   r   r   r   Údiagnose_feature_usage_errorÒ   s    z#Parser.diagnose_feature_usage_errorc                 C   s$   | j r| j jrdS | jrdS dS d S )Nz8Background may not occur after Scenario/ScenarioOutline.z!Background does not support tags.z#Background should not be used here.)r<   Z	scenariosr"   r4   r   r   r   Údiagnose_background_usage_errorØ   s
    z&Parser.diagnose_background_usage_errorc                 C   s   | j s
dS dS d S )Nz&Scenario may not occur before Feature.z!Scenario should not be used here.re   r4   r   r   r   Údiagnose_scenario_usage_errorà   s    z$Parser.diagnose_scenario_usage_errorc                 C   s   | j s
dS dS d S )Nz-ScenarioOutline may not occur before Feature.z(ScenarioOutline should not be used here.re   r4   r   r   r   Ú%diagnose_scenario_outline_usage_erroræ   s    z,Parser.diagnose_scenario_outline_usage_errorc                 C   sx   |   d|¡}|r|  ¡ S |   d|¡}|r0|  ¡ S |   d|¡}|rH|  ¡ S |   d|¡}|r`|  ¡ S | jdkrt| jstdS dS )aL  
        Try to find the failure reason when a parse failure occurs:

            Oracle, oracle, ... what went wrong?
            Zzzz

        :param line:  Text line where parse failure occured (as string).
        :return: Reason (as string) if an explanation is found.
                 Otherwise, empty string or None.
        r<   rX   ÚscenarioÚscenario_outlinezNo feature found.N)Úmatch_keywordrf   rg   rh   ri   r    r<   )r)   r'   Úfeature_kwdÚbackground_kwdÚscenario_kwdÚscenario_outline_kwdr   r   r   Úask_parse_failure_oracleì   s    zParser.ask_parse_failure_oraclec                 C   s  |  ¡  d¡r‚| jdkr‚| jdks2| js2| jdkr6d S |  ¡ dd …   ¡ }| ¡  ¡  d¡r~|dd …   ¡ }|| _tj	| | _
d S t| d| j d ƒ}|d u rÀ|  ¡ }d	| j }t|| j| j|ƒ‚||ƒ�s|  ¡ }d
| j| j|f }|  |¡}|rþ|d| 7 }t|d | jƒ‚d S )Nú#rL   r=   r<   rK   z	language:é	   Zaction_zParser in unknown state %s;z.
Parser failure in state %s, at line %d: "%s"
z
REASON: %s)r$   Ú
startswithr>   r"   r    ÚlstripÚlowerr   r   rH   rG   Úgetattrr   r'   r   rq   )r)   r'   r   ÚfuncrY   Úreasonr   r   r   rO   	  s.    

ÿ
zParser.actionc                 C   sR   |  ¡ }| d¡r(| j |  |¡¡ dS |  d|¡}|rN|  ||¡ d| _dS dS )Nú@Tr<   F)r$   rt   r"   Úextendr#   rl   rV   r>   )r)   r'   rm   r   r   r   Úaction_init$  s    
zParser.action_initc                 C   sœ   |  d¡r&| j |  |¡¡ d| _dS |  d|¡}|rL|  ||¡ d| _dS |  d|¡}|rr|  ||¡ d| _dS |  d|¡}|r˜|  ||¡ d| _dS dS )	a  Subaction is used after first tag line is detected.
        Additional lines with tags or taggable_statement follow.

        Taggable statements (excluding Feature) are:
        * Scenario
        * ScenarioOutline
        * Examples (within ScenarioOutline)
        rz   Ztaggable_statementTrj   rk   rF   rE   F)	rt   r"   r{   r#   r>   rl   r`   rb   rd   )r)   r'   ro   rp   Zexamples_kwdr   r   r   Ú#subaction_detect_taggable_statementG  s(    	
z*Parser.subaction_detect_taggable_statementc                 C   sN   |  ¡ }|  |¡rdS |  d|¡}|r<|  ||¡ d| _dS | jj |¡ dS )NTrX   r   )r$   r}   rl   rZ   r>   r<   Údescriptionrc   )r)   r'   rn   r   r   r   Úaction_featurek  s    
zParser.action_featurec                 C   s   |  ¡ }|  |¡rdS dS )a  Entered after first tag for Scenario/ScenarioOutline or
        Examples is detected (= taggable_statement except Feature).

        Taggable statements (excluding Feature) are:
          * Scenario
          * ScenarioOutline
          * Examples (within ScenarioOutline)
        TF)r$   r}   )r)   r'   r   r   r   Úaction_taggable_statement…  s    	
z Parser.action_taggable_statementc                 C   sN   |  ¡ }|  |¡}|r.d| _| jj |¡ dS |  |¡r<dS | jj |¡ dS )z÷
        Entered when Scenario/ScenarioOutline keyword/line is detected.
        Hunts/collects scenario description lines.

        DETECT:
            * first step of Scenario/ScenarioOutline
            * next Scenario/ScenarioOutline.
        r   T)r$   Ú
parse_stepr>   rC   r   rc   r}   r~   )r)   r'   Ústepr   r   r   Úaction_scenario•  s    	

zParser.action_scenarioc                 C   s°   |  ¡ }| d¡s| d¡rLd| _| j| _|dd… | _| |d ¡| _dS | ¡ }|  	|¡}|rt| j
j |¡ dS |  |¡r‚dS | d¡r¬| j
jsœJ d	ƒ‚d
| _|  |¡S dS )ax  
        Entered when first step is detected (or nested step parsing).

        Subcases:
          * step
          * multi-line text (doc-string), following a step
          * table, following a step
          * examples for a ScenarioOutline, after ScenarioOutline steps

        DETECT:
          * next Scenario/ScenarioOutline or Examples (in a ScenarioOutline)
        z"""z'''rL   Né   r   Tú|z"TABLE-START without step detected.rE   F)ru   rt   r>   r'   r@   rB   ÚindexrA   r$   r�   rC   r   rc   r}   rP   )r)   r'   Ústrippedr‚   r   r   r   Úaction_steps´  s&    



zParser.action_stepsc                 C   s¼   |  ¡  | j¡rh| jjd }t d | j¡d| j	¡|_
|j d¡rR|jd d… |_g | _d | _d| _dS | j || jd … ¡ |d | j… }|  ¡ r¸d}|d||f 7 }t|| j| jƒ‚dS )	NéÿÿÿÿrJ   z
text/plainú:r   TzBAD-INDENT in multiline text: z"Line '%s' would strip leading '%s')r$   rt   rB   rC   r   r   ÚTextrW   rD   r@   r   rU   Úendswithr>   rc   rA   r   r'   r   )r)   r'   r‚   Zremoved_line_prefixr*   r   r   r   Úaction_multilineÜ  s(    ÿÿzParser.action_multilinec                 C   sÞ   |  ¡ }| d¡sp| jr*| j| j_d | _n0| jjd }| j|_|j d¡rZ|jd d… |_d | _d| _|  	|¡S dd„ t
 d|dd… ¡D ƒ}| jd u rªt || j¡| _n0t|ƒt| jjƒkrÊtd	| jƒ‚| j || j¡ d
S )Nr…   r‰   rŠ   r   c                 S   s   g | ]}|  d d¡ ¡ ‘qS )z\|r…   )Úreplacer$   )Ú.0Úcellr   r   r   Ú
<listcomp>  s   ÿz'Parser.action_table.<locals>.<listcomp>z	(?<!\\)\|rK   zMalformed tableT)r$   rt   rF   rE   rC   r   rU   rŒ   r>   rˆ   ÚrerN   r   ÚTabler'   rR   Zheadingsr   Úadd_row)r)   r'   r‚   Úcellsr   r   r   rP   ò  s*    


ÿ
zParser.action_tablec                 C   sB   | j st| _tjt | _ | j | D ]}| |d ¡r"|  S q"dS )NrŠ   F)rG   rS   r   r   rH   rt   )r)   rT   r'   Úaliasr   r   r   rl     s    
zParser.match_keywordc                 C   st   |  d¡sJ ‚g }| ¡ D ]T}|  d¡rF| t |dd… | j¡¡ q|  d¡rV qpqtd||f | j| jƒ‚q|S )a‚  
        Parse a line with one or more tags:

          * A tag starts with the AT sign.
          * A tag consists of one word without whitespace chars.
          * Multiple tags are separated with whitespace chars
          * End-of-line comment is stripped.

        :param line:   Line with one/more tags to process.
        :raise ParserError: If syntax error is detected.
        rz   rK   Nrr   ztag: %s (line: %s))rt   rN   rc   r   ÚTagr'   r   r   )r)   r'   r"   Úwordr   r   r   r#     s    

ÿzParser.parse_tagsc              	   C   sÀ   dD ]¶}| j | D ]¦}| d¡r2d}|d d… }nd}| || ¡s\| ¡  | ¡ | ¡s\q|t|ƒd …  ¡ }|dv r’| jsŠtd| jƒ‚| j}n|| _t	 
| j| j|||¡}|    S qd S )N)ÚgivenÚwhenZthenÚandÚbutú<rM   r‰   ú )r›   rœ   zNo previous step)rG   rŒ   rt   rv   rR   r$   r?   r   r'   r   ZStepr   )r)   r'   Z	step_typeÚkwÚ
whitespacerU   r‚   r   r   r   r�   0  s*    
ÿÿzParser.parse_stepc                 C   sš   t |tjƒsJ ‚| jst| _|  ¡  || _t |ddd¡| _	d| _
| d¡D ]0}|  jd7  _| ¡ sr| j
dkrrqL|  |¡ qL| jrŽ|  d¡ | j	j}|S )zû
        Parse support for execute_steps() functionality that supports step with:
          * multiline text
          * table

        :param text:  Text that contains 0..* steps
        :return: List of parsed steps (as model.Step objects).
        r   rj   rM   r   rJ   rK   rL   )r   r   r   r   rS   rI   r   r   r]   rC   r>   rN   r'   r$   rO   rE   rP   r   )r)   r   r   r'   r   r   r   r   r!   K  s     	
zParser.parse_steps)NN)N)N)r7   r8   r9   Ú__doc__r&   rI   r   rV   rZ   r`   rb   rd   rf   rg   rh   ri   rq   rO   r|   r}   r   r€   rƒ   rˆ   r�   rP   rl   r#   r�   r!   r   r   r   r   r   X   s6   

	
#$(	r   )N)NN)NN)Ú
__future__r   r   r’   r/   r   Zbehaver   r   Zbehave.textutilr   r-   rS   r   r   r!   r#   Ú	Exceptionr   Úobjectr   r   r   r   r   Ú<module>   s   


