o
    ;Diځ                     @   s  d dl mZmZmZ d dlZd dlZd dlmZmZ d dl	m
Z
mZ d dlmZ d dlmZmZmZ d dlmZ d dlmZ d d	lmZmZmZmZmZmZ d
d Zdd Z		d5ddZee_G dd deZ 			d6ddZ!e!e_!			d6ddZ"e"e_"			d6ddZ#e#e_#		d7ddZ$dd Z%e%e_%G dd deZ&d d! Z'		d8d"d#Z(e(e_(G d$d% d%eZ)d&d' Z*			d6d(d)Z+e+e_+G d*d+ d+eZ,		d9d,d-Z-		d:d/d0Z.G d1d2 d2eZ/e.e_.G d3d4 d4eZ0dS );    )absolute_importdivisionprint_functionN)
Comparablecomparable_itemgetter)next	text_type)ArgumentError)cutcutoutstack)distinct)sort)Table	asindicesdataheader	rowgetter
rowgroupbyc                    sj   t | }ttt|}t |}ttt|  fdd|D }t|dks)J dt|dkr3|d }|S )Nc                    s   g | ]}| v r|qS  r   .0frfldsr   M/var/www/Datamplify/venv/lib/python3.10/site-packages/petl/transform/joins.py
<listcomp>       znatural_key.<locals>.<listcomp>r   zno fields in common   )r   listmapstrlen)leftrightlhdrlfldsrhdrkeyr   r   r   natural_key   s   r)   c                 C   s   ||  u r|  u rd u rn nt | | }}||fS |d ur4||  u r*d u r4n n| }}||fS |d u rE|d urE|d urE	 ||fS td)Nzbad key arguments: either specify key, or specify both lkey and rkey, or provide no key/lkey/rkey arguments at all (natural join))r)   r	   )r#   r$   r(   lkeyrkeyr   r   r   keys_from_args   s   " 	r,   FTc                 C   s0   t | ||||\}}t| ||||||||	|
d
S )a>  
    Perform an equi-join on the given tables. E.g.::

        >>> import petl as etl
        >>> table1 = [['id', 'colour'],
        ...           [1, 'blue'],
        ...           [2, 'red'],
        ...           [3, 'purple']]
        >>> table2 = [['id', 'shape'],
        ...           [1, 'circle'],
        ...           [3, 'square'],
        ...           [4, 'ellipse']]
        >>> table3 = etl.join(table1, table2, key='id')
        >>> table3
        +----+----------+----------+
        | id | colour   | shape    |
        +====+==========+==========+
        |  1 | 'blue'   | 'circle' |
        +----+----------+----------+
        |  3 | 'purple' | 'square' |
        +----+----------+----------+

        >>> # if no key is given, a natural join is tried
        ... table4 = etl.join(table1, table2)
        >>> table4
        +----+----------+----------+
        | id | colour   | shape    |
        +====+==========+==========+
        |  1 | 'blue'   | 'circle' |
        +----+----------+----------+
        |  3 | 'purple' | 'square' |
        +----+----------+----------+

        >>> # note behaviour if the key is not unique in either or both tables
        ... table5 = [['id', 'colour'],
        ...           [1, 'blue'],
        ...           [1, 'red'],
        ...           [2, 'purple']]
        >>> table6 = [['id', 'shape'],
        ...           [1, 'circle'],
        ...           [1, 'square'],
        ...           [2, 'ellipse']]
        >>> table7 = etl.join(table5, table6, key='id')
        >>> table7
        +----+----------+-----------+
        | id | colour   | shape     |
        +====+==========+===========+
        |  1 | 'blue'   | 'circle'  |
        +----+----------+-----------+
        |  1 | 'blue'   | 'square'  |
        +----+----------+-----------+
        |  1 | 'red'    | 'circle'  |
        +----+----------+-----------+
        |  1 | 'red'    | 'square'  |
        +----+----------+-----------+
        |  2 | 'purple' | 'ellipse' |
        +----+----------+-----------+

        >>> # compound keys are supported
        ... table8 = [['id', 'time', 'height'],
        ...           [1, 1, 12.3],
        ...           [1, 2, 34.5],
        ...           [2, 1, 56.7]]
        >>> table9 = [['id', 'time', 'weight'],
        ...           [1, 2, 4.5],
        ...           [2, 1, 6.7],
        ...           [2, 2, 8.9]]
        >>> table10 = etl.join(table8, table9, key=['id', 'time'])
        >>> table10
        +----+------+--------+--------+
        | id | time | height | weight |
        +====+======+========+========+
        |  1 |    2 |   34.5 |    4.5 |
        +----+------+--------+--------+
        |  2 |    1 |   56.7 |    6.7 |
        +----+------+--------+--------+

    If `presorted` is True, it is assumed that the data are already sorted by
    the given key, and the `buffersize`, `tempdir` and `cache` arguments are
    ignored. Otherwise, the data are sorted, see also the discussion of the
    `buffersize`, `tempdir` and `cache` arguments under the
    :func:`petl.transform.sorts.sort` function.

    Left and right tables with different key fields can be handled via the
    `lkey` and `rkey` arguments.

    .. versionchanged:: 1.7.16
        To ensure correct results for tables with uneven rows, tables will be
        squared up before joining to ensure correct results.

    )r*   r+   	presorted
buffersizetempdircachelprefixrprefixr,   JoinView)r#   r$   r(   r*   r+   r-   r.   r/   r0   r1   r2   r   r   r   join/   s
   _
r5   c                   @   s$   e Zd Z			dddZdd ZdS )	r4   FNTc                 C   sz   || _ || _t||d| _t||d| _|s,t| j||	|
|d| _t| j||	|
|d| _|| _|| _|| _|| _	|| _
d S Nmissingr.   r/   r0   )r*   r+   r   r#   r$   r   	leftouter
rightouterr8   r1   r2   )selfr#   r$   r*   r+   r-   r:   r;   r8   r.   r/   r0   r1   r2   r   r   r   __init__   s    


zJoinView.__init__c                 C   s,   t | j| j| j| j| j| j| j| j| j	d	S )N)r:   r;   r8   r1   r2   )
iterjoinr#   r$   r*   r+   r:   r;   r8   r1   r2   r<   r   r   r   __iter__   s
   zJoinView.__iter__)	FFFNNNTNN__name__
__module____qualname__r=   r@   r   r   r   r   r4      s    
r4   c                 C   6   t | ||||\}}t| ||||dd||||	|
|dS )a  
    Perform a left outer join on the given tables. E.g.::

        >>> import petl as etl
        >>> table1 = [['id', 'colour'],
        ...           [1, 'blue'],
        ...           [2, 'red'],
        ...           [3, 'purple']]
        >>> table2 = [['id', 'shape'],
        ...           [1, 'circle'],
        ...           [3, 'square'],
        ...           [4, 'ellipse']]
        >>> table3 = etl.leftjoin(table1, table2, key='id')
        >>> table3
        +----+----------+----------+
        | id | colour   | shape    |
        +====+==========+==========+
        |  1 | 'blue'   | 'circle' |
        +----+----------+----------+
        |  2 | 'red'    | None     |
        +----+----------+----------+
        |  3 | 'purple' | 'square' |
        +----+----------+----------+

    If `presorted` is True, it is assumed that the data are already sorted by
    the given key, and the `buffersize`, `tempdir` and `cache` arguments are
    ignored. Otherwise, the data are sorted, see also the discussion of the
    `buffersize`, `tempdir` and `cache` arguments under the
    :func:`petl.transform.sorts.sort` function.

    Left and right tables with different key fields can be handled via the
    `lkey` and `rkey` arguments.

    .. versionchanged:: 1.7.16
        To ensure correct results for tables with uneven rows, tables will be
        squared up before joining to ensure correct results.

    TFr*   r+   r-   r:   r;   r8   r.   r/   r0   r1   r2   r3   r#   r$   r(   r*   r+   r8   r-   r.   r/   r0   r1   r2   r   r   r   leftjoin   s   +
rH   c                 C   rE   )a  
    Perform a right outer join on the given tables. E.g.::

        >>> import petl as etl
        >>> table1 = [['id', 'colour'],
        ...           [1, 'blue'],
        ...           [2, 'red'],
        ...           [3, 'purple']]
        >>> table2 = [['id', 'shape'],
        ...           [1, 'circle'],
        ...           [3, 'square'],
        ...           [4, 'ellipse']]
        >>> table3 = etl.rightjoin(table1, table2, key='id')
        >>> table3
        +----+----------+-----------+
        | id | colour   | shape     |
        +====+==========+===========+
        |  1 | 'blue'   | 'circle'  |
        +----+----------+-----------+
        |  3 | 'purple' | 'square'  |
        +----+----------+-----------+
        |  4 | None     | 'ellipse' |
        +----+----------+-----------+

    If `presorted` is True, it is assumed that the data are already sorted by
    the given key, and the `buffersize`, `tempdir` and `cache` arguments are
    ignored. Otherwise, the data are sorted, see also the discussion of the
    `buffersize`, `tempdir` and `cache` arguments under the
    :func:`petl.transform.sorts.sort` function.

    Left and right tables with different key fields can be handled via the
    `lkey` and `rkey` arguments.

    .. versionchanged:: 1.7.16
        To ensure correct results for tables with uneven rows, tables will be
        squared up before joining to ensure correct results.

    FTrF   r3   rG   r   r   r   	rightjoin   s   +
rI   c                 C   s6   t | ||||\}}t| ||||dd||||	|
|dS )a  
    Perform a full outer join on the given tables. E.g.::

        >>> import petl as etl
        >>> table1 = [['id', 'colour'],
        ...           [1, 'blue'],
        ...           [2, 'red'],
        ...           [3, 'purple']]
        >>> table2 = [['id', 'shape'],
        ...           [1, 'circle'],
        ...           [3, 'square'],
        ...           [4, 'ellipse']]
        >>> table3 = etl.outerjoin(table1, table2, key='id')
        >>> table3
        +----+----------+-----------+
        | id | colour   | shape     |
        +====+==========+===========+
        |  1 | 'blue'   | 'circle'  |
        +----+----------+-----------+
        |  2 | 'red'    | None      |
        +----+----------+-----------+
        |  3 | 'purple' | 'square'  |
        +----+----------+-----------+
        |  4 | None     | 'ellipse' |
        +----+----------+-----------+

    If `presorted` is True, it is assumed that the data are already sorted by
    the given key, and the `buffersize`, `tempdir` and `cache` arguments are
    ignored. Otherwise, the data are sorted, see also the discussion of the
    `buffersize`, `tempdir` and `cache` arguments under the
    :func:`petl.transform.sorts.sort` function.

    Left and right tables with different key fields can be handled via the
    `lkey` and `rkey` arguments.

    .. versionchanged:: 1.7.16
        To ensure correct results for tables with uneven rows, tables will be
        squared up before joining to ensure correct results.

    TrF   r3   rG   r   r   r   	outerjoin  s   -
rJ   c	                 #   s   t | }	t |}
t|	 t|
}t |t||t }t }fddtt|D t d u r=t }n	fdd D }d u rR|| n|fdd|D  t	|V   fdd}t
j|	|d}t
j|
|d}g }g }td td }}z[t|\}}t|\}}	 ||k r|r||d D ]}t	|V  qt|\}}n3||kr|r|d |D ]}t	|V  qt|\}}n|||D ]}t	|V  qt|\}}t|\}}q ty   Y nw |r||kr||d D ]}t	|V  q|D ]\}}||d D ]}t	|V  qq|rG||k r1|d |D ]}t	|V  q(|D ]\}}|d |D ]}t	|V  q<q3d S d S )Nc                       g | ]}| vr|qS r   r   r   irkindr   r   r   h  r   ziterjoin.<locals>.<listcomp>c                       g | ]
}t  t | qS r   r   r   r1   r   r   r   o      c                    rP   r   rQ   r   r2   r   r   r   s  rS   c                 3   s    |d u r| D ]}t |}|gt  t|V  qd S | d u rM|D ]%}gt  }tD ]
\}}|| ||< q3|| t|V  q%d S t |}| D ]}|D ]}t |}|| t|V  qWqSd S N)r   extendr"   tuplezip)_lrowgrp_rrowgrplrowoutrowrrowliri)r%   lkindr8   rgetvrO   rvindr   r   joinrowsw  s.   
ziterjoin.<locals>.joinrowsr(   )iterr   r   r   ranger"   r   r   rV   rW   	itertoolsgroupbyr   StopIteration)r#   r$   r*   r+   r:   r;   r8   r1   r2   litritr'   lgetkrgetkouthdrrc   lgitrgitlrowgrprrowgrplkvalrkvalrowr   )r%   r`   r1   r8   ra   rO   r2   rb   r   r>   U  s   





r>   c                  O   s   t | i |S )ae  
    Form the cartesian product of the given tables. E.g.::

        >>> import petl as etl
        >>> table1 = [['id', 'colour'],
        ...           [1, 'blue'],
        ...           [2, 'red']]
        >>> table2 = [['id', 'shape'],
        ...           [1, 'circle'],
        ...           [3, 'square']]
        >>> table3 = etl.crossjoin(table1, table2)
        >>> table3
        +----+--------+----+----------+
        | id | colour | id | shape    |
        +====+========+====+==========+
        |  1 | 'blue' |  1 | 'circle' |
        +----+--------+----+----------+
        |  1 | 'blue' |  3 | 'square' |
        +----+--------+----+----------+
        |  2 | 'red'  |  1 | 'circle' |
        +----+--------+----+----------+
        |  2 | 'red'  |  3 | 'square' |
        +----+--------+----+----------+

    If `prefix` is `True` then field names in the output table header will be
    prefixed by the index of the input table.

    .. versionchanged:: 1.7.16
        To ensure correct results for tables with uneven rows, tables will be
        squared up before joining to ensure correct results.

    )CrossJoinView)tableskwargsr   r   r   	crossjoin  s   "ry   c                   @      e Zd Zdd Zdd ZdS )rv   c                    s4   | dd _| dd  _ fdd|D  _d S )NprefixFr8   c                    s   g | ]	}t | jd qS )r7   )r   r8   )r   sourcer?   r   r   r     s    z*CrossJoinView.__init__.<locals>.<listcomp>)getr{   r8   sources)r<   r~   rx   r   r?   r   r=     s   zCrossJoinView.__init__c                 C   s   t | j| jS rU   )itercrossjoinr~   r{   r?   r   r   r   r@     s   zCrossJoinView.__iter__NrA   r   r   r   r   rv         rv   c                 #   s    t  }t| D ]\ }|r| fddt|D  q|t| qt|V  dd | D }tj| D ]}t  }|D ]}|| q=t|V  q6d S )Nc                    s$   g | ]}t  d  d t | qS )r   _rQ   r   rM   r   r   r   	  s   $ z!itercrossjoin.<locals>.<listcomp>c                 S   s   g | ]}t |qS r   )r   )r   srcr   r   r   r     s    )r   	enumeraterV   r   rW   rg   product)r~   r{   rn   sdatasrcsprodr\   ru   r   r   r   r     s   
r   c	           	   
   C   s,   t | ||||\}}t| |||||||dS )a	  
    Return rows from the `left` table where the key value does not occur in
    the `right` table. E.g.::

        >>> import petl as etl
        >>> table1 = [['id', 'colour'],
        ...           [0, 'black'],
        ...           [1, 'blue'],
        ...           [2, 'red'],
        ...           [4, 'yellow'],
        ...           [5, 'white']]
        >>> table2 = [['id', 'shape'],
        ...           [1, 'circle'],
        ...           [3, 'square']]
        >>> table3 = etl.antijoin(table1, table2, key='id')
        >>> table3
        +----+----------+
        | id | colour   |
        +====+==========+
        |  0 | 'black'  |
        +----+----------+
        |  2 | 'red'    |
        +----+----------+
        |  4 | 'yellow' |
        +----+----------+
        |  5 | 'white'  |
        +----+----------+

    If `presorted` is True, it is assumed that the data are already sorted by
    the given key, and the `buffersize`, `tempdir` and `cache` arguments are
    ignored. Otherwise, the data are sorted, see also the discussion of the
    `buffersize`, `tempdir` and `cache` arguments under the
    :func:`petl.transform.sorts.sort` function.

    Left and right tables with different key fields can be handled via the
    `lkey` and `rkey` arguments.

    )r#   r$   r*   r+   r-   r.   r/   r0   )r,   AntiJoinView)	r#   r$   r(   r*   r+   r-   r.   r/   r0   r   r   r   antijoin  s
   )
r   c                   @   s"   e Zd Z		dddZdd ZdS )	r   FNTc	           	      C   sJ   |r	|| _ || _nt|||||d| _ t|||||d| _|| _|| _d S )Nr9   )r#   r$   r   r*   r+   )	r<   r#   r$   r*   r+   r-   r.   r/   r0   r   r   r   r=   J  s   
zAntiJoinView.__init__c                 C   s   t | j| j| j| jS rU   )iterantijoinr#   r$   r*   r+   r?   r   r   r   r@   W  s   zAntiJoinView.__iter__)FNNTrA   r   r   r   r   r   H  s
    
r   c                 c   sL   t | }t |}t|}t|}t|V  t||}t||}	t| }
t|	 }tj||
d}tj||d}g }td td }}z:t|\}}t|\}}	 ||k rd|D ]}t|V  qUt|\}}n||krot|\}}nt|\}}t|\}}qO ty   Y nw ||kr|D ]}t|V  q|D ]\}}|D ]}t|V  qqd S )Nrd   )	re   r   rW   r   r   rg   rh   r   ri   )r#   r$   r*   r+   rj   rk   r%   r'   r`   rO   rl   rm   ro   rp   rq   rs   rt   r   ru   r   r   r   r   [  sL   


r   c                 C   s2   t | ||||\}}t| ||||||||	|
|dS )a  
    Perform a left join, but where the key is not unique in the right-hand
    table, arbitrarily choose the first row and ignore others. E.g.::

        >>> import petl as etl
        >>> table1 = [['id', 'color', 'cost'],
        ...           [1, 'blue', 12],
        ...           [2, 'red', 8],
        ...           [3, 'purple', 4]]
        >>> table2 = [['id', 'shape', 'size'],
        ...           [1, 'circle', 'big'],
        ...           [1, 'circle', 'small'],
        ...           [2, 'square', 'tiny'],
        ...           [2, 'square', 'big'],
        ...           [3, 'ellipse', 'small'],
        ...           [3, 'ellipse', 'tiny']]
        >>> table3 = etl.lookupjoin(table1, table2, key='id')
        >>> table3
        +----+----------+------+-----------+---------+
        | id | color    | cost | shape     | size    |
        +====+==========+======+===========+=========+
        |  1 | 'blue'   |   12 | 'circle'  | 'big'   |
        +----+----------+------+-----------+---------+
        |  2 | 'red'    |    8 | 'square'  | 'tiny'  |
        +----+----------+------+-----------+---------+
        |  3 | 'purple' |    4 | 'ellipse' | 'small' |
        +----+----------+------+-----------+---------+

    See also :func:`petl.transform.joins.leftjoin`.

    .. versionchanged:: 1.7.16
        To ensure correct results for tables with uneven rows, tables will be
        squared up before joining to ensure correct results.

    )r-   r8   r.   r/   r0   r1   r2   )r,   LookupJoinViewrG   r   r   r   
lookupjoin  s   'r   c                   @   s$   e Zd Z			dddZdd ZdS )	r   FNTc                 C   sn   t ||d| _t ||d| _|s&t| j||||	d| _t| j||||	d| _|| _|| _|| _|
| _|| _d S r6   )	r   r#   r$   r   r*   r+   r8   r1   r2   )r<   r#   r$   r*   r+   r-   r8   r.   r/   r0   r1   r2   r   r   r   r=     s   


zLookupJoinView.__init__c              	   C   s$   t | j| j| j| j| j| j| jdS )N)r8   r1   r2   )iterlookupjoinr#   r$   r*   r+   r8   r1   r2   r?   r   r   r   r@     s   zLookupJoinView.__iter__)FNNNTNNrA   r   r   r   r   r     s    
r   c                 #   s   t | }t |}t|}	t|}
t|	|}t|
|tj| }tj }fddtt|
D t  d u r?t|	}n	 fdd|	D }d u rT|	|
 n|	fdd|
D  t
|V  fdd}tj||d}tj||d}g }d\}}zJt|\}}t|\}}	 ||k r||d D ]}t
|V  qt|\}}n$||krt|\}}n|||D ]}t
|V  qt|\}}t|\}}q ty   Y nw ||kr||d D ]}t
|V  q|D ]\}}||d D ]}t
|V  qqd S )	Nc                    rK   r   r   rL   rN   r   r   r     r   z"iterlookupjoin.<locals>.<listcomp>c                    rP   r   rQ   r   rR   r   r   r     rS   c                    rP   r   rQ   r   rT   r   r   r     rS   c                 3   sx    |d u r| D ]}t |}| gt  t|V  qd S tt|}| D ]}t |}|| t|V  q'd S rU   )r   rV   r"   rW   r   re   )rY   rZ   r[   r\   r]   )r8   ra   rb   r   r   rc     s   z iterlookupjoin.<locals>.joinrowsrd   )NN)re   r   r   operator
itemgetterrf   r"   r   r   rV   rW   rg   rh   ri   )r#   r$   r*   r+   r8   r1   r2   rj   rk   r%   r'   r`   rl   rm   rn   rc   ro   rp   rq   rs   rt   rr   ru   r   )r1   r8   ra   rO   r2   rb   r   r     sb   





r   r   r   c                 C   sj   |du r"|r	| }n	t | ||||d}t|||}	t|||}
|	|
fS tt| |}	tt| ||}
|	|
fS )a  
    Split a table into two tables by reversing an inner join. E.g.::

        >>> import petl as etl
        >>> # join key is present in the table
        ... table1 = (('foo', 'bar', 'baz'),
        ...           ('A', 1, 'apple'),
        ...           ('B', 1, 'apple'),
        ...           ('C', 2, 'orange'))
        >>> table2, table3 = etl.unjoin(table1, 'baz', key='bar')
        >>> table2
        +-----+-----+
        | foo | bar |
        +=====+=====+
        | 'A' |   1 |
        +-----+-----+
        | 'B' |   1 |
        +-----+-----+
        | 'C' |   2 |
        +-----+-----+

        >>> table3
        +-----+----------+
        | bar | baz      |
        +=====+==========+
        |   1 | 'apple'  |
        +-----+----------+
        |   2 | 'orange' |
        +-----+----------+

        >>> # an integer join key can also be reconstructed
        ... table4 = (('foo', 'bar'),
        ...           ('A', 'apple'),
        ...           ('B', 'apple'),
        ...           ('C', 'orange'))
        >>> table5, table6 = etl.unjoin(table4, 'bar')
        >>> table5
        +-----+--------+
        | foo | bar_id |
        +=====+========+
        | 'A' |      1 |
        +-----+--------+
        | 'B' |      1 |
        +-----+--------+
        | 'C' |      2 |
        +-----+--------+

        >>> table6
        +----+----------+
        | id | bar      |
        +====+==========+
        |  1 | 'apple'  |
        +----+----------+
        |  2 | 'orange' |
        +----+----------+

    The `autoincrement` parameter controls how an integer join key is
    reconstructed, and should be a tuple of (`start`, `step`).

    Nr9   )r    ConvertToIncrementingCounterViewEnumerateDistinctViewr   r   r
   )tablevaluer(   autoincrementr-   r.   r/   r0   
tbl_sortedr#   r$   r   r   r   unjoin:  s   ?r   c                   @   rz   )r   c                 C      || _ || _|| _d S rU   r   r   r   r<   tblr   r   r   r   r   r=        
z)ConvertToIncrementingCounterView.__init__c                 c   s    t | j}t|}t|g|}| j}||}t|}d| ||< t|V  | j	\}}t
t||D ]\}	\}
}|D ]}t|}|	| | ||< t|V  q<q4d S )Nz%s_id)re   r   r   rg   chainr   indexr   rW   r   r   r   )r<   ithdrr   r   vidxrn   offset
multipliernr   groupru   r\   r   r   r   r@     s"   



z)ConvertToIncrementingCounterView.__iter__NrA   r   r   r   r   r     r   r   c                   @   rz   )r   c                 C   r   rU   r   r   r   r   r   r=     r   zEnumerateDistinctView.__init__c                 c   sN    | j \}}d| jfV  tt| j| jD ]\}\}}|| | |fV  qd S )Nid)r   r   r   r   r   )r<   r   r   r   vr   r   r   r   r@     s   
zEnumerateDistinctView.__iter__NrA   r   r   r   r   r     r   r   )	NNNFNNTNN)
NNNNFNNTNN)FFNNN)NNNFNNT)NNN)Nr   FNNT)1
__future__r   r   r   rg   r   petl.comparisonr   r   petl.compatr   r   petl.errorsr	   petl.transform.basicsr
   r   r   petl.transform.dedupr   petl.transform.sortsr   petl.util.baser   r   r   r   r   r   r)   r,   r5   r4   rH   rI   rJ   r>   ry   rv   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sx     
e
2
3
4
z%
/9
.
]
W