B
    q\                 @   s  d dl Z d dlZd dlZd dlmZ d dlZd dlmZ yd dlm	Z	 W n e
k
r`   dZ	Y nX d dlmZmZ d dlmZ d dlmZ d dlmZ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 e Z G dd de!Z"e #de" dd Z$e%ej&ej'ej(ej)ej*ej+ej,ej-ej.ej/ej0gZ1d#ddZ2G dd dej3Z4G dd deZ5G dd deej3Z6G dd de6Z7G dd  d e5Z8G d!d" d"e7eej9Z:dS )$    N)deepcopy)ma)MaskedArrayFutureWarning)UnitQuantity)color_print)MetaData)BaseColumnInfodtype_info_name)dtype_bytes_or_chars   )groups)pprint)fix_column_name)_ColumnGetitemShim_MaskedColumnGetitemShimc               @   s   e Zd ZdZdS )StringTruncateWarninga%  
    Warning class for when a string column is assigned a value
    that gets truncated because the base (numpy) string length
    is too short.

    This does not inherit from AstropyWarning because we want to use
    stacklevel=2 to show the user where the issue occurred in their code.
    N)__name__
__module____qualname____doc__ r   r   3lib/python3.7/site-packages/astropy/table/column.pyr   &   s   r   alwaysc                s"   ddl m   fddt| D S )Nr   )confc                s   g | ]}t  j|qS r   )strZauto_colnameformat).0i)r   r   r   
<listcomp>8   s    z_auto_names.<locals>.<listcomp>) r   range)Zn_colsr   )r   r   _auto_names6   s    r"   Tc             C   s   t | tr|  S | jj}| jj}d| j_g | j_z\t| drF|  nt| }| j|_|rft|pbg ng |j_x|jjD ]}|| | qxW W d|| j_|| j_X |S )a  
    Mixin-safe version of Column.copy() (with copy_data=True).

    Parameters
    ----------
    col : Column or mixin column
        Input column
    copy_indices : bool
        Copy the column ``indices`` attribute

    Returns
    -------
    col : Copy of input column
    Ncopy)	
isinstance
BaseColumnr#   infoparent_tableindiceshasattrr   replace_col)colcopy_indicesr'   r(   Znewcolindexr   r   r   col_copyD   s    

r.   c               @   s    e Zd ZdZdd Zdd ZdS )
FalseArraya  
    Boolean mask array that is always False.

    This is used to create a stub ``mask`` property which is a boolean array of
    ``False`` used by default for mixin columns and corresponding to the mixin
    column data shape.  The ``mask`` looks like a normal numpy array but an
    exception will be raised if ``True`` is assigned to any element.  The
    consequences of the limitation are most obvious in the high-level table
    operations.

    Parameters
    ----------
    shape : tuple
        Data shape
    c             C   s   t j|td| }|S )N)dtype)npzerosboolview)clsshapeobjr   r   r   __new__~   s    zFalseArray.__new__c             C   s*   t |}t |r&td| jjd S )Nz+Cannot set any element of {0} class to True)r1   asarrayany
ValueErrorr   	__class__r   )selfitemvalr   r   r   __setitem__   s    

zFalseArray.__setitem__N)r   r   r   r   r8   r@   r   r   r   r   r/   n   s   r/   c               @   s$   e Zd ZdZejZdZdddZdS )
ColumnInfoz
    Container for meta information like name, description, format.

    This is required when the object is used as a mixin column within a table,
    but can be used as a general way to store meta information.
    TwarnNc             C   s$   |  |||d}| jf d|i|S )a  
        Return a new Column instance which is consistent with the
        input ``cols`` and has ``length`` rows.

        This is intended for creating an empty column object whose elements can
        be set in-place for table operations like join or vstack.

        Parameters
        ----------
        cols : list
            List of input columns
        length : int
            Length of the output column object
        metadata_conflicts : str ('warn'|'error'|'silent')
            How to handle metadata conflicts
        name : str
            Output column name

        Returns
        -------
        col : Column (or subclass)
            New instance of this class consistent with ``cols``

        )metaunitr   descriptionlength)Zmerge_cols_attributesZ_parent_cls)r=   ZcolsrF   Zmetadata_conflictsnameattrsr   r   r   new_like   s    
zColumnInfo.new_like)rB   N)	r   r   r   r   r	   
attr_namesZattrs_from_parentZ_supports_indexingrI   r   r   r   r   rA      s   rA   c                   s~  e Zd Ze ZdBddZedd	 Zed
d Zej	dd Ze
 ZdCddZdd Zdd Z fddZdD fdd	Zedd Zej	dd Zedd Zej	dd Zedd Zd d! Zd"d# Zed$d% ZdEd&d'ZdFd(d)ZdGd*d+Zed,d- Zej	d.d- Zejd/d- Zg fd0d1Zed2d3 Zd4d5 Zd6d7 Zd8d9 Z ed:d; Z!g fd<d=Z"d>d? Z#e$d@dA Z%  Z&S )Hr%   Nr   r   FTc             C   s  |d kr*t |j|f}t j||d}nt|trt|drt j|j||
d}|d kr^|j	}|d krp|pn|j
}|d kr~|j}|	d krt|j}	|d kr|j}nt|tr|d krt j|||
d}|j
}nt j||||
d}|d kr|jj	}|d kr|jj}|	d krHt|jj}	n,t |jdkr8| |}t j|||
d}|| }t||_d |_||_
||_||_	|	|_|rtt|dg ng |_x|jD ]}||| qW |S )N)r0   _name)r0   r#   Sr(   )r1   r0   r   r2   r$   r%   r)   arraydatarE   rD   r   r   rC   rG   r   tor&   char_encode_strr4   r   rK   _parent_table_formatgetattrr(   r*   )r5   rN   rG   r0   r6   rF   rE   rD   r   rC   r#   r,   	self_datar=   r-   r   r   r   r8      sP    






zBaseColumn.__new__c             C   s   |  tjS )N)r4   r1   ndarray)r=   r   r   r   rN      s    zBaseColumn.datac             C   s    t | dd d krd S |  S d S )NrR   )rT   rR   )r=   r   r   r   r'      s    zBaseColumn.parent_tablec             C   s    |d krd | _ nt|| _ d S )N)rR   weakrefref)r=   tabler   r   r   r'      s    Cc             C   sR   |dkr| j }|r||}|| j}||  t| trD|j|_| | |S )am  
        Return a copy of the current instance.

        If ``data`` is supplied then a view (reference) of ``data`` is used,
        and ``copy_data`` is ignored.

        Parameters
        ----------
        order : {'C', 'F', 'A', 'K'}, optional
            Controls the memory layout of the copy. 'C' means C-order,
            'F' means F-order, 'A' means 'F' if ``a`` is Fortran contiguous,
            'C' otherwise. 'K' means match the layout of ``a`` as closely
            as possible. (Note that this function and :func:numpy.copy are very
            similar, but have different default values for their order=
            arguments.)  Default is 'C'.
        data : array, optional
            If supplied then use a view of ``data`` instead of the instance
            data.  This allows copying the instance attributes and meta.
        copy_data : bool, optional
            Make a copy of the internal numpy array instead of using a
            reference.  Default is True.

        Returns
        -------
        col : Column or MaskedColumn
            Copy of the current column (same type as original)
        N)	rN   r#   r4   r<   __array_finalize__r$   MaskedColumnZ_mask_copy_groups)r=   orderrN   Z	copy_dataoutr   r   r   r#     s    



zBaseColumn.copyc             C   sx   d}dd t ||d D }|dd }t| tjr:tjntj}|| | x | D ]\}}t| || qVW d| _	dS )z
        Restore the internal state of the Column/MaskedColumn for pickling
        purposes.  This requires that the last element of ``state`` is a
        5-tuple that has Column-specific state values.
        )rK   _unitrS   rE   rC   r(   c             S   s   i | ]\}}||qS r   r   )r   rG   r?   r   r   r   
<dictcomp>8  s    z+BaseColumn.__setstate__.<locals>.<dictcomp>N)
zipr$   r   MaskedArrayr1   rV   __setstate__itemssetattrrR   )r=   statenamesrH   super_classrG   r?   r   r   r   re   0  s    zBaseColumn.__setstate__c             C   sX   t | tjrtjntj}|| \}}}| j| j| j| j	| j
| jf}||f }|||fS )z
        Return a 3-tuple for pickling a Column.  Use the super-class
        functionality but then add in a 5-tuple of Column-specific values
        that get used in __setstate__.
        )r$   r   rd   r1   rV   
__reduce__rG   rD   r   rE   rC   r(   )r=   rj   Zreconstruct_funcZreconstruct_func_argsrh   Zcolumn_stater   r   r   rk   J  s    
zBaseColumn.__reduce__c                sH   |d krd S t t jr$t | d | _t| ds:g | _| | d S )Nr(   )callablesuperr[   r'   r)   r(   _copy_attrs)r=   r7   )r<   r   r   r[   Z  s    
zBaseColumn.__array_finalize__c                sJ   t  ||}| j|jks8t|trB|dk	rB|d tkrB|jd S |S dS )a  
        __array_wrap__ is called at the end of every ufunc.

        Normally, we want a Column object back and do not have to do anything
        special. But there are two exceptions:

        1) If the output shape is different (e.g. for reduction ufuncs
           like sum() or mean()), a Column still linking to a parent_table
           makes little sense, so we return the output viewed as the
           column content (ndarray or MaskedArray).
           For this case, we use "[()]" to select everything, and to ensure we
           convert a zero rank array to a scalar. (For some reason np.sum()
           returns a zero rank scalar array while np.mean() returns a scalar;
           So the [()] is needed for this case.

        2) When the output is created by any function that returns a boolean
           we also want to consistently return an array rather than a column
           (see #1446 and #1685)
        Nr   r   )rm   __array_wrap__r6   r$   r%   _comparison_functionsrN   )r=   Zout_arrcontext)r<   r   r   ro   j  s    

zBaseColumn.__array_wrap__c             C   s   | j S )z*
        The name of this column.
        )rK   )r=   r   r   r   rG     s    zBaseColumn.namec             C   s2   t |}| jd k	r(| j}|j| j| || _d S )N)r   r'   columnsZ_rename_columnrG   rK   )r=   r?   rY   r   r   r   rG     s
    
c             C   s   | j S )zE
        Format string for displaying values in this column.
        )rS   )r=   r   r   r   r     s    zBaseColumn.formatc          
   C   sh   t | dd }|| _y| jdd W n@ tk
rb } z"|| _td| j|jd W d d }~X Y nX d S )NrS   r   )	max_linesz`Invalid format for column '{0}': could not display values in this column using this format ({1})r   )rT   rS   pformat	Exceptionr;   r   rG   args)r=   format_stringZprev_formaterrr   r   r   r     s    c             C   s   | j | jj| jdd fS )zArray-interface compliant full description of the column.

        This returns a 3-tuple (name, type, shape) that can always be
        used in a structured array dtype definition.
        r   N)rG   r0   r   r6   )r=   r   r   r   descr  s    zBaseColumn.descrc             c   s0   | j j}x"|| ddddi dD ]
}|V  qW dS )z
        Return an iterator that yields the string-formatted values of this
        column.

        Returns
        -------
        str_vals : iterator
            Column values formatted as strings
        rb   F)	show_name	show_unit
show_dtypeoutsN)
_formatter_pformat_col_iter)r=   r   Zstr_valr   r   r   iter_str_vals  s    zBaseColumn.iter_str_valsc                s2   t  tstdd}t fdd|D }|S )a{  Compare the column attributes of ``col`` to this object.

        The comparison attributes are: ``name``, ``unit``, ``dtype``,
        ``format``, ``description``, and ``meta``.

        Parameters
        ----------
        col : Column
            Comparison column

        Returns
        -------
        equal : boolean
            True if all attributes are equal
        z8Comparison `col` must be a Column or MaskedColumn object)rG   rD   r0   r   rE   rC   c             3   s"   | ]}t |t  |kV  qd S )N)rT   )r   x)r+   r=   r   r   	<genexpr>  s    z)BaseColumn.attrs_equal.<locals>.<genexpr>)r$   r%   r;   all)r=   r+   rH   equalr   )r+   r=   r   attrs_equal  s
    
zBaseColumn.attrs_equalc             C   s   | j d krtS | j jS )N)r'   	FORMATTERZ	formatter)r=   r   r   r   r~     s    zBaseColumn._formatterc       	      C   s$   | j j}|| |||||d\}}|S )a  Return a list of formatted string representation of column values.

        If no value of ``max_lines`` is supplied then the height of the
        screen terminal is used to set ``max_lines``.  If the terminal
        height cannot be determined then the default will be
        determined using the ``astropy.conf.max_lines`` configuration
        item. If a negative value of ``max_lines`` is supplied then
        there is no line limit applied.

        Parameters
        ----------
        max_lines : int
            Maximum lines of output (header + data rows)

        show_name : bool
            Include column name. Default is True.

        show_unit : bool
            Include a header row for unit. Default is False.

        show_dtype : bool
            Include column dtype. Default is False.

        html : bool
            Format the output as an HTML table. Default is False.

        Returns
        -------
        lines : list
            List of lines with header and formatted column values

        )rz   r{   r|   html)r~   _pformat_col)	r=   rs   rz   r{   r|   r   r   linesr}   r   r   r   rt     s
    "zBaseColumn.pformatc             C   s\   | j j}|| ||||d\}}|d }x0t|D ]$\}	}
|	|k rLt|
d q0t|
 q0W dS )a   Print a formatted string representation of column values.

        If no value of ``max_lines`` is supplied then the height of the
        screen terminal is used to set ``max_lines``.  If the terminal
        height cannot be determined then the default will be
        determined using the ``astropy.conf.max_lines`` configuration
        item. If a negative value of ``max_lines`` is supplied then
        there is no line limit applied.

        Parameters
        ----------
        max_lines : int
            Maximum number of values in output

        show_name : bool
            Include column name. Default is True.

        show_unit : bool
            Include a header row for unit. Default is False.

        show_dtype : bool
            Include column dtype. Default is True.
        )rz   r{   r|   n_headerZredN)r~   r   	enumerater   print)r=   rs   rz   r{   r|   r   r   r}   r   r   liner   r   r   r     s    
zBaseColumn.pprintc             C   s   | j j}|| |||d dS )a  Interactively browse column with a paging interface.

        Supported keys::

          f, <space> : forward one page
          b : back one page
          r : refresh same page
          n : next row
          p : previous row
          < : go to beginning
          > : go to end
          q : quit browsing
          h : print this help

        Parameters
        ----------
        max_lines : int
            Maximum number of lines in table output.

        show_name : bool
            Include a header row for column names. Default is True.

        show_unit : bool
            Include a header row for unit. Default is False.

        )rs   rz   r{   N)r~   _more_tabcol)r=   rs   rz   r{   r   r   r   r   more3  s    zBaseColumn.morec             C   s   | j S )a  
        The unit associated with this column.  May be a string or a
        `astropy.units.UnitBase` instance.

        Setting the ``unit`` property does not change the values of the
        data.  To perform a unit conversion, use ``convert_unit_to``.
        )r`   )r=   r   r   r   rD   R  s    	zBaseColumn.unitc             C   s"   |d krd | _ nt|dd| _ d S )NZsilent)Zparse_strict)r`   r   )r=   rD   r   r   r   rD   ]  s    c             C   s
   d | _ d S )N)r`   )r=   r   r   r   rD   d  s    c             C   s:   | j dkrtd| j j|| j|d| jdd< || _ dS )a  
        Converts the values of the column in-place from the current
        unit to the given unit.

        To change the unit associated with this column without
        actually changing the data values, simply set the ``unit``
        property.

        Parameters
        ----------
        new_unit : str or `astropy.units.UnitBase` instance
            The unit to convert to.

        equivalencies : list of equivalence pairs, optional
           A list of equivalence pairs to try if the unit are not
           directly convertible.  See :ref:`unit_equivalencies`.

        Raises
        ------
        astropy.units.UnitsError
            If units are inconsistent
        NzNo unit set on column)equivalencies)rD   r;   rO   rN   )r=   Znew_unitr   r   r   r   convert_unit_toh  s
    
zBaseColumn.convert_unit_toc             C   s   t | dst| | _| jS )N_groups)r)   r   ColumnGroupsr   )r=   r   r   r   r     s    
zBaseColumn.groupsc             C   s   t | |S )a  
        Group this column by the specified ``keys``

        This effectively splits the column into groups which correspond to
        unique values of the ``keys`` grouping object.  The output is a new
        `Column` or `MaskedColumn` which contains a copy of this column but
        sorted by row according to ``keys``.

        The ``keys`` input to ``group_by`` must be a numpy array with the
        same length as this column.

        Parameters
        ----------
        keys : numpy array
            Key grouping object

        Returns
        -------
        out : Column
            New column with groups attribute set accordingly
        )r   Zcolumn_group_by)r=   keysr   r   r   group_by  s    zBaseColumn.group_byc             C   sL   | j r*t| j drHtj|| j jjd|_nt| drHtj|| jjd|_dS )zA
        Copy current groups into a copy of self ``out``
        r   )r(   N)r'   r)   r   r   r   Z_indices)r=   r_   r   r   r   r]     s
    
zBaseColumn._copy_groupsc             C   s   t |  S )N)r1   r9   __repr__)r=   r   r   r   r     s    zBaseColumn.__repr__c             C   s   t | | jd| jdddS )z
        A view of this table column as a `~astropy.units.Quantity` object with
        units given by the Column's `unit` parameter.
        FAT)r#   r0   r^   Zsubok)r   rD   r0   )r=   r   r   r   quantity  s    	zBaseColumn.quantityc             K   s   | j ||S )a  
        Converts this table column to a `~astropy.units.Quantity` object with
        the requested units.

        Parameters
        ----------
        unit : `~astropy.units.Unit` or str
            The unit to convert to (i.e., a valid argument to the
            :meth:`astropy.units.Quantity.to` method).
        equivalencies : list of equivalence pairs, optional
            Equivalencies to use for this conversion.  See
            :meth:`astropy.units.Quantity.to` for more details.

        Returns
        -------
        quantity : `~astropy.units.Quantity`
            A quantity object with the contents of this column in the units
            ``unit``.
        )r   rO   )r=   rD   r   kwargsr   r   r   rO     s    zBaseColumn.toc             C   s<   x$dD ]}t ||d}t| || qW tt |di | _dS )zA
        Copy key column attributes from ``obj`` to self
        )rG   rD   rS   rE   NrC   )rT   rg   r   rC   )r=   r7   attrr?   r   r   r   rn     s    
zBaseColumn._copy_attrsc             C   s~   t | tr| d} ndt | tsz| tjjkr.nLt| }|jj	dkrvtj	j|dd}t | tjj
rvtjj|| jdd}|} | S )zm
        Encode anything that is unicode-ish as utf-8.  This method is only
        called for Py3+.
        zutf-8U)encodingF)maskr#   )r$   r   encodebytesr1   r   maskedr9   r0   rP   rd   rM   r   )valueZarrr   r   r   rQ     s    

zBaseColumn._encode_str)NNNr   r   NNNNFT)rZ   NT)N)NTFFF)NTFF)NTF)'r   r   r   r   rC   r8   propertyrN   r'   setterrA   r&   r#   re   rk   r[   ro   rG   r   ry   r   r   r~   rt   r   r   rD   deleterr   r   r   r]   r   r   rO   rn   staticmethodrQ   __classcell__r   r   )r<   r   r%      sL      
4

,
	 
'
#
	r%   c                   s   e Zd ZdZd# fdd	Z fd	d
Zd$ddZdd Zdd Zdd Z	dd Z
dd Zdd Zdd ZedZedZedZedZedZed Zd%d!d"ZejZejZejZejZejZejZejZejZejZ  ZS )&Columna	  Define a data column for use in a Table object.

    Parameters
    ----------
    data : list, ndarray or None
        Column data values
    name : str
        Column name and key for reference within Table
    dtype : numpy.dtype compatible value
        Data type for column
    shape : tuple or ()
        Dimensions of a single row element in the column data
    length : int or 0
        Number of row elements in column data
    description : str or None
        Full description of column
    unit : str or None
        Physical unit
    format : str or None or function or callable
        Format string for outputting column values.  This can be an
        "old-style" (``format % value``) or "new-style" (`str.format`)
        format specification string or a function or any callable object that
        accepts a single value and returns a string.
    meta : dict-like or None
        Meta-data associated with the column

    Examples
    --------
    A Column can be created in two different ways:

    - Provide a ``data`` value but not ``shape`` or ``length`` (which are
      inferred from the data).

      Examples::

        col = Column(data=[1, 2], name='name')  # shape=(2,)
        col = Column(data=[[1, 2], [3, 4]], name='name')  # shape=(2, 2)
        col = Column(data=[1, 2], name='name', dtype=float)
        col = Column(data=np.array([1, 2]), name='name')
        col = Column(data=['hello', 'world'], name='name')

      The ``dtype`` argument can be any value which is an acceptable
      fixed-size data-type initializer for the numpy.dtype() method.  See
      `<https://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html>`_.
      Examples include:

      - Python non-string type (float, int, bool)
      - Numpy non-string type (e.g. np.float32, np.int64, np.bool\_)
      - Numpy.dtype array-protocol type strings (e.g. 'i4', 'f8', 'S15')

      If no ``dtype`` value is provide then the type is inferred using
      ``np.array(data)``.

    - Provide ``length`` and optionally ``shape``, but not ``data``

      Examples::

        col = Column(name='name', length=5)
        col = Column(name='name', dtype=int, length=10, shape=(3,4))

      The default ``dtype`` is ``np.float64``.  The ``shape`` argument is the
      array shape of a single cell in the column.
    Nr   r   FTc                sF   t |trt|jrtdt j| |||||||||	|
|d}|S )Nz;Cannot convert a MaskedColumn with masked value to a Column)rN   rG   r0   r6   rF   rE   rD   r   rC   r#   r,   )r$   r\   r1   r:   r   	TypeErrorrm   r8   )r5   rN   rG   r0   r6   rF   rE   rD   r   rC   r#   r,   r=   )r<   r   r   r8   3  s    
zColumn.__new__c                s   t | ts|dkrtdt || |dkr~t| jjtj	r~y| j
| }W n tk
rd   Y nX || k	r~| j
| j| d S )Nr   z5cannot set mask value to a column in non-masked TablerD   )r$   r\   AttributeErrorrm   __setattr__
issubclassr0   typer1   Znumberr'   Z_convert_col_for_tableZreplace_columnrG   )r=   r>   r   Z	converted)r<   r   r   r   A  s    zColumn.__setattr__c          	   C   s  | j dkrt|  S | jjg}| jd kr.d nt| j}| j dkrFd n| jdd  }xdd| jfdt	| j
fd|fd|fd| jfd| jfd	t| ffD ]"\}}|d k	r|d
|| qW dd| d }|rddlm} ||}| jj| ddd|d\}	}
|d|	 }|S )Nr   r   rG   r0   r6   rD   r   rE   rF   z	{0}={1!r}< z>
)
xml_escapeF)rz   r{   Zshow_lengthr   
)ndimreprr>   r<   r   rD   r   r6   rG   r
   r0   r   rE   lenappendjoinZastropy.utils.xml.writerr   r~   r   )r=   r   Z
descr_valsrD   r6   r   r?   ry   r   Z
data_linesr}   r_   r   r   r   _base_repr_O  s,    


zColumn._base_repr_c             C   s   | j ddS )NT)r   )r   )r=   r   r   r   _repr_html_o  s    zColumn._repr_html_c             C   s   | j ddS )NF)r   )r   )r=   r   r   r   r   r  s    zColumn.__repr__c             C   s0   | j dkrt|  S | j| \}}d|S )Nr   r   )r   r   r>   r~   r   r   )r=   r   r}   r   r   r   __str__u  s    
zColumn.__str__c             C   s   t | dS )Nzutf-8)r   r   )r=   r   r   r   	__bytes__}  s    zColumn.__bytes__c             C   s\   t j|| jjd}|jdkr dS t j| }t| j}||krXt	j
d|tdd dS )z{
        Emit a warning if any elements of ``value`` will be truncated when
        ``value`` is assigned to self.
        )r0   r   NzLtruncated right side string(s) longer than {} character(s) during assignment   )
stacklevel)r1   
asanyarrayr0   r   sizerP   Zstr_lenmaxr   warningsrB   r   r   )r=   r   Zvalue_str_lenZself_str_lenr   r   r   _check_string_truncate  s    

zColumn._check_string_truncatec             C   sR   | j jdkr| |}t| j jtjr0| | | j	||t
|  || j|< d S )NrL   )r0   rP   rQ   r   r   r1   	characterr   r&   adjust_indicesr   rN   )r=   r-   r   r   r   r   r@     s    

zColumn.__setitem__c                s(   ddddddd   fdd	}|S )
z
        Make comparison methods which encode the ``other`` object to utf-8
        in the case of a bytestring dtype for Py3+.
        __eq____ne____lt____gt____le____ge__)r   r   r   r   r   r   c                sd    }t | tr>| jjdkr>t |tr>|jjdkr>||  } }}| jjdkrT| |}t| j||S )Nr   rL   )r$   r\   r0   kindrP   rQ   rT   rN   )r=   otherop)operswapped_operr   r   _compare  s    

z&Column._make_compare.<locals>._comparer   )r   r   r   )r   r   r   _make_compare  s    zColumn._make_comparer   r   r   r   r   r   c             C   sd   | j jdkr(tj| |d|d}|||< n"tj|| j d}tj| |||d}|| j}||  |S )a  
        Insert values before the given indices in the column and return
        a new `~astropy.table.Column` object.

        Parameters
        ----------
        obj : int, slice or sequence of ints
            Object that defines the index or indices before which ``values`` is
            inserted.
        values : array_like
            Value(s) to insert.  If the type of ``values`` is different
            from that of quantity, ``values`` is converted to the matching type.
            ``values`` should be shaped so that it can be broadcast appropriately
        axis : int, optional
            Axis along which to insert ``values``.  If ``axis`` is None then
            the column array is flattened before insertion.  Default is 0,
            which will insert a row.

        Returns
        -------
        out : `~astropy.table.Column`
            A copy of column with ``values`` and ``mask`` inserted.  Note that the
            insertion does not occur in-place: a new column is returned.
        ON)axis)r0   )r0   r   r1   insertr9   r4   r<   r[   )r=   r7   valuesr   rN   r_   r   r   r   r     s    

zColumn.insert)NNNr   r   NNNNFT)F)r   ) r   r   r   r   r8   r   r   r   r   r   r   r   r@   r   r   r   r   r   r   r   r   r%   rG   rD   r#   r   r   rt   r   r   rO   r   r   r   )r<   r   r     s<   ?   
 #
)r   c                   sF   e Zd ZdZejdhB ZdZejj	Z
d	 fdd	Z fddZ  ZS )
MaskedColumnInfoa  
    Container for meta information like name, description, format.

    This is required when the object is used as a mixin column within a table,
    but can be used as a general way to store meta information.  In this case
    it just adds the ``mask_val`` attribute.
    serialize_methodrN   Fc                s$   t  | |r ddddd| _d S )N
null_value	data_mask)ZfitsZecsvZhdf5N)rm   __init__r   )r=   Zbound)r<   r   r   r     s    zMaskedColumnInfo.__init__c                sl   t   }| j}| j| j }|dkrVt|jrh|jj|d< |j|d< |  j	d7  _	n|dkr`nt
d|S )Nr   rN   r   )rN   r   r   z;serialize method must be either "data_mask" or "null_value")rm   _represent_as_dictZ_parentr   Z_serialize_contextr1   r:   r   rN   Z_represent_as_dict_attrsr;   )r=   r_   r+   method)r<   r   r   r   (  s    

z#MaskedColumnInfo._represent_as_dict)F)r   r   r   r   rA   rJ   Z_represent_as_dict_primary_datar1   r   r   Zmask_valr   r   r   r   r   )r<   r   r     s   r   c                   s   e Zd ZdZe ZdddZed	d
 Zej	dd
 Zedd Z
d fdd	ZdddZdd Zdd ZejZejZejZejZejZejZ  ZS )r\   a
  Define a masked data column for use in a Table object.

    Parameters
    ----------
    data : list, ndarray or None
        Column data values
    name : str
        Column name and key for reference within Table
    mask : list, ndarray or None
        Boolean mask for which True indicates missing or invalid data
    fill_value : float, int, str or None
        Value used when filling masked column elements
    dtype : numpy.dtype compatible value
        Data type for column
    shape : tuple or ()
        Dimensions of a single row element in the column data
    length : int or 0
        Number of row elements in column data
    description : str or None
        Full description of column
    unit : str or None
        Physical unit
    format : str or None or function or callable
        Format string for outputting column values.  This can be an
        "old-style" (``format % value``) or "new-style" (`str.format`)
        format specification string or a function or any callable object that
        accepts a single value and returns a string.
    meta : dict-like or None
        Meta-data associated with the column

    Examples
    --------
    A MaskedColumn is similar to a Column except that it includes ``mask`` and
    ``fill_value`` attributes.  It can be created in two different ways:

    - Provide a ``data`` value but not ``shape`` or ``length`` (which are
      inferred from the data).

      Examples::

        col = MaskedColumn(data=[1, 2], name='name')
        col = MaskedColumn(data=[1, 2], name='name', mask=[True, False])
        col = MaskedColumn(data=[1, 2], name='name', dtype=float, fill_value=99)

      The ``mask`` argument will be cast as a boolean array and specifies
      which elements are considered to be missing or invalid.

      The ``dtype`` argument can be any value which is an acceptable
      fixed-size data-type initializer for the numpy.dtype() method.  See
      `<https://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html>`_.
      Examples include:

      - Python non-string type (float, int, bool)
      - Numpy non-string type (e.g. np.float32, np.int64, np.bool\_)
      - Numpy.dtype array-protocol type strings (e.g. 'i4', 'f8', 'S15')

      If no ``dtype`` value is provide then the type is inferred using
      ``np.array(data)``.  When ``data`` is provided then the ``shape``
      and ``length`` arguments are ignored.

    - Provide ``length`` and optionally ``shape``, but not ``data``

      Examples::

        col = MaskedColumn(name='name', length=5)
        col = MaskedColumn(name='name', dtype=int, length=10, shape=(3,4))

      The default ``dtype`` is ``np.float64``.  The ``shape`` argument is the
      array shape of a single cell in the column.
    Nr   r   FTc             C   s   |d kr,t |dd}|dk	rFtj||d}n|tjjkr>d}nt|}t||||||	|
||||d}tjj| ||d}|d krt |dd d k	r|j	
|j}||_d |_x|jD ]}||| qW |S )Nr   F)r#   )
r0   r6   rF   rG   rD   r   rE   rC   r#   r,   )rN   r   
fill_value)rT   r1   rM   r   Znomaskr   r%   rd   r8   r0   r   r   r'   r(   r*   )r5   rN   rG   r   r   r0   r6   rF   rE   rD   r   rC   r#   r,   rU   r=   r-   r   r   r   r8     s$    
zMaskedColumn.__new__c             C   s   |   S )N)Zget_fill_value)r=   r   r   r   r     s    zMaskedColumn.fill_valuec             C   s   d| _ | | dS )zSet fill value both in the masked column view and in the parent table
        if it exists.  Setting one or the other alone doesn't work.N)Z_fill_valueZset_fill_value)r=   r?   r   r   r   r     s    c             C   s   |  tj}| j|_|S )N)r4   r   rd   r   )r=   r_   r   r   r   rN     s    zMaskedColumn.datac                sV   |dkr| j }t |}| jdk	r,| jjnt}|| j|| j| j| jt	| j
d}|S )a  Return a copy of self, with masked values filled with a given value.

        Parameters
        ----------
        fill_value : scalar; optional
            The value to use for invalid entries (`None` by default).  If
            `None`, the ``fill_value`` attribute of the array is used
            instead.

        Returns
        -------
        filled_column : Column
            A copy of ``self`` with masked entries replaced by `fill_value`
            (be it the function argument or the attribute of ``self``).
        N)rG   rN   rD   r   rE   rC   )r   rm   filledr'   r   rG   rD   r   rE   r   rC   )r=   r   rN   Z
column_clsr_   )r<   r   r   r     s    zMaskedColumn.filledc       
      C   s   | j }| jjdkr0tj|j |d|d}|||< n$tj|| jd}tj|j |||d}|dkr~| jjdkrnd}ntj|jtd}tj|j	|||d}tj
j||dd}|| j}	d|	_g |	_|	|  | j|	_|	S )a  
        Insert values along the given axis before the given indices and return
        a new `~astropy.table.MaskedColumn` object.

        Parameters
        ----------
        obj : int, slice or sequence of ints
            Object that defines the index or indices before which ``values`` is
            inserted.
        values : array_like
            Value(s) to insert.  If the type of ``values`` is different
            from that of quantity, ``values`` is converted to the matching type.
            ``values`` should be shaped so that it can be broadcast appropriately
        mask : boolean array_like
            Mask value(s) to insert.  If not supplied then False is used.
        axis : int, optional
            Axis along which to insert ``values``.  If ``axis`` is None then
            the column array is flattened before insertion.  Default is 0,
            which will insert a row.

        Returns
        -------
        out : `~astropy.table.MaskedColumn`
            A copy of column with ``values`` and ``mask`` inserted.  Note that the
            insertion does not occur in-place: a new masked column is returned.
        r   N)r   )r0   F)r   r#   )rN   r0   r   r1   r   r9   r2   r6   r3   r   r   rM   r4   r<   r'   r(   rn   r   )
r=   r7   r   r   r   Zself_maZnew_dataZnew_maskZnew_mar_   r   r   r   r     s$    

zMaskedColumn.insertc             C   s2   |j | j kr.d |_|j| jkr$g |_||  |S )N)r<   r'   r(   rn   )r=   r_   r   r   r   _copy_attrs_slice2  s    
zMaskedColumn._copy_attrs_slicec          	   C   s   | j jdkr| |}t| j jtjrJtjj|| j jd}| 	|
d | j||t|  td krxtj| || n0t " tdt tj| || W d Q R X d S )NrL   )r0   r    ignore)r0   rP   rQ   r   r   r1   r   r   r   r   r   r&   r   r   r   rd   r@   r   catch_warningssimplefilter)r=   r-   r   r   r   r   r@   =  s    

zMaskedColumn.__setitem__)NNNNNr   r   NNNNFT)N)Nr   )r   r   r   r   r   r&   r8   r   r   r   rN   r   r   r   r@   r%   rG   r#   r   r   rt   r   r   r   r   )r<   r   r\   A  s&   F   
.
9r\   )T);r   rW   rer#   r   Znumpyr1   r   Znumpy.ma.corer   ImportErrorZastropy.unitsr   r   Zastropy.utils.consoler   Zastropy.utils.metadatar   Zastropy.utils.data_infor	   r
   Zastropy.utils.miscr   r    r   r   Znp_utilsr   Z_column_mixinsr   r   ZTableFormatterr   UserWarningr   r   r"   setZgreaterZgreater_equalZlessZ
less_equalZ	not_equalr   ZisfiniteZisinfZisnanZsignZsignbitrp   r.   rV   r/   rA   r%   r   r   rd   r\   r   r   r   r   <module>   sN   

*)    D  =