U
    
3g w                     @   sl  d dl Z d dlmZ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 ddlmZ ddlmZ dd	lmZ dd
lmZmZmZmZ ddlmZ ddl m!Z! ddl m"Z# ddl m$Z$m%Z% ddl&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3 ddl4m5Z5m6Z6 ddlm7Z7m8Z8m9Z9m:Z:m;Z; dZ<G dd dZ=G dd dZ>G dd de>Z?dS )    N)BytesIOFileIOIOBase)Path)TracebackType)	AnyDictIterableListOptionalTupleTypeUnioncast   )
Encryption)
PageObject)	PdfReader)StrByteTypedeprecation_bookmarkdeprecation_with_replacementstr_)	PdfWriter)GoToActionArguments)PagesAttributes)TypArgumentsTypFitArguments)PAGE_FITArrayObjectDestinationDictionaryObjectFitFloatObjectIndirectObject
NameObject
NullObjectNumberObjectOutlineItemTextStringObject
TreeObject)	PageRangePageRangeSpec)FitType
LayoutTypeOutlineTypePagemodeTypeZoomArgTypez=close() was called and thus the writer cannot be used anymorec                   @   s$   e Zd ZdZeeeddddZdS )_MergedPagez@Collect necessary information on each page that is being merged.N)pagedatasrcidreturnc                 C   s   || _ || _d | _|| _d S N)r3   r2   out_pagedatar4   )selfr2   r3   r4    r9   2/tmp/pip-unpacked-wheel-ifm06wwb/PyPDF2/_merger.py__init__Q   s    z_MergedPage.__init__)__name__
__module____qualname____doc__r   r   intr;   r9   r9   r9   r:   r1   N   s   r1   c                   @   s,  e Zd ZdZedddYeeeef dddd	Z	d d
ddZ
eee  ee ee ddddZeddddZee eeeef ee ee eee ddddZeeeef eeee f dddZedddd[eeeef ee edeeeef eeeef ee f eddddZeeef ddddZdd
dd Zeeef dd!d"d#Z eeef dd!d$d%Z!e"dd&d'd(Z#e"dd&d)d*Z$e%dd+d,d-Z&e%dd+d.d/Z'eeeeeef f eeeef eeeef ee f eeeef  d0d1d2Z(ee)eeeef eeeef ee f e)d3d4d5Z*dd
d6d7Z+eddd\ee,e-  ee. dd8d9d:Z/edd;ee-e0f e1dd<d=d>Z2ee1 dd?d@dAZ3eddd]ee1 ee,e-  ddBdCdDZ4edd;d^eeef ee) eee  dEdFdGZ5edd;d_eeef ee) eee  dEdHdIZ6ddddde7dfeee ede.e8f eee9e9e9f  eee:ee e8dJ	dKdLZ;d`eeede.e8f eee9e9e9f  eee<e=e8dN	dOdPZ>daeeede.e8f eee9e9e9f  eee<e=e8dN	dQdRZ?eeddSdTdUZ@dbeee ee ddVdWdXZAdS )c	PdfMergeraI  
    Initialize a ``PdfMerger`` object.

    ``PdfMerger`` merges multiple PDFs into a single PDF.
    It can concatenate, slice, insert, or any combination of the above.

    See the functions :meth:`merge()<merge>` (or :meth:`append()<append>`)
    and :meth:`write()<write>` for usage information.

    :param bool strict: Determines whether user should be warned of all
            problems and also causes some correctable problems to be fatal.
            Defaults to ``False``.
    :param fileobj: Output file. Can be a filename or any kind of
            file-like object.
    outline)Z	bookmarksF N)strictfileobjr5   c                 C   s6   g | _ g | _t | _g | _g | _d| _|| _|| _d S )Nr   )	inputspagesr   outputrB   named_destsid_countrE   rD   )r8   rD   rE   r9   r9   r:   r;   i   s    zPdfMerger.__init__)r5   c                 C   s   | S r6   r9   )r8   r9   r9   r:   	__enter__v   s    zPdfMerger.__enter__)exc_typeexc	tracebackr5   c                 C   s   | j r| | j  |   dS )z*Write to the fileobj and close the merger.N)rE   writeclose)r8   rL   rM   rN   r9   r9   r:   __exit__z   s    zPdfMerger.__exit__outline_itemimport_outline)bookmarkZimport_bookmarksT)page_numberrE   rR   rG   rS   positionr5   c                 C   s  |dk	r>|dkr6|}d}d}t | d| dt ntd|dkrNtd|dkr^td| |\}	}
t|	| jd	}| j|	|f |
dk	r|
|_	|dkrd
t
|jf}n:t|tr|t
|j}nt|trnt|tstdg }g }|r|j}| |||}|r@tt|t| jt }|  j||g7  _n|  j|7  _|j}| |||}|  j|7  _t| D ]:}|j| }| j}|  jd7  _t|||}|| qx| | |  | || j||< dS )a  
        Merge the pages from the given file into the output file at the
        specified page number.

        :param int page_number: The *page number* to insert this file. File will
            be inserted after the given number.

        :param fileobj: A File Object or an object that supports the standard
            read and seek methods similar to a File Object. Could also be a
            string representing a path to a PDF file.

        :param str outline_item: Optionally, you may specify an outline item
            (previously referred to as a 'bookmark') to be applied at the
            beginning of the included file by supplying the text of the outline item.

        :param pages: can be a :class:`PageRange<PyPDF2.pagerange.PageRange>`
            or a ``(start, stop[, step])`` tuple
            to merge only the specified range of pages from the source
            document into the output document.
            Can also be a list of pages to merge.

        :param bool import_outline: You may prevent the source document's
            outline (collection of outline items, previously referred to as
            'bookmarks') from being imported by specifying this as ``False``.
        NrV   rU   zG is deprecated as an argument and will be removed in PyPDF2=4.0.0. Use  insteadzCThe argument position of merge is deprecated. Use page_number only.page_number may not be Nonezfileobj may not be None)rD   r   z0"pages" must be a tuple of (start, stop[, step])r   )!warningswarnDeprecationWarning
ValueError_create_streamr   rD   rF   append_encryptionlenrG   
isinstancer*   indiceslisttuple	TypeErrorrB   _trim_outliner'   r(   r&   rJ   r!   fitZnamed_destinations_trim_destsrI   ranger1   _associate_dests_to_pages!_associate_outline_items_to_pages)r8   rU   rE   rR   rG   rS   rV   old_termnew_termstreamencryption_objreaderZsrcpagesrB   Zoutline_item_typdestsZtrimmed_destsipager4   mpr9   r9   r:   merge   sl    #





zPdfMerger.merge)rE   r5   c                 C   s   d }t |ttfrt|d}nt |trf|jr4|j}|j }|jd t	|j
 }|j| n8t|drt|dr|d |
 }t	|}ntd||fS )Nrbr   seekreadzPdfMerger.merge requires an object that PdfReader can parse. Typically, that is a Path or a string representing a Path, a file object, or an object implementing .seek and .read. Passing a PdfReader directly works as well.)ra   strr   r   r   r_   rn   tellrw   r   rx   hasattrNotImplementedError)r8   rE   ro   rn   Z	orig_tellZfilecontentr9   r9   r:   r]      s$    	



zPdfMerger._create_stream)rE   rR   rG   rS   r5   c                 C   s   |  t| j|||| dS )a  
        Identical to the :meth:`merge()<merge>` method, but assumes you want to
        concatenate all pages onto the end of the file instead of specifying a
        position.

        :param fileobj: A File Object or an object that supports the standard
            read and seek methods similar to a File Object. Could also be a
            string representing a path to a PDF file.

        :param str outline_item: Optionally, you may specify an outline item
            (previously referred to as a 'bookmark') to be applied at the
            beginning of the included file by supplying the text of the outline item.

        :param pages: can be a :class:`PageRange<PyPDF2.pagerange.PageRange>`
            or a ``(start, stop[, step])`` tuple
            to merge only the specified range of pages from the source
            document into the output document.
            Can also be a list of pages to append.

        :param bool import_outline: You may prevent the source document's
            outline (collection of outline items, previously referred to as
            'bookmarks') from being imported by specifying this as ``False``.
        N)ru   r`   rG   )r8   rE   rR   rG   rS   r9   r9   r:   r^     s    !zPdfMerger.appendc                 C   s   | j dkrtt| jD ]H}| j |j tttt	f | j j
 }| j |tj d  |_q|   |   | j |\}}|r|  dS )z
        Write all data that has been merged to the given output file.

        :param fileobj: Output file. Can be a filename or any kind of
            file-like object.
        N)rH   RuntimeErrorERR_CLOSED_WRITERrG   Zadd_pager2   r   r   ry   r   Z_pages
get_objectZget_referencePAZKIDSr7   _write_dests_write_outlinerO   rP   )r8   rE   rs   Z	pages_objZmy_fileZret_fileobjr9   r9   r:   rO   A  s    

zPdfMerger.writec                 C   s.   g | _ | jD ]\}}|  qg | _d| _dS )zHShut all file descriptors (input and output) and clear all memory usage.N)rG   rF   rP   rH   )r8   fo_readerr9   r9   r:   rP   a  s
    
zPdfMerger.close)infosr5   c                 C   s"   | j dkrtt| j | dS )z
        Add custom metadata to the output.

        :param dict infos: a Python dictionary where each key is a field
            and each value is your new metadata.
            Example: ``{u'/Title': u'My title'}``
        N)rH   r~   r   add_metadatar8   r   r9   r9   r:   r   j  s    
zPdfMerger.add_metadatac                 C   s   t dd | | dS )zW
        .. deprecated:: 1.28.0

            Use :meth:`add_metadata` instead.
        addMetadatar   N)r   r   r   r9   r9   r:   r   v  s    
zPdfMerger.addMetadata)layoutr5   c                 C   s   t dd | | dS )zZ
        .. deprecated:: 1.28.0

            Use :meth:`set_page_layout` instead.
        setPageLayoutset_page_layoutN)r   r   r8   r   r9   r9   r:   r     s    
zPdfMerger.setPageLayoutc                 C   s"   | j dkrtt| j | dS )a  
        Set the page layout.

        :param str layout: The page layout to be used

        .. list-table:: Valid ``layout`` arguments
           :widths: 50 200

           * - /NoLayout
             - Layout explicitly not specified
           * - /SinglePage
             - Show one page at a time
           * - /OneColumn
             - Show one column at a time
           * - /TwoColumnLeft
             - Show pages in two columns, odd-numbered pages on the left
           * - /TwoColumnRight
             - Show pages in two columns, odd-numbered pages on the right
           * - /TwoPageLeft
             - Show two pages at a time, odd-numbered pages on the left
           * - /TwoPageRight
             - Show two pages at a time, odd-numbered pages on the right
        N)rH   r~   r   Z_set_page_layoutr   r9   r9   r:   r     s    
zPdfMerger.set_page_layout)moder5   c                 C   s   t ddd | | dS )zX
        .. deprecated:: 1.28.0

            Use :meth:`set_page_mode` instead.
        setPageModeset_page_mode3.0.0N)r   r   r8   r   r9   r9   r:   r     s    zPdfMerger.setPageModec                 C   s"   | j dkrtt| j | dS )aP  
        Set the page mode.

        :param str mode: The page mode to use.

        .. list-table:: Valid ``mode`` arguments
           :widths: 50 200

           * - /UseNone
             - Do not show outline or thumbnails panels
           * - /UseOutlines
             - Show outline (aka bookmarks) panel
           * - /UseThumbs
             - Show page thumbnails panel
           * - /FullScreen
             - Fullscreen view
           * - /UseOC
             - Show Optional Content Group (OCG) panel
           * - /UseAttachments
             - Show attachments panel
        N)rH   r~   r   r   r   r9   r9   r:   r     s    
zPdfMerger.set_page_mode)pdfrq   rG   r5   c           	      C   s   g }t |tr|n
tt| }| D ]f\}}|D ]X}|j|  |d  kr2|d  |td< t|t|d ks|t|	|  q&q2q&|S )zHRemove named destinations that are not a part of the specified page set./Page/Title)
ra   rc   ri   itemsrG   r   r$   r   AssertionErrorr^   )	r8   r   rq   rG   Z	new_destslstkeyobjjr9   r9   r:   rh     s    
zPdfMerger._trim_dests)r   rB   rG   r5   c                 C   s   g }d}t |tr|n
tt| }t|D ]\}}t |trp| |||}	|	r|sd|||d   ||	 q*d}|D ]R}
|d dkrqx|j|
  |d  krx|d  |td< || d} q*qxq*|S )zJRemove outline item entries that are not a part of the specified page set.Tr   Fr   N)	ra   rc   ri   	enumeraterf   r^   rG   r   r$   )r8   r   rB   rG   Znew_outlineZprev_header_addedr   rr   rR   subr   r9   r9   r:   rf     s,    

zPdfMerger._trim_outlinec                 C   sv   | j d krtt| jD ]X}d }d|kr\t| jD ](\}}|j|d kr2|j|td<  q\q2|d k	r| j 	| qd S )Nr   )
rH   r~   r   rI   r   rG   r4   r7   r$   Zadd_named_destination_object)r8   
named_destpagenors   r9   r9   r:   r     s    

zPdfMerger._write_dests)rB   parentr5   c                 C   s   | j d krtt|d kr | j}|d k	s0tdd }|D ]|}t|trT| || q8d }d|krt| j	D ]&\}}|j
|d krj| ||  qqj|d k	r8|d= |d= | j ||}q8d S )Nhint for mypyr   /Type)rH   r~   r   rB   r   ra   rc   r   r   rG   r4   _write_outline_item_on_pageZadd_outline_item_dict)r8   rB   r   Z
last_addedrR   Zpage_nors   r9   r9   r:   r     s&    

zPdfMerger._write_outline)rT   )rR   rs   r5   c                 C   s   t t|d }t|jt|g}tjtjftj	tjftj
tjftjtjftjtjtjdftjtjtjtjtjfi}||t D ]B}||krt|| ts|t||  n|td ||= qtttjtdttjt|i|td< d S )Nr   z/Zoomr   z/GoToz/A)r   ry   r&   r4   r$   r   ZFIT_Hr   ZTOPZFIT_BHZFIT_VLEFTZFIT_BVZXYZZFIT_RZBOTTOMRIGHTgetrd   ra   r%   r^   r"   r    r   SDr   )r8   rR   rs   Zoi_typeargsZfit2arg_keysZarg_keyr9   r9   r:   r   "  sD         
   z%PdfMerger._write_outline_item_on_page)rG   r5   c                 C   sv   | j D ]j}d }|d }t|tr"q|D ]}| |j kr&|j}q&|d kr`td|d  dt||td< qd S )Nr   zUnresolved named destination 'r   ')rI   ra   r&   r   r2   r4   r\   r$   )r8   rG   r   r   nprs   r9   r9   r:   rj   E  s    

z#PdfMerger._associate_dests_to_pages)rG   rB   r5   c                 C   s   |d kr| j }|d k	std|D ]n}t|tr>| || q"d }|d }t|trVq"|D ]}| |j krZ|j}qZ|d k	r"t||t	d< q"d S )Nr   r   )
rB   r   ra   rc   rk   r&   r   r2   r4   r$   )r8   rG   rB   rR   r   Zoutline_item_pagepr9   r9   r:   rk   W  s     

z+PdfMerger._associate_outline_items_to_pages)rR   rootr5   c                 C   sz   |d kr| j }t|D ]^\}}t|trH| ||}|rt|g|   S q||ksjttttf |d |kr|g  S qd S )Nr   )rB   r   ra   rc   find_outline_itemr   r   r   )r8   rR   r   rr   Zoi_enumresr9   r9   r:   r   p  s    
zPdfMerger.find_outline_itemc                 C   s   |  ||S )zZ
        .. deprecated:: 2.9.0
            Use :meth:`find_outline_item` instead.
        )r   )r8   rR   r   r9   r9   r:   find_bookmark  s    
zPdfMerger.find_bookmark)	titlerU   r   colorbolditalicrg   pagenumr5   c	              
   C   s   |dk	r|dk	rt d|dk	rDd}	d}
t|	 d|
 dt |}|dkrTt d| j}|dkrjtt||||d||||S )al  
        Add an outline item (commonly referred to as a "Bookmark") to this PDF file.

        :param str title: Title to use for this outline item.
        :param int page_number: Page number this outline item will point to.
        :param parent: A reference to a parent outline item to create nested
            outline items.
        :param tuple color: Color of the outline item's font as a red, green, blue tuple
            from 0.0 to 1.0
        :param bool bold: Outline item font is bold
        :param bool italic: Outline item font is italic
        :param Fit fit: The fit of the destination page.
        NzMThe argument pagenum of add_outline_item is deprecated. Use page_number only.r   rU   H is deprecated as an argument and will be removed in PyPDF2==4.0.0. Use rW   rX   )r\   rY   rZ   r[   rH   r~   r   add_outline_item)r8   r   rU   r   r   r   r   rg   r   rl   rm   writerr9   r9   r:   r     s6    zPdfMerger.add_outline_item/Fit)	r   r   r   r   r   r   rg   r   r5   c           	      G   s*   t ddd | ||||||t||dS )zZ
        .. deprecated:: 1.28.0
            Use :meth:`add_outline_item` instead.
        addBookmarkr   r   Zfit_typeZfit_argsr   r   r!   	r8   r   r   r   r   r   r   rg   r   r9   r9   r:   r     s    
zPdfMerger.addBookmarkc           	      G   s*   t ddd | ||||||t||dS )zY
        .. deprecated:: 2.9.0
            Use :meth:`add_outline_item` instead.
        r   r   r   r   r   r   r9   r9   r:   add_bookmark  s    
zPdfMerger.add_bookmark)r   r   r5   c                 C   s   t ddd | ||S )z_
        .. deprecated:: 1.28.0
            Use :meth:`add_named_destination` instead.
        addNamedDestinationadd_named_destinationr   )r   r   )r8   r   r   r9   r9   r:   r      s      zPdfMerger.addNamedDestination)r   rU   r   r5   c                 C   s   |dk	r|dk	rt d|dk	rDd}d}t| d| dt |}|dkrTt dtt|t|tjdd	}| j	
| dS )
z
        Add a destination to the output.

        :param str title: Title to use
        :param int page_number: Page number this destination points at.
        NzRThe argument pagenum of add_named_destination is deprecated. Use page_number only.r   rU   r   rW   rX   i:  )top)r\   rY   rZ   r[   r   r(   r&   r!   Zfit_horizontallyrI   r^   )r8   r   rU   r   rl   rm   destr9   r9   r:   r   
  s(    
zPdfMerger.add_named_destination)FrC   )NNNNTN)NNT)NN)N)N)N)NNFFr   )NNFFr   )NN)Br<   r=   r>   r?   r   boolr   r   r   r;   rK   r   r   BaseExceptionr   rQ   r@   r   ry   r+   ru   r   r   r   r]   r*   r
   r^   rO   rP   r   r   r   r   r-   r   r   r/   r   r   rh   r.   rf   r   r	   r'   r)   r   r   r1   r   rj   rk   r   r   r   r#   floatr!   r   r,   r0   r   r   r   r   r9   r9   r9   r:   rA   X   s@      


      v#
   "" 				""  

 "  
 

 

;            rA   c                       s&   e Zd Zeedd fddZ  ZS )PdfFileMergerN)r   kwargsr5   c                    s:   t ddd d|kr(t|dk r(d|d< t j|| d S )Nr   rA   r   rD   r   T)r   r`   superr;   )r8   r   r   	__class__r9   r:   r;   0  s    zPdfFileMerger.__init__)r<   r=   r>   r   r;   __classcell__r9   r9   r   r:   r   /  s   r   )@rY   ior   r   r   pathlibr   typesr   typingr   r   r	   r
   r   r   r   r   r   r_   r   Z_pager   r   r   _utilsr   r   r   r   Z_writerr   	constantsr   r   r   r   r   Zgenericr   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   Z	pageranger*   r+   r,   r-   r.   r/   r0   r   r1   rA   r   r9   r9   r9   r:   <module>   s0   ,<
     \