U
    Pf!%                     @   sN   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 G dd dZ	dS )	    )List)NoSuchElementException)UnexpectedTagNameException)By)
WebElementc                   @   s  e Zd ZeddddZeee dddZeee ddd	Zeedd
dZ	e
ddddZeddddZe
ddddZddddZe
ddddZeddddZe
ddddZddddZdddd Ze
e
dd!d"Ze
e
dd#d$ZdS )%SelectN)
webelementreturnc                 C   sB   |j  dkrtd|j  || _| jd}|o:|dk| _dS )a|  Constructor. A check is made that the given element is, indeed, a
        SELECT tag. If it is not, then an UnexpectedTagNameException is thrown.

        :Args:
         - webelement - SELECT element to wrap

        Example:
            from selenium.webdriver.support.ui import Select 

            Select(driver.find_element(By.TAG_NAME, "select")).select_by_index(2)
        selectz/Select only works on <select> elements, not on multiplefalseN)Ztag_namelowerr   _elZget_dom_attributeis_multiple)selfr   Zmulti r   E/tmp/pip-unpacked-wheel-ds5t_0qj/selenium/webdriver/support/select.py__init__   s
    zSelect.__init__)r	   c                 C   s   | j tjdS )z;Returns a list of all options belonging to this select tag.option)r   find_elementsr   ZTAG_NAMEr   r   r   r   options,   s    zSelect.optionsc                 C   s   dd | j D S )zLReturns a list of all selected options belonging to this select
        tag.c                 S   s   g | ]}|  r|qS r   )is_selected).0optr   r   r   
<listcomp>5   s      z/Select.all_selected_options.<locals>.<listcomp>)r   r   r   r   r   all_selected_options1   s    zSelect.all_selected_optionsc                 C   s(   | j D ]}| r|  S qtddS )zjThe first selected option in this select tag (or the currently
        selected option in a normal select)zNo options are selectedN)r   r   r   r   r   r   r   r   first_selected_option7   s    

zSelect.first_selected_option)valuer	   c                 C   s`   d|  | d}| jtj|}d}|D ]}| | | jsD dS d}q*|s\td| dS )aL  Select all options that have a value matching the argument. That is,
        when given "foo" this would select an option like:

        <option value="foo">Bar</option>

        :Args:
         - value - The value to match against

        throws NoSuchElementException If there is no option with specified value in SELECT
        zoption[value =]FNTz!Cannot locate option with value: )_escape_stringr   r   r   CSS_SELECTOR_set_selectedr   r   )r   r   cssoptsmatchedr   r   r   r   select_by_value@   s    
zSelect.select_by_value)indexr	   c                 C   sD   t |}| jD ]"}|d|kr| |  dS qtd| dS )a:  Select the option at the given index. This is done by examining the
        "index" attribute of an element, and not merely by counting.

        :Args:
         - index - The option at this index will be selected

        throws NoSuchElementException If there is no option with specified index in SELECT
        r(   N$Could not locate element with index )strr   get_attributer#   r   )r   r(   matchr   r   r   r   select_by_indexV   s    	

zSelect.select_by_index)textr	   c           	      C   s   d|  | d}| jtj|}d}|D ]}| | | jsD dS d}q*t|dkrd|kr| |}|dkrx| j	}n"d	|  | d
}| jtj|}|D ](}||j
kr| | | js dS d}q|std| dS )aS  Select all options that display text matching the argument. That is,
        when given "Bar" this would select an option like:

         <option value="foo">Bar</option>

        :Args:
         - text - The visible text to match against

         throws NoSuchElementException If there is no option with specified text in SELECT
        .//option[normalize-space(.) = r    FNTr     z.//option[contains(.,z)],Could not locate element with visible text: )r!   r   r   r   XPATHr#   r   len_get_longest_tokenr   r.   r   )	r   r.   xpathr%   r&   r   Zsub_string_without_space
candidates	candidater   r   r   select_by_visible_textf   s,    



zSelect.select_by_visible_textc                 C   s(   | j std| jD ]}| | qdS )zClear all selected entries.

        This is only valid when the SELECT supports multiple selections.
        throws NotImplementedError If the SELECT does not support
        multiple selections
        z3You may only deselect all options of a multi-selectN)r   NotImplementedErrorr   _unset_selectedr   r   r   r   deselect_all   s    
zSelect.deselect_allc                 C   sb   | j stdd}d| | d}| jtj|}|D ]}| | d}q8|s^td| dS )aR  Deselect all options that have a value matching the argument. That
        is, when given "foo" this would deselect an option like:

         <option value="foo">Bar</option>

        :Args:
         - value - The value to match against

         throws NoSuchElementException If there is no option with specified value in SELECT
        /You may only deselect options of a multi-selectFzoption[value = r    Tz%Could not locate element with value: N)	r   r:   r!   r   r   r   r"   r;   r   )r   r   r&   r$   r%   r   r   r   r   deselect_by_value   s    
zSelect.deselect_by_valuec                 C   sN   | j std| jD ]&}|dt|kr| |  dS qtd| dS )a?  Deselect the option at the given index. This is done by examining
        the "index" attribute of an element, and not merely by counting.

        :Args:
         - index - The option at this index will be deselected

         throws NoSuchElementException If there is no option with specified index in SELECT
        r=   r(   Nr)   )r   r:   r   r+   r*   r;   r   )r   r(   r   r   r   r   deselect_by_index   s    	

zSelect.deselect_by_indexc                 C   sb   | j stdd}d| | d}| jtj|}|D ]}| | d}q8|s^td| dS )zDeselect all options that display text matching the argument. That
        is, when given "Bar" this would deselect an option like:

        <option value="foo">Bar</option>

        :Args:
         - text - The visible text to match against
        r=   Fr/   r    Tr2   N)	r   r:   r!   r   r   r   r3   r;   r   )r   r.   r&   r6   r%   r   r   r   r   deselect_by_visible_text   s    	
zSelect.deselect_by_visible_textc                 C   s$   |  s | std|  d S )Nz$You may not select a disabled option)r   
is_enabledr:   clickr   r   r   r   r   r#      s    zSelect._set_selectedc                 C   s   |  r|  d S )N)r   rB   rC   r   r   r   r;      s    zSelect._unset_selectedc                 C   s   d|krtd|krt| d}dg}|D ] }|d| d |d q$|dd }|drf|d d|d	 S d|krd| dS d| dS )
N"'zconcat(z, '"', r   z, '"'r1   ))splitappendendswithjoin)r   r   Z
substringsresultZ	substringr   r   r   r!      s    


zSelect._escape_stringc                 C   s0   | d}d}|D ]}t|t|kr|}q|S )Nr0   r1   )rH   r4   )r   r   itemslongestitemr   r   r   r5      s    
zSelect._get_longest_token)__name__
__module____qualname__r   r   propertyr   r   r   r   r*   r'   intr-   r9   r<   r>   r?   r@   r#   r;   r!   r5   r   r   r   r   r      s$   %r   N)
typingr   Zselenium.common.exceptionsr   r   Zselenium.webdriver.common.byr   Z$selenium.webdriver.remote.webelementr   r   r   r   r   r   <module>   s
   