U
    d:                     @   s   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 d dlm	Z	 d dl
mZmZmZmZ G dd	 d	e	ZG d
d deZdS )    copy)
attrgetter)Strict)MinMax)UniqueSequence)Serialisable)range_boundariesrange_to_tupleget_column_letterquote_sheetnamec                   @   s  e Zd ZdZeddedZeddedZeddedZeddedZ	dFddZ
ed	d
 Zedd Zedd Zedd Zedd Zdd Zdd Zdd Zdd Zdd ZdGddZd d! Zd"d# Zd$d% ZeZd&d' Zd(d) Zd*d+ ZeZd,d- Zd.d/ Z d0d1 Z!d2d3 Z"e"Z#d4d5 Z$e$Z%d6d7 Z&dHd8d9Z'dId:d;Z(ed<d= Z)ed>d? Z*ed@dA Z+edBdC Z,edDdE Z-dS )J	CellRangea  
    Represents a range in a sheet: title and coordinates.

    This object is used to perform operations on ranges, like:

    - shift, expand or shrink
    - union/intersection with another sheet range,

    We can check whether a range is:

    - equal or not equal to another,
    - disjoint of another,
    - contained in another.

    We can get:

    - the size of a range.
    - the range bounds (vertices)
    - the coordinates,
    - the string representation,

       ifG  )minmaxexpected_typei   Nc                 C   s   |d k	r6d|kr&t |\}\}}}}nt|\}}}}|| _|| _|| _|| _|| _||krrd}t|j||d||krd}t|j||dd S )N!z({max_col} must be greater than {min_col})min_colmax_colz({max_row} must be greater than {min_row})min_rowmax_row)	r
   r	   r   r   r   r   title
ValueErrorformat)selfZrange_stringr   r   r   r   r   fmt r   A/tmp/pip-unpacked-wheel-rwywncvq/openpyxl/worksheet/cell_range.py__init__0   s    zCellRange.__init__c                 C   s   | j | j| j| jfS )z2
        Vertices of the range as a tuple
        r   r   r   r   r   r   r   r   boundsF   s    zCellRange.boundsc                 C   sB   d}| j | jkr | j| jkr d}|jt| j | jt| j| jdS )z9
        Excel-style representation of the range
        z%{min_col}{min_row}:{max_col}{max_row}z{min_col}{min_row}r   )r   r   r   r   r   r   r   r   r   r   r   coordN   s    
zCellRange.coordc                 #   s>   t | j| jd D ]&  fddt | j| jd D V  qdS )z1
        Return cell coordinates as rows
        r   c                    s   g | ]} |fqS r   r   .0colrowr   r   
<listcomp>e   s     z"CellRange.rows.<locals>.<listcomp>N)ranger   r   r   r   r    r   r'   r   rows_   s    zCellRange.rowsc                 #   s>   t | j| jd D ]&  fddt | j| jd D V  qdS )z4
        Return cell coordinates as columns
        r   c                    s   g | ]}| fqS r   r   r%   r(   r&   r   r   r)   n   s     z"CellRange.cols.<locals>.<listcomp>N)r*   r   r   r   r   r    r   r-   r   colsh   s    zCellRange.colsc                 C   s2   ddl m} |t| j| jd t| j| jd S )Nr   )productr   )	itertoolsr/   r*   r   r   r   r   )r   r/   r   r   r   cellsq   s    zCellRange.cellsc                 C   s8   t |tsttt||jr4| j|jkr4tddS )z
        Check whether comparisons between ranges are possible.
        Cannot compare ranges from different worksheets
        Skip if the range passed in has no title.
        z1Cannot work with ranges from different worksheetsN)
isinstancer   	TypeErrorreprtyper   r   r   otherr   r   r   _check_titlew   s    
zCellRange._check_titlec                 C   s&   d}| j rd}|j| jj| j | jdS )Nz<{cls} {coord}>z<{cls} {title!r}!{coord}>)clsr   r#   )r   r   	__class____name__r#   r"   r   r   r   __repr__   s    zCellRange.__repr__c                 C   s   t | j| j| j| jfS N)hashr   r   r   r   r    r   r   r   __hash__   s    zCellRange.__hash__c                 C   s*   d}| j }|rd}t|}|j|| jdS )Nz{coord}z{title}!{coord})r   r#   )r   r   r   r#   )r   r   r   r   r   r   __str__   s    zCellRange.__str__c                 C   s   | j | j| j| j| j| jdS )Nr   r   r   r   r   )r:   r   r   r   r   r   r    r   r   r   __copy__   s
     zCellRange.__copy__r   c                 C   sh   | j | dks| j| dkr,td|||  j |7  _ |  j|7  _|  j|7  _|  j|7  _dS )a{  
        Shift the focus of the range according to the shift values (*col_shift*, *row_shift*).

        :type col_shift: int
        :param col_shift: number of columns to be moved by, can be negative
        :type row_shift: int
        :param row_shift: number of rows to be moved by, can be negative
        :raise: :class:`ValueError` if any row or column index < 1
        r   z1Invalid shift value: col_shift={0}, row_shift={1}N)r   r   r   r   r   r   )r   Z	col_shiftZ	row_shiftr   r   r   shift   s    zCellRange.shiftc                 C   sV   z|  | W n tk
r$   Y dS X |j| jkpT| j|jkpT|j| jkpT| j|jkS )z
        Test whether the ranges are not equal.

        :type other: openpyxl.worksheet.cell_range.CellRange
        :param other: Other sheet range
        :return: ``True`` if *range* != *other*.
        T)r8   r   r   r   r   r   r6   r   r   r   __ne__   s    


zCellRange.__ne__c                 C   s   |  | S )z
        Test whether the ranges are equal.

        :type other: openpyxl.worksheet.cell_range.CellRange
        :param other: Other sheet range
        :return: ``True`` if *range* == *other*.
        )rD   r6   r   r   r   __eq__   s    zCellRange.__eq__c                 C   s   |  | || S )z
        Test whether every cell in this range is also in *other*.

        :type other: openpyxl.worksheet.cell_range.CellRange
        :param other: Other sheet range
        :return: ``True`` if *range* <= *other*.
        r8   _CellRange__supersetr6   r   r   r   issubset   s    
zCellRange.issubsetc                 C   s   |  |o| |S )z
        Test whether *other* contains every cell of this range, and more.

        :type other: openpyxl.worksheet.cell_range.CellRange
        :param other: Other sheet range
        :return: ``True`` if *range* < *other*.
        )__le__rD   r6   r   r   r   __lt__   s    zCellRange.__lt__c                 C   sT   | j |j   ko$|j  ko$| jkn  oR| j|j  koN|j  koN| jkS   S r=   )r   r   r   r   r6   r   r   r   Z
__superset   s    *(zCellRange.__supersetc                 C   s   |  | | |S )z
        Test whether every cell in *other* is in this range.

        :type other: openpyxl.worksheet.cell_range.CellRange
        :param other: Other sheet range
        :return: ``True`` if *range* >= *other* (or *other* in *range*).
        rF   r6   r   r   r   
issuperset   s    
zCellRange.issupersetc                 C   s   |  |}| |S )zO
        Check whether the range contains a particular cell coordinate
        )r:   rG   r   r#   crr   r   r   __contains__  s    
zCellRange.__contains__c                 C   s   |  |o| |S )z
        Test whether this range contains every cell in *other*, and more.

        :type other: openpyxl.worksheet.cell_range.CellRange
        :param other: Other sheet range
        :return: ``True`` if *range* > *other*.
        )__ge__rD   r6   r   r   r   __gt__  s    zCellRange.__gt__c                 C   sD   |  | | j|jkr ||  } }| j|jk pB| j|jk pB|j| jk S )aV  
        Return ``True`` if this range has no cell in common with *other*.
        Ranges are disjoint if and only if their intersection is the empty range.

        :type other: openpyxl.worksheet.cell_range.CellRange
        :param other: Other sheet range.
        :return: ``True`` if the range has no cells in common with other.
        )r8   r!   r   r   r   r   r6   r   r   r   
isdisjoint  s    	



zCellRange.isdisjointc                 C   sb   |  |rtd| |t| j|j}t| j|j}t| j|j}t| j|j}t	||||dS )aN  
        Return a new range with cells common to this range and *other*

        :type other: openpyxl.worksheet.cell_range.CellRange
        :param other: Other sheet range.
        :return: the intersecting sheet range.
        :raise: :class:`ValueError` if the *other* range doesn't intersect
            with this range.
        zRange {0} doesn't intersect {0}r   )
rQ   r   r   r   r   r   r   r   r   r   r   r7   r   r   r   r   r   r   r   intersection*  s    

zCellRange.intersectionc                 C   sV   |  | t| j|j}t| j|j}t| j|j}t| j|j}t||||| jdS )a  
        Return the minimal superset of this range and *other*. This new range
        will contain all cells from this range, *other*, and any additional
        cells required to form a rectangular ``CellRange``.

        :type other: openpyxl.worksheet.cell_range.CellRange
        :param other: Other sheet range.
        :return: a ``CellRange`` that is a superset of this and *other*.
        rA   )	r8   r   r   r   r   r   r   r   r   rR   r   r   r   unionB  s    

 zCellRange.unionc                 c   s.   | j D ]"}|dkrqt| |}||fV  qdS )zC
        For use as a dictionary elsewhere in the library.
        r   N)	__attrs__getattr)r   xvr   r   r   __iter__X  s
    

zCellRange.__iter__c                 C   s<   |  j |8  _ |  j|8  _|  j|7  _|  j|7  _dS )a  
        Expand the range by the dimensions provided.

        :type right: int
        :param right: expand range to the right by this number of cells
        :type down: int
        :param down: expand range down by this number of cells
        :type left: int
        :param left: expand range to the left by this number of cells
        :type up: int
        :param up: expand range up by this number of cells
        Nr   )r   rightZdownleftZupr   r   r   expandc  s    zCellRange.expandc                 C   s<   |  j |7  _ |  j|7  _|  j|8  _|  j|8  _dS )a  
        Shrink the range by the dimensions provided.

        :type right: int
        :param right: shrink range from the right by this number of cells
        :type down: int
        :param down: shrink range from the top by this number of cells
        :type left: int
        :param left: shrink range from the left by this number of cells
        :type up: int
        :param up: shrink range from the bottom by this number of cells
        Nr   )r   rZ   bottomr[   topr   r   r   shrinkv  s    zCellRange.shrinkc                 C   s*   | j d | j }| jd | j }||dS )zC Return the size of the range as a dictionary of rows and columns. r   )columnsr+   )r   r   r   r   )r   r.   r+   r   r   r   size  s    zCellRange.sizec                    s     fddt  j jd D S )z=A list of cell coordinates that comprise the top of the rangec                    s   g | ]} j |fqS r   )r   r$   r    r   r   r)     s     z!CellRange.top.<locals>.<listcomp>r   r*   r   r   r    r   r    r   r^     s    zCellRange.topc                    s     fddt  j jd D S )z@A list of cell coordinates that comprise the bottom of the rangec                    s   g | ]} j |fqS r   )r   r$   r    r   r   r)     s     z$CellRange.bottom.<locals>.<listcomp>r   rb   r    r   r    r   r]     s    zCellRange.bottomc                    s     fddt  j jd D S )zCA list of cell coordinates that comprise the left-side of the rangec                    s   g | ]}| j fqS r   )r   r,   r    r   r   r)     s     z"CellRange.left.<locals>.<listcomp>r   r*   r   r   r    r   r    r   r[     s    zCellRange.leftc                    s     fddt  j jd D S )zDA list of cell coordinates that comprise the right-side of the rangec                    s   g | ]}| j fqS r   )r   r,   r    r   r   r)     s     z#CellRange.right.<locals>.<listcomp>r   rc   r    r   r    r   rZ     s    zCellRange.right)NNNNNN)r   r   )r   r   r   r   )r   r   r   r   ).r;   
__module____qualname____doc__r   intr   r   r   r   r   propertyr!   r#   r+   r.   r1   r8   r<   r?   r@   rB   rC   rD   rE   rH   rI   rJ   rG   rK   rO   rN   rP   rQ   rS   __and__rT   __or__rY   r\   r_   ra   r^   r]   r[   rZ   r   r   r   r   r      sl         





	






r   c                   @   s   e Zd ZeedZe f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S )MultiCellRange)r   c                 C   s*   t |trdd | D }t|| _d S )Nc                 S   s   g | ]}t |qS r   )r   r%   rr   r   r   r)     s     z+MultiCellRange.__init__.<locals>.<listcomp>)r2   strsplitsetrangesr   rq   r   r   r   r     s    
zMultiCellRange.__init__c                 C   s0   t |trt|}| jD ]}||kr dS qdS )NTF)r2   rn   r   rq   )r   r#   rm   r   r   r   rN     s    

zMultiCellRange.__contains__c                 C   s.   d dd |  D }d| jj d| dS )N c                 S   s   g | ]}t |qS r   rn   rl   r   r   r   r)     s     z+MultiCellRange.__repr__.<locals>.<listcomp><z [z]>)joinsortedr:   r;   rr   r   r   r   r<     s    zMultiCellRange.__repr__c                 C   s   d dd |  D }|S )Nrs   c                 S   s   g | ]}t |qS r   rt   rl   r   r   r   r)     s     z*MultiCellRange.__str__.<locals>.<listcomp>)rv   rw   rr   r   r   r   r@     s    zMultiCellRange.__str__c                 C   s   t t| S r=   )r>   rn   r    r   r   r   r?     s    zMultiCellRange.__hash__c                 C   s   t | jtdddddS )z/
        Return a sorted list of items
        r   r   r   r   )key)rw   rq   r   r    r   r   r   rw     s    zMultiCellRange.sortedc                 C   sB   |}t |trt|}nt |ts*td|| kr>| j| dS )z4
        Add a cell coordinate or CellRange
        zYou can only add CellRangesN)r2   rn   r   r   rq   addrL   r   r   r   ry     s    


zMultiCellRange.addc                 C   s   |  | | S r=   )ry   r   r#   r   r   r   __iadd__  s    
zMultiCellRange.__iadd__c                 C   s    t |tr| |}| j|jkS r=   )r2   rn   r:   rq   r6   r   r   r   rE     s    

zMultiCellRange.__eq__c                 C   s
   | |k S r=   r   r6   r   r   r   rD     s    zMultiCellRange.__ne__c                 C   s
   t | jS r=   )boolrq   r    r   r   r   __bool__  s    zMultiCellRange.__bool__c                 C   s"   t |tst|}| j| d S r=   )r2   r   rq   removerz   r   r   r   r~     s    
zMultiCellRange.removec                 c   s   | j D ]
}|V  qd S r=   )rq   )r   rM   r   r   r   rY     s    
zMultiCellRange.__iter__c                 C   s   dd | j D }t|S )Nc                 S   s   h | ]}t |qS r   r   rl   r   r   r   	<setcomp>  s     z*MultiCellRange.__copy__.<locals>.<setcomp>)rq   rk   rr   r   r   r   rB     s    zMultiCellRange.__copy__N)r;   rd   re   r   r   rq   rp   r   rN   r<   r@   r?   rw   ry   r{   rE   rD   r}   r~   rY   rB   r   r   r   r   rk     s   
	rk   N)r   operatorr   Zopenpyxl.descriptorsr   r   Zopenpyxl.descriptors.sequencer   Z!openpyxl.descriptors.serialisabler   Zopenpyxl.utilsr	   r
   r   r   r   rk   r   r   r   r   <module>   s      