U
    ߦwhL                     @   s  U d Z dZd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
m
Z
mZ ddlmZ ddlmZ dd	lmZmZmZmZmZmZmZmZmZ ejdd
 dkrddlmZ nddlmZ ejdkrddlmZ nddlmZ ddlmZm Z m!Z! eee"e"e"f ee"e"e"f ee"e"e"f f Z#ee$d< ee"e"e"e"e"e"f Z%ee$d< ee Z&ee'e&f Z(ee' ee
 dddZ)e'e'e'dddZ*dZ+d,e+Z-de- d Z.d`e&ee/ e0dddZ1e&e0d d!d"Z2e&e3d d#d$Z4e0e3d%d&d'Z5e&dd d(d)Z6e&ee0 e0d*d+d,Z7e&e/e0d-d.d/Z8e&e0d d0d1Z9e#e#e#d2d3d4Z:e&dd d5d6Z;ee'e/d7d8d9Z<ee0e0d7d:d9Z<ee/e/d7d;d9Z<ee/e'e0f ee/e0f d7d<d9Z<dae'e/dd>d?d@Z=e'ddAdBdCZ>e'e'e'ddDdEdFZ?e'e'e'ddDdGdHZ@e'e'ddIdJdKZAe'e'ddIdLdMZBe'e'ddNdOdPZCe'e'ddNdQdRZDdbe'ee'ef ee'e'f e3ddTdUdVZEe/e'dWdXdYZFG dZd[ d[ZGe	G d\d] d]ZHejIG d^d_ d_ZJdS )cz"Utility functions for PDF library.zMathieu Fenniakzbiziqe@mathieu.fenniak.net    N)	dataclass)datetimetimezone)DEFAULT_BUFFER_SIZE)SEEK_CUR)	IOAnyDictListOptionalPatternTupleUnionoverload   )   
   )	TypeAlias)r      )Self   )STREAM_TRUNCATED_PREMATURELYDeprecationErrorPdfStreamErrorTransformationMatrixTypeCompressedTransformationMatrix)textreturnc              	   C   s   | }| d krd S | d   r$d|  } | dr6| d7 } | dddddd	} t| d| d
}|dkr|t| d kr| d7 } dD ]N}zt| |}W n tk
r   Y qY qX | dr|jt	j
d}|  S qtd| d S )Nr   zD:)ZzZ0000r   +r   ' -   Z00)zD:%YzD:%Y%mzD:%Y%m%dz
D:%Y%m%d%HzD:%Y%m%d%H%MzD:%Y%m%d%H%M%SzD:%Y%m%d%H%M%S%zz+0000)tzinfozCan not convert date: )isdigitendswithreplacemaxfindlenr   strptime
ValueErrorr   utc)r   Zorgtextifd r2   0/tmp/pip-unpacked-wheel-r8zeli8p/pypdf/_utils.pyparse_iso8824_dateQ   s(    
	


r4   )header1header2r   c                 C   sf   d}g }| |kr | ||  ||kr8| || t|dkrZtd| d|d|t| S )N)z%PDF-1.3z%PDF-1.4z%PDF-1.5z%PDF-1.6z%PDF-1.7z%PDF-2.0r   zNeither z nor z are proper headers)appendindexr+   r-   r)   )r5   r6   versionsZpdf_header_indicesr2   r2   r3   _get_max_pdf_version_headerq   s    r:   )       	   
                 [   ])streammaxcharsr   c                 C   s8   d}|  d}| s4|sq4||7 }t||krq4q|S )a<  
    Read non-whitespace characters and return them.

    Stops upon encountering whitespace or when maxchars is reached.

    Args:
        stream: The data stream from which was read.
        maxchars: The maximum number of bytes returned; by default unlimited.

    Returns:
        The data which was read.

    rA   r   )readisspacer+   )rD   rE   txttokr2   r2   r3   read_until_whitespace   s    
rJ   )rD   r   c                 C   s"   |  d}|tkr|  d}q
|S )z
    Find and read the next non-whitespace character (ignores whitespace).

    Args:
        stream: The data stream from which was read.

    Returns:
        The data which was read.

    r   rF   WHITESPACESrD   rI   r2   r2   r3   read_non_whitespace   s    
rN   c                 C   s2   |  d}d}|tkr*|d7 }|  d}q|dkS )a  
    Similar to read_non_whitespace, but return a boolean if at least one
    whitespace character was read.

    Args:
        stream: The data stream from which was read.

    Returns:
        True if one or more whitespace was skipped, otherwise return False.

    r   r   rK   )rD   rI   Zcntr2   r2   r3   skip_over_whitespace   s    
rO   )valuer   c                 C   s   t dd | D S )z
    Check if the given value consists of whitespace characters only.

    Args:
        value: The bytes to check.

    Returns:
        True if the value only has whitespace characters, otherwise return False.

    c                 s   s   | ]}|t kV  qd S N)WHITESPACES_AS_BYTES).0br2   r2   r3   	<genexpr>   s     z+check_if_whitespace_only.<locals>.<genexpr>)all)rP   r2   r2   r3   check_if_whitespace_only   s    rW   c                 C   sF   |  d}| dd |dkrB|dkrB|  d}|dkrtdqd S )Nr      %)r=   r?   rA   zFile ended unexpectedly.)rF   seekr   rM   r2   r2   r3   skip_over_comment   s    

r[   )rD   regexr   c                 C   sp   d}|  d}|s|S ||| }|dk	rb| | t|t|  d || d|  }ql||7 }q|S )z
    Read until the regular expression pattern matched (ignore the match).
    Treats EOF on the underlying stream as the end of the token to be matched.

    Args:
        regex: re.Pattern

    Returns:
        The read bytes.

    rA      Nr   )rF   searchrZ   startr+   )rD   r\   namerI   mr2   r2   r3   read_until_regex   s    
 
rb   )rD   to_readr   c                 C   s>   |   |k rtd| | t | |}| | t |S )a  
    Given a stream at position X, read a block of size to_read ending at position X.

    This changes the stream's position to the beginning of where the block was
    read.

    Args:
        stream:
        to_read:

    Returns:
        The data which was read.

    z!Could not read malformed PDF file)tellr   rZ   r   rF   )rD   rc   rF   r2   r2   r3   read_block_backwards   s    
re   c                 C   s   g }d}|   dkrtttt|   }|dkr4qt| |}t|d }|sx|dkrl|| dkrl|d8 }qN|dkrxd}|r|||d d  |dkr|| dkr|d8 }qn
|| |dkr| |d t	 qqd
|ddd S )	a  
    Given a byte stream with current position X, return the previous line.

    All characters between the first CR/LF byte found before X
    (or, the start of the file, if no such byte is found) and position X
    After this call, the stream will be positioned one byte after the
    first non-CRLF character found beyond the first CR/LF byte before X,
    or, if no such byte is found, at the beginning of the stream.

    Args:
        stream: StreamType:

    Returns:
        The data which was read.

    Fr   r   s   
TNrA   rX   )rd   r   r   minr   re   r+   r7   rZ   r   join)rD   Zline_contentZ
found_crlfrc   blockidxr2   r2   r3   read_previous_line  s.    


rj   )arT   r   c                    s   t  fdd| D S )Nc                 3   s(   | ]  t  fd dt D V  qdS )c                 3   s&   | ]}t d d t |D V  qdS )c                 s   s"   | ]\}}t |t | V  qd S rQ   )float)rS   r/   jr2   r2   r3   rU   P  s     z6matrix_multiply.<locals>.<genexpr>.<genexpr>.<genexpr>N)sumzip)rS   colrowr2   r3   rU   P  s     z,matrix_multiply.<locals>.<genexpr>.<genexpr>N)tuplero   )rS   rT   rq   r3   rU   O  s   z"matrix_multiply.<locals>.<genexpr>)rs   )rk   rT   r2   rt   r3   matrix_multiplyL  s    ru   c              	   C   sd   d}|  | d tdd0}|| | |d || | W 5 Q R X |  | d dS )z5Create text file showing current location in context.i  r   zpypdf_pdfLocation.txtwbs   HEREN)rZ   openwriterF   )rD   ZradiusZ	output_fhr2   r2   r3   mark_locationU  s    
ry   )rT   r   c                 C   s   d S rQ   r2   rt   r2   r2   r3   ord_a  s    rz   c                 C   s   d S rQ   r2   rt   r2   r2   r3   rz   f  s    c                 C   s   d S rQ   r2   rt   r2   r2   r3   rz   k  s    c                 C   s   t | trt| S | S rQ   )
isinstancestrordrt   r2   r2   r3   rz   p  s    
r   )msg
stacklevelr   c                 C   s   t j| t|d d S )N)r   )warningswarnDeprecationWarning)r~   r   r2   r2   r3   	deprecatev  s    r   )r~   r   c                 C   s   t | d S rQ   )r   )r~   r2   r2   r3   deprecationz  s    r   )old_namenew_name
removed_inr   c                 C   s    t |  d| d| dd dS )zFIssue a warning that a feature will be removed, but has a replacement., is deprecated and will be removed in pypdf . Use 	 instead.   Nr   r   r   r   r2   r2   r3   deprecate_with_replacement~  s    r   c                 C   s   t |  d| d| d dS )zMRaise an exception that a feature was already removed, but has a replacement.( is deprecated and was removed in pypdf r   r   Nr   r   r2   r2   r3   deprecation_with_replacement  s    r   )r`   r   r   c                 C   s   t |  d| dd dS )zCIssue a warning that a feature will be removed without replacement.r   .r   Nr   r`   r   r2   r2   r3   deprecate_no_replacement  s    r   c                 C   s   t |  d| d dS )zJRaise an exception that a feature was already removed without replacement.r   r   Nr   r   r2   r2   r3   deprecation_no_replacement  s    r   )r~   srcr   c                 C   s   t ||  dS )z
    Use this instead of logger.error directly.

    That allows people to overwrite it more easily.

    See the docs on when to use which:
    https://pypdf.readthedocs.io/en/latest/user/suppress-warnings.html
    N)logging	getLoggererrorr~   r   r2   r2   r3   logger_error  s    	r   c                 C   s   t ||  dS )a  
    Use this instead of logger.warning directly.

    That allows people to overwrite it more easily.

    ## Exception, warnings.warn, logger_warning
    - Exceptions should be used if the user should write code that deals with
      an error case, e.g. the PDF being completely broken.
    - warnings.warn should be used if the user needs to fix their code, e.g.
      DeprecationWarnings
    - logger_warning should be used if the user needs to know that an issue was
      handled by pypdf, e.g. a non-compliant PDF being read in a way that
      pypdf could apply a robustness fix to still read it. This applies mainly
      to strict=False mode.
    N)r   r   warningr   r2   r2   r3   logger_warning  s    r   F)	func_namekwargsaliasesfailr   c                 C   s   |  D ]\}}||kr|r0t| d| d||kr^t|  d| d| d| d| d
||||< tj| d| dtdd	 qd
S )z
    Helper function to deprecate arguments.

    Args:
        func_name: Name of the function to be deprecated
        kwargs:
        aliases:
        fail:

    z# is deprecated as an argument. Use z insteadz received both z and z as an argument. z is deprecated. Use r   r   )messagecategoryr   N)itemsr   	TypeErrorpopr   r   r   )r   r   r   r   Zold_termZnew_termr2   r2   r3   rename_kwargs  s      r   )bytesr   c                 C   sR   | dk r|  dS | dk r*| d ddS | dk rB| d ddS | d ddS )	Ni  z Bytei@B z.1fz kBi ʚ;z MBz GBr2   )r   r2   r2   r3   _human_readable_bytes  s    
r   c                   @   s>   e Zd ZdZd
ddddZdedddZeddd	ZdS )classpropertyz
    Decorator that converts a method with a single cls argument into a property
    that can be accessed directly from the class.
    Nr   c                 C   s
   || _ d S rQ   fgetselfmethodr2   r2   r3   __init__  s    zclassproperty.__init__c                 C   s
   |  |S rQ   r   )r   instanceclsr2   r2   r3   __get__  s    zclassproperty.__get__c                 C   s
   || _ | S rQ   r   r   r2   r2   r3   getter  s    zclassproperty.getter)N)N)	__name__
__module____qualname____doc__r   r   r   r   r   r2   r2   r2   r3   r     s   r   c                   @   s^   e Zd ZU ddlmZ dZeed< dZe	ed< dZ
ee ed< ed	d
dZed	ddZdS )Filer   )IndirectObjectr"   r`   rA   dataNindirect_referencer   c                 C   s&   | j j d| j dtt| j dS )Nz(name=z, data: ))	__class__r   r`   r   r+   r   r   r2   r2   r3   __str__(  s    zFile.__str__c                 C   s"   |   d d dt| j d S )NrX   z, hash: r   )r   hashr   r   r2   r2   r3   __repr__+  s    zFile.__repr__)r   r   r   Zgenericr   r`   r|   __annotations__r   r   r   r   r   r   r2   r2   r2   r3   r     s   
r   c                   @   sp   e Zd ZedZeddddZeee	e
ef  dddZeedd	d
Ze
dddZeedddZdS )Versionz^(\d+)(.*)$N)version_strr   c                 C   s   || _ | || _d S rQ   )r   _parse_version
components)r   r   r2   r2   r3   r   3  s    zVersion.__init__c                 C   sn   | d}g }|D ]V}tj|}|s6|d|f q|d}|d}|d krVd}|t||f q|S )Nr   r   r   r   )splitr   COMPONENT_PATTERNmatchr7   groupint)r   r   r   Zparsed_components	componentr   Zinteger_prefixsuffixr2   r2   r3   r   7  s    


zVersion._parse_version)otherr   c                 C   s   t |tsdS | j|jkS )NF)r{   r   r   )r   r   r2   r2   r3   __eq__F  s    
zVersion.__eq__r   c                 C   s   t | jt| jfS rQ   )r   r   rs   r   r   r2   r2   r3   __hash__K  s    zVersion.__hash__c                 C   s   t |tstdt| t| j|jD ]P\}}|\}}|\}}||k rP dS ||kr^ dS ||k rl dS ||kr* dS q*t| jt|jk S )Nz#Version cannot be compared against TF)r{   r   r-   typero   r   r+   )r   r   Zself_componentZother_componentZ
self_valueZself_suffixZother_valueZother_suffixr2   r2   r3   __lt__O  s    
zVersion.__lt__)r   r   r   recompiler   r|   r   r
   r   r   r   objectboolr   r   r   r   r2   r2   r2   r3   r   /  s   
r   )N)r   )F)Kr   
__author____author_email__	functoolsr   r   sysr   dataclassesr   r   r   ior   osr   typingr   r   r	   r
   r   r   r   r   r   version_infor   Ztyping_extensionsr   errorsr   r   r   rl   r   r   r   Z
StreamTyper|   ZStrByteTyper4   r:   rL   rg   rR   ZWHITESPACES_AS_REGEXPr   r   rJ   rN   r   rO   rW   r[   rb   re   rj   ru   ry   rz   r   r   r   r   r   r   r   r   r   r   r   r   total_orderingr   r2   r2   r2   r3   <module>   s   ,
& 

; 	"  
 
 #-