B
    `W                 @   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 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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G dd deZeejd < eejd!< eejd"< eejd#< eejd$< eejd%< eejd&< eejd'< eejd(< eejd)< eejd*< eejd+< eejd,< eejd-< G d.d/ d/e
ZdS )0z!Helpers to fill and submit forms.    N)BeautifulSoup)OrderedDict)utilsc               @   s   e Zd ZdS )NoValueN)__name__
__module____qualname__ r	   r	   U/home/kop/projects/devel/pgwui/test_venv/lib/python3.7/site-packages/webtest/forms.pyr      s   r   c               @   s*   e Zd ZdZd	ddZdd Zdd ZdS )
Uploada  
    A file to upload::

        >>> Upload('filename.txt', 'data', 'application/octet-stream')
        <Upload "filename.txt">
        >>> Upload('filename.txt', 'data')
        <Upload "filename.txt">
        >>> Upload("README.txt")
        <Upload "README.txt">

    :param filename: Name of the file to upload.
    :param content: Contents of the file.
    :param content_type: MIME type of the file.

    Nc             C   s   || _ || _|| _d S )N)filenamecontentcontent_type)selfr   r   r   r	   r	   r
   __init__"   s    zUpload.__init__c             c   s&   | j V  | jd k	r"| jV  | jV  d S )N)r   r   r   )r   r	   r	   r
   __iter__'   s    
zUpload.__iter__c             C   s
   d| j  S )Nz<Upload "%s">)r   )r   r	   r	   r
   __repr__/   s    zUpload.__repr__)NN)r   r   r   __doc__r   r   r   r	   r	   r	   r
   r      s   
r   c               @   sH   e Zd ZdZi ZdddZdd Zdd ZeeeZ	d	d
 Z
dd ZdS )FieldzBase class for all Field objects.

    .. attribute:: classes

        Dictionary of field types (select, radio, etc)

    .. attribute:: value

        Set/get value of the field.

    Nc             K   s.   || _ || _|| _|| _|| _|| _|| _d S )N)formtagnamepos_valueidattrs)r   r   r   r   r   valuer   r   r	   r	   r
   r   B   s    zField.__init__c             C   s   | j d krdS | j S d S )N )r   )r   r	   r	   r
   
value__getL   s    
zField.value__getc             C   s
   || _ d S )N)r   )r   r   r	   r	   r
   
value__setR   s    zField.value__setc             C   s
   || _ dS )zWLike setting a value, except forces it (even for, say, hidden
        fields).
        N)r   )r   r   r	   r	   r
   force_valueW   s    zField.force_valuec             C   s.   d| j j| jf }| jr&|d| j 7 }|d S )Nz<%s name="%s"z id="%s">)	__class__r   r   r   )r   r   r	   r	   r
   r   ]   s    zField.__repr__)NN)r   r   r   r   classesr   r   r   propertyr   r    r   r	   r	   r	   r
   r   3   s   
	
r   c                   sT   e Zd ZdZ fddZdd ZdddZd	d
 Zdd Zdd Z	e
e	eZ  ZS )Selectz/Field representing ``<select />`` form element.c                s.   t t| j|| g | _g | _d | _t| _d S )N)superr%   r   optionsoptionPositionsselectedIndexr   _forced_value)r   argsr   )r"   r	   r
   r   g   s
    zSelect.__init__c             C   s6   y|| _ t| _W n  tk
r0   d| _|| _Y nX dS )zWLike setting a value, except forces it (even for, say, hidden
        fields).
        N)r   r   r*   
ValueErrorr)   )r   r   r	   r	   r
   r    p   s    
zSelect.force_valueNc             C   s4   |d k	r|d k	rt d|d k	r*| |}|| _d S )Nz#Specify only one of value and text.)r,   _get_value_for_textr   )r   r   textr	   r	   r
   select{   s
    
zSelect.selectc             C   sV   x.t | jD ] \}\}}}|t|kr|S qW td|ddd | jD f d S )Nz'Option with text %r not found (from %s)z, c             S   s   g | ]\}}}t |qS r	   )repr).0octr	   r	   r
   
<listcomp>   s    z.Select._get_value_for_text.<locals>.<listcomp>)	enumerater'   r   	stringifyr,   join)r   r.   iZoption_valuecheckedZoption_textr	   r	   r
   r-      s    zSelect._get_value_for_textc             C   sj   | j tk	rt| _ xTt| jD ]$\}\}}}|t|kr|| _P qW td|ddd | jD f d S )NzOption %r not found (from %s)z, c             S   s   g | ]\}}}t |qS r	   )r0   )r1   r2   r3   r4   r	   r	   r
   r5      s    z%Select.value__set.<locals>.<listcomp>)	r*   r   r6   r'   r   r7   r)   r,   r8   )r   r   r9   optionr:   r.   r	   r	   r
   r      s    
zSelect.value__setc             C   s`   | j tk	r| j S | jd k	r*| j| j d S x0| jD ]\}}}|r2|S q2W | jr\| jd d S d S )Nr   )r*   r   r)   r'   )r   r;   r:   r.   r	   r	   r
   r      s    

zSelect.value__get)NN)r   r   r   r   r   r    r/   r-   r   r   r$   r   __classcell__r	   r	   )r"   r
   r%   d   s   	
		r%   c                   sT   e Zd ZdZ fddZdd ZdddZd	d
 Zdd Zdd Z	e
e	eZ  ZS )MultipleSelectz3Field representing ``<select multiple="multiple">``c                s(   t t| j|| g | _g | _t| _d S )N)r&   r=   r   r'   selectedIndicesr   _forced_values)r   r+   r   )r"   r	   r
   r      s    zMultipleSelect.__init__c             C   s   || _ g | _dS )zWLike setting a value, except forces it (even for, say, hidden
        fields).
        N)r?   r>   )r   valuesr	   r	   r
   r       s    zMultipleSelect.force_valueNc             C   s4   |d k	r|d k	rt d|d k	r*| |}|| _d S )Nz$Specify only one of value and texts.)r,   _get_value_for_textsr   )r   r   textsr	   r	   r
   select_multiple   s
    
zMultipleSelect.select_multiplec             C   s|   dd |D }g }x8t | jD ]*\}\}}}||kr|| || qW |rxtdd|ddd | jD f |S )Nc             S   s   g | ]}t |qS r	   )r   r7   )r1   r.   r	   r	   r
   r5      s    z7MultipleSelect._get_value_for_texts.<locals>.<listcomp>z Option(s) %r not found (from %s)z, c             S   s   g | ]\}}}t |qS r	   )r0   )r1   r2   r3   r4   r	   r	   r
   r5      s    )r6   r'   appendremover,   r8   )r   rB   Z	str_textsr   r9   r;   r:   r.   r	   r	   r
   rA      s    
z#MultipleSelect._get_value_for_textsc             C   s   |sd | _ n| j tk	rt| _ dd |D }g | _x:t| jD ],\}\}}}||kr<| j| || q<W |rtdd|ddd | jD f d S )Nc             S   s   g | ]}t |qS r	   )r   r7   )r1   r   r	   r	   r
   r5      s    z-MultipleSelect.value__set.<locals>.<listcomp>z Option(s) %r not found (from %s)z, c             S   s   g | ]\}}}t |qS r	   )r0   )r1   r2   r3   r4   r	   r	   r
   r5      s    )	r?   r   r>   r6   r'   rD   rE   r,   r8   )r   r@   Z
str_valuesr9   r;   r:   r.   r	   r	   r
   r      s    
zMultipleSelect.value__setc                sb    j tk	r j S  jr* fdd jD S g }x" jD ]\}}}|r6|| q6W |rZ|S d S d S )Nc                s   g | ]} j | d  qS )r   )r'   )r1   r9   )r   r	   r
   r5      s    z-MultipleSelect.value__get.<locals>.<listcomp>)r?   r   r>   r'   rD   )r   Zselected_valuesr;   r:   r.   r	   )r   r
   r      s    
zMultipleSelect.value__get)NN)r   r   r   r   r   r    rC   rA   r   r   r$   r   r<   r	   r	   )r"   r
   r=      s   
	r=   c               @   s$   e Zd ZdZdd ZeeejZdS )Radioz+Field representing ``<input type="radio">``c             C   sP   | j tk	r| j S | jd k	r*| j| j d S x | jD ]\}}}|r2|S q2W d S d S )Nr   )r*   r   r)   r'   )r   r;   r:   r.   r	   r	   r
   r      s    

zRadio.value__getN)	r   r   r   r   r   r$   r%   r   r   r	   r	   r	   r
   rF      s   rF   c                   sT   e Zd ZdZ fddZdd Zdd ZeeeZdd	 Z	d
d Z
ee	e
Z  ZS )Checkboxz~Field representing ``<input type="checkbox">``

    .. attribute:: checked

        Returns True if checkbox is checked.

    c                s    t t| j|| d|k| _d S )Nr:   )r&   rG   r   _checked)r   r+   r   )r"   r	   r
   r     s    zCheckbox.__init__c             C   s   |  | _ d S )N)rH   )r   r   r	   r	   r
   r     s    zCheckbox.value__setc             C   s$   | j r| jd krdS | jS nd S d S )Non)rH   r   )r   r	   r	   r
   r     s
    
zCheckbox.value__getc             C   s
   t | jS )N)boolrH   )r   r	   r	   r
   checked__get  s    zCheckbox.checked__getc             C   s   |  | _ d S )N)rH   )r   r   r	   r	   r
   checked__set"  s    zCheckbox.checked__set)r   r   r   r   r   r   r   r$   r   rK   rL   r:   r<   r	   r	   )r"   r
   rG     s   	
rG   c               @   s   e Zd ZdZdS )Textz*Field representing ``<input type="text">``N)r   r   r   r   r	   r	   r	   r
   rM   (  s   rM   c               @   s   e Zd ZdZdS )Emailz+Field representing ``<input type="email">``N)r   r   r   r   r	   r	   r	   r
   rN   ,  s   rN   c               @   s$   e Zd ZdZdd ZeeejZdS )Filez*Field representing ``<input type="file">``c             C   s   | j d krdS | j S d S )Nr   )r   )r   r	   r	   r
   r   4  s    
zFile.value__getN)	r   r   r   r   r   r$   r   r   r   r	   r	   r	   r
   rO   0  s   rO   c               @   s   e Zd ZdZdS )Textareaz!Field representing ``<textarea>``N)r   r   r   r   r	   r	   r	   r
   rP   =  s   rP   c               @   s   e Zd ZdZdS )Hiddenz,Field representing ``<input type="hidden">``N)r   r   r   r   r	   r	   r	   r
   rQ   A  s   rQ   c               @   s2   e Zd ZdZdd Zdd ZeeeZdd ZdS )	Submitz=Field representing ``<input type="submit">`` and ``<button>``c             C   s   d S )Nr	   )r   r	   r	   r
   r   H  s    zSubmit.value__getc             C   s   t d| j| jf d S )Nz-You cannot set the value of the <%s> field %r)AttributeErrorr   r   )r   r   r	   r	   r
   r   K  s    zSubmit.value__setc             C   s
   | j pdS )Nr   )r   )r   r	   r	   r
   value_if_submittedR  s    zSubmit.value_if_submittedN)	r   r   r   r   r   r   r$   r   rT   r	   r	   r	   r
   rR   E  s
   
rR   submitbuttonimagemultiple_selectr/   hiddenfiler.   searchemailpasswordZcheckboxtextarearadioc               @   s   e Zd ZdZedejZedejZe	Z
d ddZdd Zd	d
 Zdd Zdd Zd!ddZdejfddZd"ddZd#ddZd$ddZdd Zd%ddZdd ZdS )&Forma1  This object represents a form that has been found in a page.

    :param response: `webob.response.TestResponse` instance
    :param text: Unparsed html of the form

    .. attribute:: text

        the full HTML of the form.

    .. attribute:: action

        the relative URI of the action.

    .. attribute:: method

        the HTTP method (e.g., ``'GET'``).

    .. attribute:: id

        the id, or None if not given.

    .. attribute:: enctype

        encoding of the form submission

    .. attribute:: fields

        a dictionary of fields, each value is a list of fields by
        that name.  ``<input type="radio">`` and ``<select>`` are
        both represented as single fields with multiple options.

    .. attribute:: field_order

        Ordered list of field names as found in the html.

    z<(/?)([a-z0-9_\-]*)([^>]*?)>z<<label\s+(?:[^>]*)for=(?:"|')([a-z0-9_\-]+)(?:"|')(?:[^>]*)>html.parserc             C   sl   || _ || _t| j|| _| dd j}|dd| _|dd| _|d| _|dd	| _	| 
  d S )
Nr   r   actionr   methodGETr   enctypez!application/x-www-form-urlencoded)responser.   r   htmlr   getrb   rc   r   re   _parse_fields)r   rf   r.   Zparser_featuresr   r	   r	   r
   r     s    zForm.__init__c             C   s  t  }g }d}xxt| j|D ]b\}}t|j}|j}d }d|krR|d}|dkr|j	drv|jdd  }	n"|j	dr|jdd  }	n|j}	|	|d< |
d	d
 }
|dkrd}
|
dkrd|krd}
|dkrd}
| jj
|
| j}tjd d dkrtdd | D }d}x|D ]}||kr"||= q"W |dkr|
dkr|
|}|s|| |||f|}||g | |||f n |d }t|| jjd st|j|
dd|kd f |j| d|kr"t|jd |_q"n|
dkrd|kr|d= || |||f|}||g | |||f |dkr"x8|dD ],}|j|j
d|jd|jk|jf qVW q"W || _|| _d S )N)inputr/   r^   rV   r   r^   z
   
   r   typer.   r/   multiplerX   rV   rU   )rk      c             s   s.   | ]&\}}t |tr|d n||fV  qdS )zutf-8N)
isinstanceunicodeencode)r1   kvr	   r	   r
   	<genexpr>  s   z%Form._parse_fields.<locals>.<genexpr>)r   r   r   rj   r_   r   r:   rZ   r;   selected)r   r6   rg   ZfindAlldictr   r   popr.   
startswithrh   lower
FieldClassr#   sysversion_infoitems
setdefaultrD   rq   AssertionErrorr'   r(   lenr)   field_orderfields)r   r   r   tagsr   noder   r   r   r.   Ztag_typer|   Zreserved_attributesattrfieldr;   r	   r	   r
   ri     s~    









zForm._parse_fieldsc          	   C   s   | j |}|dk	s6td|dtt| j  f tdd |D }|rt|t	rt
dd |D }xL|D ]}|j|k|_qnW n2t|dkstd|dtt|f ||d	 _dS )
ai  Set the value of the named field. If there is 0 or multiple fields
        by that name, it is an error.

        Multiple checkboxes of the same name are special-cased; a list may be
        assigned to them to check the checkboxes whose value is present in the
        list (and uncheck all others).

        Setting the value of a ``<select>`` selects the given option (and
        confirms it is an option). Setting radio fields does the same.
        Checkboxes get boolean values. You cannot set hidden fields or buttons.

        Use ``.set()`` if there is any ambiguity and you must provide an index.
        Nz*No field by the name %r found (fields: %s)z, c             s   s   | ]}t |tV  qd S )N)rq   rG   )r1   fr	   r	   r
   rv     s    z#Form.__setitem__.<locals>.<genexpr>c             s   s   | ]}t |V  qd S )N)r   r7   )r1   ru   r	   r	   r
   rv     s    rm   zMultiple fields match %r: %sr   )r   rh   r   r8   mapr0   keysallrq   listsetr   r:   r   r   )r   r   r   r   Zall_checkboxesr@   r   r	   r	   r
   __setitem__  s    

zForm.__setitem__c             C   sP   | j |}|dk	s td| t|dksHtd|dtt|f |d S )z3Get the named field object (ambiguity is an error).NzNo field by the name %r foundrm   zMultiple fields match %r: %sz, r   )r   rh   r   r   r8   r   r0   )r   r   r   r	   r	   r
   __getitem__  s    

zForm.__getitem__c             C   sp   | j | j}x\| j D ]N\}}xD|D ]<}t|ttfs(|jsNt	d| q(|j|kr(t	d| q(W qW dS )z}
        Check that the html is valid:

        - each field must have an id
        - each field must have a label

        z%r as no id attributez%r as no associated labelN)
	_label_refindallr.   r   r   rq   rR   rQ   r   rS   )r   labelsr   r   r   r	   r	   r
   lint&  s    

z	Form.lintNc             C   sD   |dkr|| |< n.| j |}|dk	s2td| || }||_dS )z4Set the given name, using ``index`` to disambiguate.NzNo fields found matching %r)r   rh   r   r   )r   r   r   indexr   r   r	   r	   r
   r   8  s    


zForm.setc             C   sF   | j |}|dkr.|tjkr*td| |S |dkr>| | S || S )z
        Get the named/indexed field object, or ``default`` if no field is
        found. Throws an AssertionError if no field is found and no ``default``
        was given.
        Nz2No fields found matching %r (and no default given))r   rh   r   	NoDefaultr   )r   r   r   defaultr   r	   r	   r
   rh   C  s    
zForm.getc             C   s,   | j ||d}t|tst||| dS )zyLike ``.set()``, except also confirms the target is a ``<select>``
        and allows selecting options by text.
        )r   N)rh   rq   r%   r   r/   )r   r   r   r.   r   r   r	   r	   r
   r/   T  s    zForm.selectc             C   s,   | j ||d}t|tst||| dS )zLike ``.set()``, except also confirms the target is a
        ``<select multiple>`` and allows selecting options by text.
        )r   N)rh   rq   r=   r   rC   )r   r   r   rB   r   r   r	   r	   r
   rC   ]  s    zForm.select_multiplec             K   sl   | j |||d}| j dkr,|d| j |di }|dt| jjj | jj	| j
f| j|d|S )aW  Submits the form.  If ``name`` is given, then also select that
        button (using ``index`` or ``value`` to disambiguate)``.

        Any extra keyword arguments are passed to the
        :meth:`webtest.TestResponse.get` or
        :meth:`webtest.TestResponse.post` method.

        Returns a :class:`webtest.TestResponse` object.

        )r   submit_valuerd   r   extra_environZHTTP_REFERER)rc   params)submit_fieldsrc   upperr   re   strrf   requesturlgotorb   )r   r   r   r   r+   r   r   r	   r	   r
   rU   f  s    zForm.submitc             C   sT   g }xJ| j  D ]<\}}x2|D ]*}t|tr|jr||gt|j  qW qW |S )zReturn a list of file field tuples of the form::

            (field name, file name)

        or::

            (field name, file name, file contents).

        )r   r   rq   rO   r   rD   r   )r   Zuploadsr   r   r   r	   r	   r
   upload_fieldsy  s    

zForm.upload_fieldsc       
      C   s  g }|}|dk	r |dk	r t d|dkr4|dkr4d}d}x*| jD ]\}}|dkrVqB|dk	r||kr|dk	r||kr||j|| f |dk	r| |kr||j|| f |d7 }qB|j}|dkrqBt|tr||j||f qBt|tr |j	dk	r ||j
|j	 ||f qBt|trPx4|D ]}	||j||	f q2W qB||j||f qBW |jtdd dd |D S )zReturn a list of ``[(name, value), ...]`` for the current state of
        the form.

        :param name: Same as for :meth:`submit`
        :param index: Same as for :meth:`submit`

        Nz*Can't specify both submit_value and index.r   rm   )keyc             S   s   g | ]}|d d qS )rm   Nr	   )r1   xr	   r	   r
   r5     s    z&Form.submit_fields.<locals>.<listcomp>)r,   r   rD   r   rT   r   rq   rO   rF   r)   r(   r   sortoperator
itemgetter)
r   r   r   r   rU   Zsubmit_nameZcurrent_indexr   r   itemr	   r	   r
   r     sB    


zForm.submit_fieldsc             C   s$   d}| j r|dt| j  7 }|d S )Nz<Formz id=%rz />)r   r   )r   r   r	   r	   r
   r     s    zForm.__repr__)ra   )N)NNN)NNN)NNN)NNN)r   r   r   r   recompileIZ_tag_rer   r   r|   r   ri   r   r   r   r   r   r   rh   r/   rC   rU   r   r   r   r	   r	   r	   r
   r`   t  s&   $
N


	
	

1r`   )r   r   r   r}   Zbs4r   collectionsr   Zwebtestr   objectr   r   r   r%   r=   rF   rG   rM   rN   rO   rP   rQ   rR   r#   r`   r	   r	   r	   r
   <module>   sD   "1EI$













