a
    4ñ»jÜ7  ã                   @   sF  d Z ddlmZmZmZ ddlZddlZddlZddlZddl	Z	ddl
mZ ddlmZmZ ddlmZmZ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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G dd„ deƒZeeeedœZ ea!dd„ Z"d d!„ Z#d"d#„ Z$dS )$z�
This module provides the step matchers functionality that matches a
step definition (as text) with step-functions that implement this step.
é    )Úabsolute_importÚprint_functionÚwith_statementN)Úcfparse)ÚChainedExceptionUtilÚExceptionUtil)ÚArgumentÚFileLocationÚ
Replayablec                   @   s   e Zd ZdZddd„ZdS )ÚStepParseErrorz¯Exception class, used when step matching fails before a step is run.
    This is normally the case when an error occurs during the type conversion
    of step parameters.
    Nc                 C   sX   |s|rt  |¡}|r8t jr8tj|ddd�}|d| 7 }t | |¡ |rTt | |¡ d S )NTzCAUSED-BY: )Zuse_tracebackÚprefixÚ
)	ÚsixÚ	text_typeÚPY2r   ÚdescribeÚ
ValueErrorÚ__init__r   Z	set_cause)ÚselfÚtextÚ	exc_causeZ
cause_text© r   ú5E:\soccer\ml_env\Lib\site-packages\behave/matchers.pyr      s    

þzStepParseError.__init__)NN©Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   r      s   r   c                       sR   e Zd ZdZdZd‡ fdd„	Zdd„ Zdd	„ Zd
d„ Zdd„ Z	e
dd„ ƒZ‡  ZS )ÚMatchaW  An parameter-matched *feature file* step name extracted using
    step decorator `parameters`_.

    .. attribute:: func

       The step function that this match will be applied to.

    .. attribute:: arguments

       A list of :class:`~behave.model_core.Argument` instances containing the
       matched parameters from the step name.
    ÚmatchNc                    s4   t t| ƒ ¡  || _|| _d | _|r0|  |¡| _d S ©N)Úsuperr   r   ÚfuncÚ	argumentsÚlocationÚmake_location)r   r"   r#   ©Ú	__class__r   r   r   ?   s    zMatch.__init__c                 C   s"   | j r| j j}nd}d|| jf S )Nz<no function>z<Match %s, %s>)r"   r   r$   )r   Ú	func_namer   r   r   Ú__repr__G   s    
zMatch.__repr__c                 C   s&   t |tƒsdS | j| jf|j|jfkS )NF)Ú
isinstancer   r"   r$   )r   Úotherr   r   r   Ú__eq__N   s    
zMatch.__eq__c                 C   s   t   | ¡}||_|S r    )Úcopyr#   )r   r#   r   r   r   r   Úwith_argumentsS   s    
zMatch.with_argumentsc                 C   s|   g }i }| j D ](}|jd ur*|j||j< q| |j¡ q| ¡ �( | j|g|¢R i |¤Ž W d   ƒ n1 sn0    Y  d S r    )r#   ÚnameÚvalueÚappendZuse_with_user_moder"   )r   ÚcontextÚargsÚkwargsÚargr   r   r   ÚrunX   s    


z	Match.runc                 C   s
   t  | ¡S )a  Extracts the location information from the step function and
        builds a FileLocation object with (filename, line_number) info.

        :param step_function: Function whose location should be determined.
        :return: FileLocation object for step function.
        )r	   Zfor_function)Zstep_functionr   r   r   r%   d   s    zMatch.make_location)N)r   r   r   r   Útyper   r)   r,   r.   r6   Ústaticmethodr%   Ú__classcell__r   r   r&   r   r   0   s   r   c                   @   s   e Zd ZdZdd„ ZdS )ÚNoMatchzXUsed for an "undefined step" when it can not be matched with a
    step definition.
    c                 C   s$   t j| d d� d | _g | _d | _d S ©N)r"   )r   r   r"   r#   r$   ©r   r   r   r   r   t   s    zNoMatch.__init__Nr   r   r   r   r   r:   o   s   r:   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚMatchWithErrorzvMatch class when error occur during step-matching

    REASON:
      * Type conversion error occured.
      * ...
    c                 C   s,   t  |¡st  |¡ tj| |d� || _d S r;   )r   Zhas_tracebackZset_tracebackr   r   Ústored_error)r   r"   Úerrorr   r   r   r   ‚   s    

zMatchWithError.__init__c                 C   s   t | jd�‚dS )z?Raises stored error from step matching phase (type conversion).)r   N)r   r>   )r   r2   r   r   r   r6   ˆ   s    zMatchWithError.runN)r   r   r   r   r   r6   r   r   r   r   r=   {   s   r=   c                   @   sd   e Zd ZdZdZddd„Zedd„ ƒZedd	„ ƒZed
d„ ƒZ	ddd„Z
dd„ Zdd„ Zdd„ ZdS )ÚMatcherzÑPull parameters out of step names.

    .. attribute:: pattern

       The match pattern attached to the step function.

    .. attribute:: func

       The step function the pattern is being attached to.
    z	@%s('%s')Nc                 C   s   || _ || _|| _d | _d S r    )r"   ÚpatternÚ	step_typeÚ	_location©r   r"   rA   rB   r   r   r   r   Ÿ   s    zMatcher.__init__c                 C   s   t  dt¡ | jS )Nz!deprecated: Use 'pattern' instead)ÚwarningsÚwarnÚDeprecationWarningrA   r<   r   r   r   Ústring¦   s    zMatcher.stringc                 C   s   | j d u rt | j¡| _ | j S r    )rC   r   r%   r"   r<   r   r   r   r$   «   s    
zMatcher.locationc                 C   s   | j S )z&Return the used textual regex pattern.)rA   r<   r   r   r   Úregex_pattern±   s    zMatcher.regex_patternc                 C   s"   | j pd}|s| j}||| jf S )zÀProvide a textual description of the step function/matcher object.

        :param schema:  Text schema to use.
        :return: Textual description of this step definition (matcher).
        Ústep)rB   ÚschemarA   )r   rK   rB   r   r   r   r   ¸   s    
zMatcher.describec                 C   s   t ‚dS )a<  Match me against the "step" name supplied.

        Return None, if I don't match otherwise return a list of matches as
        :class:`~behave.model_core.Argument` instances.

        The return value from this function will be converted into a
        :class:`~behave.matchers.Match` instance by *behave*.
        N)ÚNotImplementedError)r   rJ   r   r   r   Úcheck_matchÄ   s    	zMatcher.check_matchc              
   C   sX   z|   |¡}W n0 ty> } zt| j|ƒW  Y d }~S d }~0 0 |d u rLd S t| j|ƒS r    )rM   Ú	Exceptionr=   r"   r   )r   rJ   ÚresultÚer   r   r   r   Ï   s    "zMatcher.matchc                 C   s   d| j j| jf S )Nz<%s: %r>)r'   r   rA   r<   r   r   r   r)   Ú   s    zMatcher.__repr__)N)N)r   r   r   r   rK   r   ÚpropertyrH   r$   rI   r   rM   r   r)   r   r   r   r   r@   ’   s   





r@   c                       s@   e Zd ZdZi ZejZd	‡ fdd„	Ze	dd„ ƒZ
dd„ Z‡  ZS )
ÚParseMatcherz~Uses :class:`~parse.Parser` class to be able to use simpler
    parse expressions compared to normal regular expressions.
    Nc                    s(   t t| ƒ |||¡ |  || j¡| _d S r    )r!   rR   r   Úparser_classÚcustom_typesÚparserrD   r&   r   r   r   å   s    zParseMatcher.__init__c                 C   s   | j jS r    )rU   Z_expressionr<   r   r   r   rI   é   s    zParseMatcher.regex_patternc           	   	   C   sª   | j  |¡}|sd S g }t|jƒD ]2\}}|j| \}}| t|||||… |ƒ¡ q"|j ¡ D ]4\}}|j| \}}| t|||||… ||ƒ¡ q`|j	dd„ d� |S )Nc                 S   s   | j S r    )Ústart)Úxr   r   r   Ú<lambda>ü   ó    z*ParseMatcher.check_match.<locals>.<lambda>)Úkey)
rU   ÚparseÚ	enumerateÚfixedÚspansr1   r   ÚnamedÚitemsÚsort)	r   rJ   rO   r3   Úindexr0   rV   Úendr/   r   r   r   rM   î   s     zParseMatcher.check_match)N)r   r   r   r   rT   r[   ÚParserrS   r   rQ   rI   rM   r9   r   r   r&   r   rR   Þ   s   
rR   c                   @   s   e Zd ZdZejZdS )ÚCFParseMatcherz²Uses :class:`~parse_type.cfparse.Parser` instead of "parse.Parser".
    Provides support for automatic generation of type variants
    for fields with CardinalityField part.
    N)r   r   r   r   r   rd   rS   r   r   r   r   re      s   re   c                  K   s   t j | ¡ dS )až  Registers a custom type that will be available to "parse"
    for type conversion during step matching.

    Converters should be supplied as ``name=callable`` arguments (or as dict).

    A type converter should follow :pypi:`parse` module rules.
    In general, a type converter is a function that converts text (as string)
    into a value-type (type converted value).

    EXAMPLE:

    .. code-block:: python

        from behave import register_type, given
        import parse

        # -- TYPE CONVERTER: For a simple, positive integer number.
        @parse.with_pattern(r"\d+")
        def parse_number(text):
            return int(text)

        # -- REGISTER TYPE-CONVERTER: With behave
        register_type(Number=parse_number)

        # -- STEP DEFINITIONS: Use type converter.
        @given('{amount:Number} vehicles')
        def step_impl(context, amount):
            assert isinstance(amount, int)
    N)rR   rT   Úupdate)Úkwr   r   r   Úregister_type  s     rh   c                       s&   e Zd Zd‡ fdd„	Zdd„ Z‡  ZS )ÚRegexMatcherNc                    s&   t t| ƒ |||¡ t | j¡| _d S r    )r!   ri   r   ÚreÚcompilerA   ÚregexrD   r&   r   r   r   ,  s    zRegexMatcher.__init__c              	   C   s‚   | j  |¡}|sd S tdd„ | j j ¡ D ƒƒ}g }t| ¡ ƒD ]>\}}|d7 }| |d ¡}| t	| 
|¡| |¡|||ƒ¡ q>|S )Nc                 s   s   | ]\}}||fV  qd S r    r   )Ú.0rW   Úyr   r   r   Ú	<genexpr>5  rY   z+RegexMatcher.check_match.<locals>.<genexpr>é   )rl   r   ÚdictÚ
groupindexr`   r\   ÚgroupsÚgetr1   r   rV   rc   )r   rJ   Úmrr   r3   rb   Úgroupr/   r   r   r   rM   0  s    ÿzRegexMatcher.check_match)N)r   r   r   r   rM   r9   r   r   r&   r   ri   +  s   ri   c                       s"   e Zd ZdZd‡ fdd„	Z‡  ZS )ÚSimplifiedRegexMatchera  Simplified regular expression step-matcher that automatically adds
    start-of-line/end-of-line matcher symbols to string:

    .. code-block:: python

        @when(u'a step passes')     # re.pattern = "^a step passes$"
        def step_impl(context): pass
    Nc                    sF   |  d¡s| d¡r J d| ƒ‚d| }tt| ƒ |||¡ || _d S )Nú^ú$z5Regular expression should not use begin/end-markers: z^%s$)Ú
startswithÚendswithr!   rw   r   rA   )r   r"   rA   rB   Ú
expressionr&   r   r   r   I  s    ÿzSimplifiedRegexMatcher.__init__)N)r   r   r   r   r   r9   r   r   r&   r   rw   ?  s   	rw   c                   @   s   e Zd ZdZdS )ÚCucumberRegexMatchera  Compatible to (old) Cucumber style regular expressions.
    Text must contain start-of-line/end-of-line matcher symbols to string:

    .. code-block:: python

        @when(u'^a step passes$')   # re.pattern = "^a step passes$"
        def step_impl(context): pass
    N)r   r   r   r   r   r   r   r   r}   Q  s   r}   )r[   r   rj   Zre0c                 C   s   t |  adS )a¥  Change the parameter matcher used in parsing step text.

    The change is immediate and may be performed between step definitions in
    your step implementation modules - allowing adjacent steps to use different
    matchers if necessary.

    There are several parsers available in *behave* (by default):

    **parse** (the default, based on: :pypi:`parse`)
        Provides a simple parser that replaces regular expressions for
        step parameters with a readable syntax like ``{param:Type}``.
        The syntax is inspired by the Python builtin ``string.format()``
        function.
        Step parameters must use the named fields syntax of :pypi:`parse`
        in step definitions. The named fields are extracted,
        optionally type converted and then used as step function arguments.

        Supports type conversions by using type converters
        (see :func:`~behave.register_type()`).

    **cfparse** (extends: :pypi:`parse`, requires: :pypi:`parse_type`)
        Provides an extended parser with "Cardinality Field" (CF) support.
        Automatically creates missing type converters for related cardinality
        as long as a type converter for cardinality=1 is provided.
        Supports parse expressions like:

        * ``{values:Type+}`` (cardinality=1..N, many)
        * ``{values:Type*}`` (cardinality=0..N, many0)
        * ``{value:Type?}``  (cardinality=0..1, optional)

        Supports type conversions (as above).

    **re**
        This uses full regular expressions to parse the clause text. You will
        need to use named groups "(?P<name>...)" to define the variables pulled
        from the text and passed to your ``step()`` function.

        Type conversion is **not supported**.
        A step function writer may implement type conversion
        inside the step function (implementation).

    You may `define your own matcher`_.

    .. _`define your own matcher`: api.html#step-parameters
    N)Úmatcher_mappingÚcurrent_matcher©r/   r   r   r   Úuse_step_matcherk  s    /r�   c                 C   s   t jdtdd� t| ƒ dS )z=
    DEPRECATED, use :func:`use_step_matcher()` instead.
    z,deprecated: Use 'use_step_matcher()' insteadé   )Ú
stacklevelN)rE   rF   rG   r�   r€   r   r   r   Ústep_matcherœ  s    ÿr„   c                 C   s
   t | |ƒS r    )r   )r"   rA   r   r   r   Úget_matcher¥  s    r…   )%r   Ú
__future__r   r   r   r-   rj   rE   r[   r   Z
parse_typer   Zbehave._typesr   r   Zbehave.model_corer   r	   r
   r   r   r   r:   r=   Úobjectr@   rR   re   rh   ri   rw   r}   r~   r   r�   r„   r…   r   r   r   r   Ú<module>   s:   ?L"#õ1	