
    5i+                     >   d Z ddlmZmZmZmZ ddl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ZddlZddlmZ ddlmZ ddl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mZ  e  e       d      Z!dZ"dZ#ejH                  rdZ#dZ%dZ&dZ'd Z(d Z)ddZ* G d de      Z+y)zW
DXFile Handler
**************

This remote file handler is a Python file-like object.
    )print_functionunicode_literalsdivisionabsolute_importN)BytesIO)Lock)	cpu_count   )DXDataObject   )DXFileErrorDXIncompleteReadsError)warn)object_exists_in_project)
md5_hasher
basestring   i   i   i   i  @ <   i,  c                     | j                         D ]F  \  }}t        |t              st        d|d      t        |t              r6t        d|d|d       | S )NzExpected key z of headers to be a stringzExpected value z! of headers (associated with key z) to be a string)items
isinstancer   
ValueError)headerskeyvalues      v/home/marpiech/ifpan-abm-pgxpred/analysis/marpiech-gwas-test/venv/lib/python3.12/site-packages/dxpy/bindings/dxfile.py_validate_headersr   6   s[    mmo -
U#z*CQRR%, %s, - -	- N    c                    | }t        d      }t        |dz        }t        |dz        }t        |dz        }||k  rdj                  ||dk7  rd      S d      S ||cxk  r|k  rn ndj                  ||z        S ||cxk  r|k  rn ndj                  ||z        S ||cxk  r|k  rn ndj                  ||z        S ||k  rd	j                  ||z        S y
)z'Returns the file size in readable form.i   z{0} {1}r
   bytesbytez{0:.2f} KiBz{0:.2f} MiBz{0:.2f} GiBz{0:.2f} TiBN)floatformat)	num_bytesBKBMBGBTBs         r   _readable_part_sizer*   @   s    A	tB	rDy	B	rDy	B	rDy	B2va1f7AA&AA	q2##AbD))	q2##AbD))	q2##AbD))	q##AbD)) 
r   c           
         |d   }|d   }|d   }|d   }|(||kD  r#t        dj                  t        |                  |}|4t        |t	        t        j                  t        |      |z                    }|}	||	k  sJ |r|t        j                  z  dk7  r'|t        j                  |t        j                  z  z
  z  }|	t        j                  z  dk7  r|	|	t        j                  z  z  }	| | t        j                  z  z
  } n| } | }
t        |
|      }
t        |
|	      }
||
|z  |k  rt        d      |r!|
t        j                  z  dk7  rt        d      |
S )	NmaximumNumPartsminimumPartSizemaximumPartSizemaximumFileSizez"Size of file exceeds maximum of {}r   zDpart size would be too small to upload the requested number of bytesz&part size will not be accepted by mmap)r   r#   r*   maxintmathceilr"   mmapALLOCATIONGRANULARITYminAssertionError)buffer_size_hintfile_upload_paramsexpected_file_sizefile_is_mmapdmax_num_partsmin_part_sizemax_part_sizemax_file_sizemin_buffer_sizemax_buffer_sizebuffer_sizes              r   _get_write_buf_sizerC   T   s   &'89M&'89M&'89M&'89M%*<}*L>EEFYZgFhijj#O% os499UCU=VYf=f3g/hi#Oo--- T7771<t99OdNhNh<hhhOT7771<1K1KKKO+.>A[A[.[[+
 #Kk?3Kk?3K%;+FI[+[cddt'A'AAQFEFFr   c                      e Zd ZdZdZ eej                  j                        Z	 eej                  j                        Z eej                  j                        Z eej                  j                        Z eej                  j                         Z eej                  j$                        Z eej                  j(                        Z eej                  j,                        Z eej                  j0                        Z eej                  j4                        Z eej                  j8                        Z eej                  j<                        Ze Z!ejD                  jG                  e!      Z$dZ%e&d        Z'ddde(e(ddfdZ)d"d	Z*d
 Z+d Z,d Z-d Z.e/Z/e/Z0d"dZ1e2jf                  fdZ4d Z5d#dZ6d Z7d Z8d#dZ9d#dZ:d Z;d$dZ<d%dZ=d&dZ>d Z?d'dZ@	 	 d(dZAd$dZBd)dZCd)dZDd$d ZEd$d!ZFy)*DXFileae  Remote file object handler.

    :param dxid: Object ID
    :type dxid: string
    :param project: Project ID
    :type project: string
    :param mode: One of "r", "w", or "a" for read, write, and append modes, respectively.
                 Use "b" for binary mode. For example, "rb" means open a file for reading
                 in binary mode.
    :type mode: string

    .. note:: The attribute values below are current as of the last time
              :meth:`~dxpy.bindings.DXDataObject.describe` was run.
              (Access to any of the below attributes causes
              :meth:`~dxpy.bindings.DXDataObject.describe` to be called
              if it has never been called before.)

    .. py:attribute:: media

       String containing the Internet Media Type (also known as MIME type
       or Content-type) of the file.

    .. automethod:: _new

    file)max_workersNO_PROJECT_HINTc                     t        d       y)z+

        .. deprecated:: 0.191.0

        z&set_http_threadpool_size is deprecatedN)print)clsnum_threadss     r   set_http_threadpool_sizezDXFile.set_http_threadpool_size   s     	67r   NFc                    t        j                  | ||       d| _        |d| _        n6d|v rd| _        |j	                  dd      }|dvrt        d      |d	k(  | _        t               | _        t               | _        || _	        d| _
        || _        || _        || _        d
\  | _        | _        | _        t#               | _        d\  | _        | _        t+               | _        d| _        d| _        d| _        d| _        d| _        y)a  
        :param dxid: Object ID
        :type dxid: string
        :param project: Project ID
        :type project: string
        :param mode: One of "r", "w", or "a" for read, write, and append
            modes, respectively. Add "b" for binary mode.
        :type mode: string
        :param read_buffer_size: size of read buffer in bytes
        :type read_buffer_size: int
        :param write_buffer_size: hint for size of write buffer in
            bytes. A lower or higher value may be used depending on
            region-specific parameters and on the expected file size.
        :type write_buffer_size: int
        :param expected_file_size: size of data that will be written, if
            known
        :type expected_file_size: int
        :param file_is_mmapd: True if input file is mmap'd (if so, the
            write buffer size will be constrained to be a multiple of
            the allocation granularity)
        :type file_is_mmapd: bool
        )dxidprojectFNTb )rwaz[mode must be one of 'r', 'w', or 'a'. Character 'b' may be used in combination (e.g. 'wb').rT   NNNNNr   r
   )r   __init___binary_mode_close_on_exitreplacer   r   	_read_buf
_write_buf_read_bufsize_write_bufsize_write_buffer_size_hint_expected_file_size_file_is_mmapd_download_url_download_url_headers_download_url_expiresr   _url_download_mutex_request_iterator_response_iteratorset_http_threadpool_futures_pos_file_length	_cur_part_num_uploaded_parts_exists_in_proj)selfrO   rP   moderead_buffer_sizewrite_buffer_sizer:   r;   s           r   rX   zDXFile.__init__   s   0 	dw? "<"&Dd{$(!||C,?* !~#'3;D !)- #'8$#5 + VfRD68R $(6 :D7 7(+% 	 #$ #r   c                     |||d<   t        j                  j                  |fi |}| j                  |d   |d          y)aV  
        :param dx_hash: Standard hash populated in :func:`dxpy.bindings.DXDataObject.new()` containing attributes common to all data object classes.
        :type dx_hash: dict
        :param media_type: Internet Media Type
        :type media_type: string

        Creates a new remote file with media type *media_type*, if given.

        NmediaidrP   )dxpyapifile_newset_ids)rp   dx_hash
media_typekwargsresps        r   _newzDXFile._new  sD     !)GGxx  3F3T$Z!34r   c                     | S N rp   s    r   	__enter__zDXFile.__enter__  s    r   c                     | j                          | j                  r%| j                         dk(  r| j                          y y y )Nopen)flushrZ   
_get_stateclose)rp   typer   	tracebacks       r   __exit__zDXFile.__exit__  s3    

4??#4#>JJL $?r   c                    t        | d      sy| j                  j                         dkD  st        | j                        dkD  r7t        d       t        d       t        d       t        d       t        d       	 | j                  d	
       y# t        $ rB}t        d| j                         t        j                  t        j                            d}~ww xY w)a#  
        Exceptions raised here in the destructor are IGNORED by Python! We will try and flush data
        here just as a safety measure, but you should not rely on this to flush your data! We will
        be really grumpy and complain if we detect unflushed data here.

        Use a context manager or flush the object explicitly to avoid this.

        In addition, when this is triggered by interpreter shutdown, the thread pool is not
        available, and we will wait for the request queue forever. In this case, we must revert to
        synchronous, in-thread flushing. We don't know how to detect this condition, so we'll use
        that for all destructor events.

        Neither this nor context managers are compatible with kwargs pass-through (so e.g. no
        custom auth).
        r]   Nr   z=== WARNING! ===zCThere is still unflushed data in the destructor of a DXFile object!zcWe will attempt to flush it now, but if an error were to occur, we could not report it back to you.z@Your program could fail to flush the data but appear to succeed.zxInstead, please call flush() or close(), or use the context managed version (e.g., with open_dxfile(ID, mode='w') as f:)F)multithreadz@=== Exception occurred while flushing accumulated file data for )hasattrr]   telllenrj   r   r   	Exception_dxidr   print_exceptionsysexc_info)rp   es     r   __del__zDXFile.__del__  s      t\* ??!A%T-J-J)Ka)O#$VWvwST  L  M	JJ5J) 	Y]YcYcef%%s||~6	s   ;B 	C=CCc              #     K   d}| j                   rt        d      	 | j                  | j                        }|sn?||z  }|j	                  d      }t        t        |      dz
        D ]	  }||     |d   }]|r| y y w)NrR   z1Cannot read lines when file opened in binary mode
r
   )rY   r   readr^   splitranger   )rp   _buffermorepartsis        r   __iter__zDXFile.__iter__?  s     QRR99T//0DtOGMM$'E3u:>* Ah BiG  M s   B Bc                     | j                   | j                          t        j                  | ||       d| _        d| _        d| _        d| _        y)aK  
        :param dxid: Object ID
        :type dxid: string
        :param project: Project ID
        :type project: string

        Discards the currently stored ID and associates the handler with
        *dxid*. As a side effect, it also flushes the buffer for the
        previous file object if the buffer is nonempty.
        Nr   r
   )r   r   r   rz   rk   rl   rm   rn   )rp   rO   rP   s      r   rz   zDXFile.set_idsS  sI     ::!JJLT41 	 #$ r   c                    |t         j                  k(  rd}n}|t         j                  k(  r| j                  }n]|t         j                  k(  r?| j
                  dk(  r#| j                         }t        |d         | _        | j
                  }nt        d      | j                  }||z   | _        d}| j                  j                         }||k  r|||z
  kD  r9d}n6t        j                  j                  | j                        }||z
  ||z
  kD  rd}|r"| j                  j                  ||z
  |z          y||k(  ryt               | _	        d\  | _        | _        y)at  
        :param offset: Position in the file to seek to
        :type offset: integer

        Seeks to *offset* bytes from the beginning of the file.  This is a no-op if the file is open for writing.

        The position is computed from adding *offset* to a reference point; the reference point is selected by the
        *from_what* argument. A *from_what* value of 0 measures from the beginning of the file, 1 uses the current file
        position, and 2 uses the end of the file as the reference point. *from_what* can be omitted and defaults to 0,
        using the beginning of the file as the reference point.
        r   Nsizez$Invalid value supplied for from_whatFTrW   )osSEEK_SETSEEK_CURrk   SEEK_ENDrl   describer1   r   r\   r   rw   utilsstring_buffer_lengthseekr   rg   rh   )	rp   offset	from_whatreference_posdescorig_posin_buforig_buf_posbuf_lens	            r   r   zDXFile.seeki  s5    #M"++% IIM"++%  D(}}$'V$5! --MDEE99!F*	~~**,Hh//jj55dnnEG%(99 NNx 7& @Ax  %YDN>H;D"D$;r   c                     | j                   S )z
        Returns the current position of the file read cursor.

        Warning: Because of buffering semantics, this value will **not** be accurate when using the line iterator form
        (`for line in file`).
        )rk   r   s    r   r   zDXFile.tell  s     yyr   c                 p   | j                   j                         dkD  r~| j                   j                         }t               | _         |r  | j                  |fd| j
                  i| n | j                  || j
                  fi | | xj
                  dz  c_        t        | j                        dkD  rot        j                  j                  | j                         	 | j                  D ]%  }|j                         dk7  s|j                          	 t               | _        yy# t               | _        w xY w)z4
        Flushes the internal write buffer.
        r   indexr
   N)r]   r   getvaluer   _async_upload_part_requestrm   upload_partr   rj   rw   r   wait_for_all_futures	exceptionri   )rp   r   r}   datafutures        r   r   zDXFile.flush  s    ??!A%??++-D%iDO///UDNNUfU   t~~@@NNaNt,,-1JJ++D,I,IJ6";; 1F'')T1$..001 14- 2 14-s   "D$ D$ $D5c                    t        | j                        | j                  k\  rt        j                  j                  | j                        }|j                         d k7  r|j                         | j                  j                  |       t        | j                        | j                  k\  r | j                  j                  | j                  g|i |}| j                  j                  |       y r   )r   rj   _http_threadpool_sizerw   r   wait_for_a_futurer   remove_http_threadpoolsubmitr   add)rp   argsr}   r   s       r   r   z!DXFile._async_upload_part_request  s    $//0D4N4NNZZ11$2O2OPF!T)&&(())008	 $//0D4N4NN .&&--d.>.>PPP%%))&1r   c                     | j                   y t        j                  j                  | j	                         dddiifi |d   }|d   | _        t        | j                  || j                  | j                        | _         y )NfieldsfileUploadParametersTemptyLastPartAllowed)
r_   rw   rx   project_describeget_proj_id_empty_last_part_allowedrC   r`   ra   rb   )rp   r}   r9   s      r   _ensure_write_bufsizezDXFile._ensure_write_bufsize  s    *!XX66.56
 
 !	"
 );;Q(R%1$2N2N2D262J2J262E2EGr   c                 H    t        |t              sJ   j                  di   fd} j                  j	                         dk(  r! j
                  t        |      k(  r	 ||       y j
                   j                  j	                         z
  }t        |      |k  r j                  j                  |       y j                  j                  |d|         j                  j                         }t                _         ||         j                  ||d fi  y)  
        :param data: Data to be written
        :type data: str or mmap object
        :param multithread: If True, sends multiple write requests asynchronously
        :type multithread: boolean

        Writes the data *data* to the file.

        .. note::

            Writing to remote files is append-only. Using :meth:`seek`
            does not affect where the next :meth:`write` will occur.

        c                     r  j                   | fdj                  i n j                  | j                  fi  xj                  dz  c_        y )Nr   r
   )r   rm   r   )data_for_write_reqr}   r   rp   s    r   write_requestz%DXFile._write2.<locals>.write_request  sP    ///0Bc$..c\bc   !3T^^NvNNNaNr   r   Nr   )
r   r    r   r]   r   r_   r   writer   r   )rp   r   r   r}   r   remaining_space	temp_datas   ` ``   r   _write2zDXFile._write2  s     $&'&""",V,	  ??!Q&4+>+>#d)+K $--0D0D0FFt9'OO!!$'OO!!$'7"89002I%iDO)$ DJJtO,-88r   c                    t        |t              r|j                  d      }nxt        |t              rt	        |      }n\t        |t              r|}nIt        |t
        j
                        rt	        |      }n#t        dj                  t        |                  t        |t              sJ  | j                  |fd|i| y)r   utf-8z'Invalid type {} for write data argumentr   N)
r   strencode	bytearrayr    r4   r   r#   r   r   )rp   r   r   r}   bts        r   r   zDXFile.write  s    2 dC W%Bi(tBe$Bdii(tBGNNtTXzZ[["e$%$R;[;F;r   c                 8     | j                   dddhi|d   dk(  S )a  
        :returns: Whether the remote file is closed
        :rtype: boolean

        Returns :const:`True` if the remote file is closed and
        :const:`False` otherwise. Note that if it is not closed, it can
        be in either the "open" or "closing" states.
        r   stateclosedr   )r   rp   r}   s     r   r   zDXFile.closed<  s)     t}}8WI88AXMMr   c                 z    | j                   di |  | j                  di | | j                  dk(  r| j                  r	  | j                  di | d|v r|d= t        j                  j                  | j                  fi | |r | j                  di | yy# t
        j                  j                  $ r Y fw xY w)aJ  
        :param block: If True, this function blocks until the remote file has closed.
        :type block: boolean

        Attempts to close the file.

        .. note:: The remote file cannot be closed until all parts have
           been fully uploaded. An exception will be thrown if this is
           not the case.
        r   report_progress_fnNr   )r   r
   )r   r   rn   r   r   rw   
exceptionsInvalidStaterx   
file_closer   _wait_on_close)rp   blockr}   s      r   r   zDXFile.closeH  s     	

V 	#"",V,##q(T-J-J
   262  6)+,DJJ1&1D)&)  ??// s   B B:9B:c                 *     | j                   |fi | y)a+  
        :param timeout: Maximum amount of time to wait (in seconds) until the file is closed.
        :type timeout: integer
        :raises: :exc:`dxpy.exceptions.DXFileError` if the timeout is reached before the remote file has been closed

        Waits until the remote file is closed.
        N)r   )rp   timeoutr}   s      r   wait_on_closezDXFile.wait_on_closej  s     	G.v.r   c           
      T   
 t        |t              sJ i 
|t        |      
d<   t               }t	        |d      rZt	        |d      rN|j                         }	 |j                  t              }|r|j                  |       nn+|j                  |       n|j                  |       |j                         
d<   t        |      
d<   
 fd}	t        j                  |	|d	d	dt        dd
        xj                  dz  c_        |rt!        d       | | t        |             yy)a  
        :param data: Data to be uploaded in this part
        :type data: str or mmap object, bytes on python3
        :param index: Index of part to be uploaded; must be in [1, 10000]
        :type index: integer
        :param display_progress: Whether to print "." to stderr when done
        :type display_progress: boolean
        :param report_progress_fn: Optional: a function to call that takes in two arguments (self, # bytes transmitted)
        :type report_progress_fn: function or None
        :raises: :exc:`dxpy.exceptions.DXFileError` if *index* is given and is not in the correct range, :exc:`urllib3.exceptions.HTTPError` if upload fails

        Uploads the data in *data* as part number *index* for the
        associated file. If no value for *index* is given, *index*
        defaults to 1. This probably only makes sense if this is the
        only part to be uploaded.
        Nr   r   r   Tmd5r   c                     dvrt         j                  d<   nd   dkD  rdxx   dz  cc<   dvr	t        d<   t        j                  j                  j
                  fi } | d   }|t        | j                  di             fS )Nmax_retriesr   r
   r   urlr   )rw   DEFAULT_RETRIESFILE_REQUEST_TIMEOUTrx   file_uploadr   r   get)r~   r   r}   	req_inputrp   s     r   get_upload_url_and_headersz6DXFile.upload_part.<locals>.get_upload_url_and_headers  s     F*(,(<(<}%&*}%*%&$8y!88''

IHHDu+C)$((9b*ABBBr   FPUT)jsonify_dataprepend_srvalways_retryr   authmethodr
   .)r   r    r1   r   r   r   r   MD5_READ_CHUNK_SIZEupdater   	hexdigestr   rw   DXHTTPRequest#PART_UPLOAD_REQUEST_TIMEOUT_SECONDSrn   r   )rp   r   r   display_progressr   r}   r   rewind_input_buffer_offset
bytes_readr   r   s   `    `    @r   r   zDXFile.upload_partt  s   " $&'&	!$UIgl4 WT6%:)-&!YY':;
JJz*  II01JJt==?	%I	&	C& 	5(-',(,#F $"'	) 	  A% I)tSY/ *r   c                 (     | j                   di | y )Nr   )_wait_until_parts_uploadedr   s     r   wait_until_parts_uploadedz DXFile.wait_until_parts_uploaded  s    '''1&1r   c                    | j                   5  | j                  "| j                  t        j                         k  rGd|i}|||d<   |||d<   |@dt        j
                  vr.| j                         }|rt        | j                         |      r|}||t        j                  ur||d<   dt        j
                  v rLt        t        j
                  d   d      5 }|$|t        j                  k7  r|j                  |       ddd       d	|vr	t        |d	<   t        j                  j                   | j"                  |fi |}	|	d
   | _        t%        |	j'                  di             | _        |r|	d   dz  dz
  | _        nd| _        | j                  }
t+        j*                  | j(                        }ddd       |
|fS # 1 sw Y   xY w# 1 sw Y   
fS xY w)a  
        :param duration: number of seconds for which the generated URL will be
            valid, should only be specified when preauthenticated is True
        :type duration: int
        :param preauthenticated: if True, generates a 'preauthenticated'
            download URL, which embeds authentication info in the URL and does
            not require additional headers
        :type preauthenticated: bool
        :param filename: desired filename of the downloaded file
        :type filename: str
        :param project: ID of a project containing the file (the download URL
            will be associated with this project, and this may affect which
            billing account is billed for this download).
            If no project is specified, an attempt will be made to verify if the file is
            in the project from the DXFile handler (as specified by the user or
            the current project stored in dxpy.WORKSPACE_ID). Otherwise, no hint is supplied.
            This fall back behavior does not happen inside a job environment.
            A non preauthenticated URL is only valid as long as the user has
            access to that project and the project contains that file.
        :type project: str
        :returns: download URL and dict containing HTTP headers to be supplied
            with the request
        :rtype: tuple (str, dict)
        :raises: :exc:`~dxpy.exceptions.ResourceNotFound` if a project context was
            given and the file was not found in that project context.
        :raises: :exc:`~dxpy.exceptions.ResourceNotFound` if no project context was
            given and the file was not found in any projects.

        Obtains a URL that can be used to directly download the associated
        file.

        Npreauthenticateddurationfilename	DX_JOB_IDrP   _DX_DUMP_BILLED_PROJECTrT   r   r   r   expiresi  r   l    L" )rf   rc   re   timer   environr   r   get_idrE   rH   r   r   r   rw   rx   file_downloadr   r   r   rd   copy)rp   r  r  r  rP   r}   r   project_from_handlerfdr~   retval_download_urlretval_download_url_headerss               r   get_download_urlzDXFile.get_download_url  s   B %% 8	P!!)T-G-G$))+-U*,<=''/D$''/D$ ?{"**'D+/+;+;+=(+0HXl0m"6&7&:P:P+P&-DO -

:bjj)BCSI .R".7f>T>T3THHW-. F*(<F9%xx--djj$I&I%)%["->txx	SU?V-W*#15i1E1JD.1<D. #'"4"4*.))D4N4N*O'q8	Pt #$???9. .=8	Pt #$???s%   CG'F:?B/G:G	?GGc           
   +     K   | j                   | j                  d k(  r% | j                  di |}t        |d         | _        |d k(  r| j                  }|| j                  kD  rt	        d      dfd	} |||      D ]Q  \  }}	 | j
                  dd|i|\  }
}t        j                  |
||t        |	| j                  dz
        t        gi f S y w)Nr   zInvalid end_posc              3      K   | }t        |	      }d}||k  rHt        ||z   dz
  |      }||f ||z  }|	k  r||z  |dz
  k(  rt        ||z  	      }|dz  }||k  rGy y w)Nr   r
   )r6   )
	start_posend_posinit_chunk_sizerampnum_requests_between_rampcur_chunk_startcur_chunk_sizer   cur_chunk_endlimit_chunk_sizes
            r   chunk_rangesz4DXFile._generate_read_requests.<locals>.chunk_ranges2  s     'O 2BCNA!G+ #On$Dq$H' R%}44>1!$44=V9V[twx[x9y%($)>@P%QNQ "G+s   AA" A"rP   r
   r   )i   r      )
r^   rl   r   r1   r   r  rw   _dxhttp_read_ranger6   r   )rp   r  r  rP   r&  r}   r   r'  chunk_start_poschunk_end_posr   r   s       `       r   _generate_read_requestszDXFile._generate_read_requests"  s      ##11$ 4==*6*D #DL 1Dd?''GT&&&/00
	 /;9g.N 	F*O]0400KKFKLC))C/3}^b^o^ors^sKt,@,BCEF F	Fs   CCc                     | j                   ;t        j                  j                  | j                  | j
                  |      | _         	 t        | j                         S #  d | _         d | _         xY w)N)do_first_task_sequentially)rh   rw   r   response_iteratorrg   r   next)rp   get_first_chunk_sequentiallys     r   _next_response_contentzDXFile._next_response_contentD  sr    ""*&*jj&B&B&&%%+G 'C 'D#
	//00	 '+D#%)D"s   	A A/c                    | j                   dk(  r8 | j                  di |}|d   dk7  rt        d      t        |d         | _         | j                   dkD  xr! | j                  dk(  xr t
        j                  }| j                  | j                   k(  ry|dk(  s|| j                   | j                  z
  kD  r| j                   | j                  z
  }| j                  }t
        j                  j                  |      |j                         z
  }||k  r&| xj                  |z  c_        |j                  |      S |j                         }	| j                  }
|j                  dt        j                         | xj                  |z  c_        | j                  |
|z   k  r|
|z   | j                  z
  }| j                  $ | j                   d| j                  |d	|| _        | j%                  |
      }t'        |      |k  r0|j)                  |       | xj                  t'        |      z  c_        nq|j)                  |d|        | xj                  |z  c_        t+               | _        | j                  j)                  ||d        | j                  j                  d       | j                  |
|z   k  r|j                  |	       |j                         S )a  
        :param length: Maximum number of bytes to be read
        :type length: integer
        :param project: project to use as context for this download (may affect
            which billing account is billed for this download). If specified,
            must be a project in which this file exists. If not specified, the
            project ID specified in the handler is used for the download, IF it
            contains this file. If set to DXFile.NO_PROJECT_HINT, no project ID
            is supplied for the download, even if the handler specifies a
            project ID.
        :type project: str or None
        :rtype: string
        :raises: :exc:`~dxpy.exceptions.ResourceNotFound` if *project* is supplied
           and it does not contain this file

        Returns the next *length* bytes, or all the bytes until the end of file
        (if no *length* is given or there are fewer than *length* bytes left in
        the file).

        .. note:: After the first call to read(), the project arg and
           passthrough kwargs are not respected while using the same response
           iterator (i.e. until next seek).

        Nr   r   z5Cannot read from file until it is in the closed stater   i   r   r   )r  rP   )r1  r   )rl   r   r   r1   rk   rw   JOB_IDr\   r   r   r   r   r   r   r   rh   r,  rg   r2  r   r   r   )rp   lengthuse_compressionrP   r}   r   r1  bufbuf_remaining_bytesr   orig_file_posremaining_lencontents                r   _read2zDXFile._read2U  se   2 $ 4==*6*DG}(!"YZZ #DL 1D )-(9(9J(F(i499XY>(i^b^i^i$99)))T>Vd&7&7$))&CC&&2Fnn"jj==cBSXXZO((III88F##88:L IIMHHQ$II,,I))mf44 - 6 B**2-IT-I-I .H"&))W.H@F.HD* 55So5pw<-/IIg&IIW-IIIgn}56II.I%,YDNNN(()@ANN''*# ))mf44$ HH\"88:r   c                 B   |I| j                   =| j                         -t        | j                         | j                               | _         || j                   r| j                         } | j                  d|||d|}| j
                  du r|S |j                  d      S )N)r5  r6  rP   Tr   r   )ro   r   r   r  r<  rY   decode)rp   r5  r6  rP   r}   r   s         r   r   zDXFile.read  s    ?t33;@P@P@R@^#;DKKM4K[K[K]#^D ?t33&&(Gt{{e&/SZe^de$K{{7##r   c                     t         j                  j                  | j                         | j	                         g|d       y)a.  
        :param all_copies: Force the transition of files into the archived state. Requesting user must be the ADMIN of the project billTo org. 
            If true, archive all the copies of files in projects with the same billTo org.
        :type all_copies: boolean
        :raises: :exc:`~dxpy.exceptions.InvalidState` if the file is not in a live state
        :raises: :exc:`~dxpy.exceptions.PermissionDenied` if the requesting user does not have CONTRIBUTE access or
            is not an ADMIN of the project billTo org with allCopies=True.
        )files	allCopiesN)rw   rx   project_archiver   r  )rp   
all_copiess     r   archivezDXFile.archive  s/     	  !1!1!3]g5hir   c                     t         j                  j                  | j                         | j	                         g|d       y)ao  
        :param dry_run:  If true, only display the output of the API call without executing the unarchival
        :type dry_run: boolean
        :raises: :exc:`~dxpy.exceptions.InvalidState` if the file is not in a closed or archived state
        :raises: :exc:`~dxpy.exceptions.PermissionDenied` if the requesting user does not have CONTRIBUTE access    
        )r@  dryRunN)rw   rx   project_unarchiver   r  )rp   dry_runs     r   	unarchivezDXFile.unarchive  s/     	""4#3#3#5$++-\c7der   r   )TF)i:	 )NFN)NFNN)r   NNNrV   )G__name__
__module____qualname____doc___classstaticmethodrw   rx   file_describe	_describefile_add_types
_add_typesfile_remove_types_remove_typesfile_get_details_get_detailsfile_set_details_set_detailsfile_set_visibility_set_visibilityfile_rename_renamefile_set_properties_set_propertiesfile_add_tags	_add_tagsfile_remove_tags_remove_tagsr   _closefile_list_projects_list_projectsDXFILE_HTTP_THREADSr   r   get_futures_threadpoolr   rH   classmethodrM   DEFAULT_BUFFER_SIZErX   r   r   r   r   r   r0  __next__rz   r   r   r   r   r   r   r   r   r   r   r   r   r   r
  r  r,  r2  r<  r   rD  rI  r   r   r   rE   rE      s   4 FTXX334Idhh556J !;!;<M 9 9:L 9 9:L"488#?#?@O488//0G"488#?#?@OTXX334I 9 9:L$((--.F!$(("="=>N/zz88EZ8['O8 8 !$TL_#64_dE$N5"
 D" DH%, &([[ 9Iv602G79r$<L
N *D/K0Z2[@z JN15 FD"L\$	jfr   rE   rJ  ),rN  
__future__r   r   r   r   r   r   r   r  r  ior   r2   r4   	threadingr   multiprocessingr	   rw   rR   r   r   r   r   r   r   utils.resolverr   compatr   r   r6   rh  MIN_BUFFER_SIZErk  r4  r   r   r  r   r*   rC   rE   r   r   r   <module>rt     s   " S R % % %     %   <  5 + )+q) " ;; '!  &) #*(.b}f\ }fr   