U
    d$                     @   sl   d Z ddd Zddd ZdgZddlZddlZddlZddlZd	d
lm	Z	 d	dl
mZ G dd dZdS )zDBF header definition.

TODO:
  - handle encoding of the character fields
    (encoding information stored in the DBF header)

z$Revision: 1.6 $   z$Date: 2010/09/16 05:06:39 $   	DbfHeader    N   )fields)getDatec                   @   s   e Zd ZdZdZd$ddZd	d
 ZeeZdd ZeeZe	dd Z
e	dd Ze	dd Zdd Ze	dd e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 )%r   a|  Dbf header definition.

    For more information about dbf header format visit
    `http://www.clicketyclick.dk/databases/xbase/format/dbf.html#DBF_STRUCT`

    Examples:
        Create an empty dbf header and add some field definitions:
            dbfh = DbfHeader()
            dbfh.addField(("name", "C", 10))
            dbfh.addField(("date", "D"))
            dbfh.addField(DbfNumericFieldDef("price", 5, 2))
        Create a dbf header with field definitions:
            dbfh = DbfHeader([
                ("name", "C", 10),
                ("date", "D"),
                DbfNumericFieldDef("price", 5, 2),
            ])

    )	signaturer   
lastUpdaterecordLengthrecordCountheaderLengthchanged_ignore_errorsNr      Fc                 C   sR   || _ |dkrg | _n
t|| _t|| _|| _|| _|| _|| _t	| j| _
dS )a  Initialize instance.

        Arguments:
            fields:
                a list of field definitions;
            recordLength:
                size of the records;
            headerLength:
                size of the header;
            recordCount:
                number of records stored in DBF;
            signature:
                version number (aka signature). using 0x03 as a default meaning
                "File without DBT". for more information about this field visit
                ``http://www.clicketyclick.dk/databases/xbase/format/dbf.html#DBF_NOTE_1_TARGET``
            lastUpdate:
                date of the DBF's update. this could be a string ('yymmdd' or
                'yyyymmdd'), timestamp (int or float), datetime/date value,
                a sequence (assuming (yyyy, mm, dd, ...)) or an object having
                callable ``ticks`` field.
            ignoreErrors:
                error processing mode for DBF fields (boolean)

        N)r	   r   listr   r
   r   r   r   ignoreErrorsboolr   )selfr   r   r   r   r	   r
   r    r   @/tmp/pip-unpacked-wheel-_3ph8cfy/tablib/packages/dbfpy/header.py__init__9   s    

zDbfHeader.__init__c                 C   s   |  tt|S )z.Return header instance from the string object.)
fromStreamioStringIOstr)clsstringr   r   r   
fromStringb   s    zDbfHeader.fromStringc              
   C   s   | d |d}t|tkr.t|t }|}td|dd \}}}|d }|dk rf|d7 }n|d	7 }| d
||||d ||d |d f}d}	|d}|dkr||d7 }t	|d 
||	}
||
 |
j}	|d}q|S )z%Return header object from the stream.r       z<I2H      r   P   i  l  N   r         r   )seekreadtypebytessysgetfilesystemencodingstructunpackr   	lookupForr   	_addFieldend)r   streamZfirst_32_dataZ_cntZ_hdrLenZ_recLenZ_year_obj_pos_fldr   r   r   r   h   s,    




zDbfHeader.fromStreamc                 C   s   | j jS N)r
   yearr   r   r   r   <lambda>       zDbfHeader.<lambda>c                 C   s   | j jS r7   )r
   monthr9   r   r   r   r:      r;   c                 C   s   | j jS r7   )r
   dayr9   r   r   r   r:      r;   c                 C   s$   t | | _}| jD ]
}||_qdS )z1Update `ignoreErrors` flag on self and all fieldsN)r   r   r   r   )r   value_fieldr   r   r   r      s    
zDbfHeader.ignoreErrorsc                 C   s   | j S r7   )r   r9   r   r   r   r:      r;   zError processing mode for DBF field value conversion

        if set, failing field value conversion will return
        ``INVALID_VALUE`` instead of raising conversion error.

        )docc                 C   s:   d| j | j| j| j| jf }|ddd | jD 7 }|S )NzVersion (signature): 0x%02x
        Last update: %s
      Header length: %d
      Record length: %d
       Record count: %d
 FieldName Type Len Dec

c                 S   s   g | ]}d |   qS )z%10s %4s %3s %3s)Z	fieldInfo.0r6   r   r   r   
<listcomp>   s     z&DbfHeader.__repr__.<locals>.<listcomp>)r	   r
   r   r   r   joinr   )r   Z_rvr   r   r   __repr__   s     	zDbfHeader.__repr__c                 G   s   g }d}|D ]b}t |tjr"|}n8t|d dd \}}}}	t|}
|
|||	| jd}||j7 }|| q|  j|7  _|S )ah  Internal variant of the `addField` method.

        This method doesn't set `self.changed` field to True.

        Return value is a length of the appended records.
        Note: this method doesn't modify ``recordLength`` and
        ``headerLength`` fields. Use `addField` instead of this
        method if you don't exactly know what you're doing.

        r   )NNNNNr    )r   )
isinstancer   ZDbfFieldDeftupler/   r   lengthappend)r   defsZ_defsZ_recordLengthZ_defr4   _name_type_lenZ_dec_clsr   r   r   r0      s    

zDbfHeader._addFieldc                 G   sN   | j }|  j | j| 7  _ |s,|  j d7  _ ddt| j  d | _d| _dS )a  Add field definition to the header.

        Examples:
            dbfh.addField(
                ("name", "C", 20),
                dbf.DbfCharacterFieldDef("surname", 20),
                dbf.DbfDateFieldDef("birthdate"),
                ("member", "L"),
            )
            dbfh.addField(("price", "N", 5, 2))
            dbfh.addField(dbf.DbfNumericFieldDef("origprice", 5, 2))

        r   r   TN)r   r0   lenr   r   r   )r   rK   Z_oldLenr   r   r   addField   s    zDbfHeader.addFieldc                 C   sV   | d ||   dd | jD }|d|t  |d d| _dS )z&Encode and write header to the stream.r   c                 S   s   g | ]}|  qS r   )toStringrB   r   r   r   rD      s     z#DbfHeader.write.<locals>.<listcomp> r%   FN)	r'   writerR   r   rE   encoder+   r,   r   )r   r2   r   r   r   r   rT      s    

zDbfHeader.writec              
   C   s.   t d| j| jd | j| j| j| j| jd S )z4Returned 32 chars length string with encoded header.z<4BI2Hr#   s                       )	r-   packr	   r8   r<   r=   r   r   r   r9   r   r   r   rR      s    zDbfHeader.toStringc                 C   s   t j | _dS )z9Update ``self.lastUpdate`` field with current date value.N)datetimedatetodayr
   r9   r   r   r   setCurrentDate   s    zDbfHeader.setCurrentDatec                 C   sH   t |tr:| }| jD ]}|j|kr|  S qt|n
| j| S dS )z9Return a field definition by numeric index or name stringN)rG   r   upperr   nameKeyError)r   itemrL   r?   r   r   r   __getitem__  s    




zDbfHeader.__getitem__)Nr   r   r   r   NF)__name__
__module____qualname____doc__	__slots__r   r   classmethodr   propertyr8   r<   r=   r   rF   r0   rQ   rT   rR   rZ   r_   r   r   r   r   r      s8           
) 	)rc   __version____date____all__rW   r   r-   r+   rS   r   utilsr   r   r   r   r   r   <module>   s   