U
    Bb]                     @   s<  d dl mZmZmZ d dl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 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(m)Z)m*Z* ddl+m,Z,m-Z- ddl.m/Z/m0Z0m1Z1m2Z2m3Z3 dZ4G dd dZ5G dd dZ6G dd de6Z7dS )    )BytesIOFileIOIOBase)AnyDictIterableListOptionalTupleUnioncast   )
Encryption)
PageObject)	PdfReader)StrByteTypedeprecate_with_replacementstr_)	PdfWriter)GoToActionArguments)PagesAttributes)TypArgumentsTypFitArguments)ArrayObjectBookmarkDestinationDictionaryObjectFloatObjectIndirectObject
NameObject
NullObjectNumberObjectTextStringObject
TreeObject)	PageRangePageRangeSpec)FitType
LayoutTypeOutlinesType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)r-   r,   out_pagedatar.   )selfr,   r-   r.    r2   2/tmp/pip-unpacked-wheel-weujb6sz/PyPDF2/_merger.py__init__=   s    z_MergedPage.__init__)__name__
__module____qualname____doc__r   r   intr4   r2   r2   r2   r3   r+   :   s   r+   c                   @   s  e Zd ZdZdGeddddZdHeeee	f e
e e
e eddd	d
Zeee	f eeee
e f dddZdIeee	f e
e edeeeef eeeef f eddddZe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 f e eeef  d%d&d'Z!e	e"eeeef eeeef f e"d(d)d*Z#ddd+d,Z$dJe
e%e&  e
e' dd-d.d/Z(ee&e)f e*dd0d1d2Z+e e* dd3d4d5Z,dKe e* e
e%e&  dd6d7d8Z-dLeeef e
e" e
e e  d9d:d;Z.dMeeede'e/f e
ee0e0e0f  eee1e2e/d=	d>d?Z3dNeeede'e/f e
ee0e0e0f  eee1e2e/d=	d@dAZ4eeddBdCdDZ5eeddBdEdFZ6dS )O	PdfMergera  
    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``.
    FN)strictr/   c                 C   s0   g | _ g | _t | _g | _g | _d| _|| _d S )Nr   )inputspagesr   output	bookmarksnamed_destsid_countr;   )r1   r;   r2   r2   r3   r4   S   s    zPdfMerger.__init__T)positionfileobjbookmarkr=   import_bookmarksr/   c                 C   sr  |  |\}}}t|| jd}	| j||	|f |dk	r>||	_|dkrVdt|	jf}n.t|t	rr|
t|	j}nt|tstdg }
g }|r|	j}| |	||}|rtt|t| jttj}|  j||g7  _n|  j|7  _|	j}| |	||}|  j|7  _t| D ]:}|	j| }| j}|  jd7  _t||	|}|
| q| |
 | |
 |
| j||< dS )a  
        Merge the pages from the given file into the output file at the
        specified page number.

        :param int position: 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 bookmark: Optionally, you may specify a bookmark to be
            applied at the beginning of the included file by supplying the text
            of the bookmark.

        :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.

        :param bool import_bookmarks: You may prevent the source document's
            bookmarks from being imported by specifying this as ``False``.
        )r;   Nr   z0"pages" must be a tuple of (start, stop[, step])r   )_create_streamr   r;   r<   append_encryptionlenr=   
isinstancer$   indicestuple	TypeErrorZoutlines_trim_outliner   r"   r!   rA   r   r   ZFITr?   Znamed_destinations_trim_destsr@   ranger+   _associate_dests_to_pages_associate_bookmarks_to_pages)r1   rB   rC   rD   r=   rE   streammy_fileencryption_objreaderZsrcpagesoutlineZbookmark_typdestsZtrimmed_destsipager.   mpr2   r2   r3   merge\   sH    




zPdfMerger.merge)rC   r/   c                 C   s   d}d }t |tr"t|d}d}nt |trn|jr8|j}|j }|jd t|j	 }|j| d}n8t
|drt
|dr|d |	 }t|}d}n|}|||fS )NFrbTr   seekread)rJ   strr   r   rH   rS   tellr^   r   r_   hasattr)r1   rC   rT   rU   rS   Z	orig_tellZfilecontentr2   r2   r3   rF      s(    




zPdfMerger._create_stream)rC   rD   r=   rE   r/   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 bookmark: Optionally, you may specify a bookmark to be
            applied at the beginning of the included file by supplying the text
            of the bookmark.

        :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.

        :param bool import_bookmarks: You may prevent the source document's
            bookmarks from being imported by specifying this as ``False``.
        N)r\   rI   r=   )r1   rC   rD   r=   rE   r2   r2   r3   rG      s    zPdfMerger.appendc                 C   s   | j dkrttd}t|tr.t|d}d}| jD ]H}| j |j t	t
ttf | j j }| j |tj d  |_q4|   |   | 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.
        NFwbT)r>   RuntimeErrorERR_CLOSED_WRITERrJ   r`   r   r=   Zadd_pager,   r   r   r   Z_pages
get_objectZget_referencePAZKIDSr0   _write_dests_write_bookmarkswriteclose)r1   rC   rT   rZ   Z	pages_objr2   r2   r3   rk      s"    



zPdfMerger.write)r/   c                 C   s4   g | _ | jD ]\}}}|r|  qg | _d| _dS )zHShut all file descriptors (input and output) and clear all memory usage.N)r=   r<   rl   r>   )r1   fo_readerZminer2   r2   r3   rl     s    
zPdfMerger.close)infosr/   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)r>   re   rf   add_metadatar1   ro   r2   r2   r3   rp   $  s    
zPdfMerger.add_metadatac                 C   s   t dd | | dS )zW
        .. deprecated:: 1.28.0

            Use :meth:`add_metadata` instead.
        addMetadatarp   N)r   rp   rq   r2   r2   r3   rr   0  s    
zPdfMerger.addMetadata)layoutr/   c                 C   s   t dd | | dS )zZ
        .. deprecated:: 1.28.0

            Use :meth:`set_page_layout` instead.
        setPageLayoutset_page_layoutN)r   ru   r1   rs   r2   r2   r3   rt   9  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)r>   re   rf   Z_set_page_layoutrv   r2   r2   r3   ru   B  s    
zPdfMerger.set_page_layout)moder/   c                 C   s   t dd | | dS )zX
        .. deprecated:: 1.28.0

            Use :meth:`set_page_mode` instead.
        setPageModeset_page_modeN)r   ry   r1   rw   r2   r2   r3   rx   ^  s    
zPdfMerger.setPageModec                 C   s"   | j dkrtt| j | dS )aR  
        Set the page mode.

        :param str mode: The page mode to use.

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

           * - /UseNone
             - Do not show outlines or thumbnails panels
           * - /UseOutlines
             - Show outlines (aka bookmarks) panel
           * - /UseThumbs
             - Show page thumbnails panel
           * - /FullScreen
             - Fullscreen view
           * - /UseOC
             - Show Optional Content Group (OCG) panel
           * - /UseAttachments
             - Show attachments panel
        N)r>   re   rf   ry   rz   r2   r2   r3   ry   g  s    
zPdfMerger.set_page_mode)pdfrX   r=   r/   c                 C   s|   g }|  D ]j\}}t| D ]X}|j|  |d  kr|d  |td< t|t|d ksft||  qqq|S )zHRemove named destinations that are not a part of the specified page set./Page/Title)itemsrP   r=   rg   r   r   AssertionErrorrG   )r1   r{   rX   r=   Z	new_destskeyobjjr2   r2   r3   rO     s    
zPdfMerger._trim_dests)r{   rW   r=   r/   c           
      C   s   g }d}t |D ]\}}t|trV| |||}|r|sJ|||d   || qd}t| D ]R}	|d dkrtqb|j|	  |d  krb|d  |td< || d} qqbq|S )zNRemove outline/bookmark entries that are not a part of the specified page set.Tr   Fr|   N)		enumeraterJ   listrN   rG   rP   r=   rg   r   )
r1   r{   rW   r=   Znew_outlineZprev_header_addedrY   osubr   r2   r2   r3   rN     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|   )
r>   re   rf   r@   r   r=   r.   r0   r   Zadd_named_destination_object)r1   Z
named_destpagenorZ   r2   r2   r3   ri     s    

zPdfMerger._write_dests)r?   parentr/   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)r>   re   rf   r?   r   rJ   r   rj   r   r=   r.   _write_bookmark_on_pageZadd_bookmark_dict)r1   r?   r   Z
last_addedrD   Zpage_norZ   r2   r2   r3   rj     s&    

zPdfMerger._write_bookmarks)rD   rZ   r/   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   r`   r!   r.   r   r   FIT_Hr   ZTOPZFIT_BHZFIT_VLEFTZFIT_BVZXYZZFIT_RZBOTTOMRIGHTgetrL   rJ   r    rG   r   r   r   SDr   )r1   rD   rZ   Zbm_typeargsZfit2arg_keysZarg_keyr2   r2   r3   r     s>           z!PdfMerger._write_bookmark_on_page)r=   r/   c                 C   sx   | j D ]l}d }|d }t|tr"q|D ]}| |j kr&|j}q&|d k	r^t||td< qtd|d  dqd S )Nr|   zUnresolved named destination 'r}   ')r@   rJ   r!   rg   r,   r.   r   
ValueError)r1   r=   Zndr   nppr2   r2   r3   rQ     s    

z#PdfMerger._associate_dests_to_pages)r=   r?   r/   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|   )
r?   r   rJ   r   rR   r!   rg   r,   r.   r   )r1   r=   r?   br   Zbpr   r2   r2   r3   rR     s     

z'PdfMerger._associate_bookmarks_to_pages)rD   rootr/   c                 C   sl   |d kr| j }t|D ]P\}}t|trH| ||}|rf|g|   S q||ks\|d |kr|g  S qd S )Nr}   )r?   r   rJ   r   find_bookmark)r1   rD   r   rY   r   resr2   r2   r3   r      s    
zPdfMerger.find_bookmark/Fit)	titlepagenumr   colorbolditalicfitr   r/   c           	      G   s&   t dd | j|||||||f| S )zV
        .. deprecated:: 1.28.0
            Use :meth:`add_bookmark` instead.
        addBookmarkadd_bookmark)r   r   )	r1   r   r   r   r   r   r   r   r   r2   r2   r3   r   5  s    
      zPdfMerger.addBookmarkc           
      G   s2   | j }	|	dkrtt|	j|||||||f| S )aG  
        Add a bookmark to this PDF file.

        :param str title: Title to use for this bookmark.
        :param int pagenum: Page number this bookmark will point to.
        :param parent: A reference to a parent bookmark to create nested
            bookmarks.
        :param tuple color: Color of the bookmark as a red, green, blue tuple
            from 0.0 to 1.0
        :param bool bold: Bookmark is bold
        :param bool italic: Bookmark is italic
        :param str fit: The fit of the destination page. See
            :meth:`addLink()<addLink>` for details.
        N)r>   re   rf   r   )
r1   r   r   r   r   r   r   r   r   writerr2   r2   r3   r   I  s          zPdfMerger.add_bookmark)r   r   r/   c                 C   s   t dd | ||S )z_
        .. deprecated:: 1.28.0
            Use :meth:`add_named_destination` instead.
        addNamedDestinationadd_named_destination)r   r   )r1   r   r   r2   r2   r3   r   i  s    
zPdfMerger.addNamedDestinationc                 C   s0   t t|t|ttjtd}| j| dS )z
        Add a destination to the output.

        :param str title: Title to use
        :param int pagenum: Page number this destination points at.
        i:  N)r   r"   r!   r   r   r   r@   rG   )r1   r   r   destr2   r2   r3   r   q  s    zPdfMerger.add_named_destination)F)NNT)NNT)NN)N)N)NNFFr   )NNFFr   )7r5   r6   r7   r8   boolr4   r9   r   r   r   r	   r`   r%   r\   r
   r   r   rF   r$   rG   rk   rl   r   r   rp   rr   r'   rt   ru   r)   rx   ry   r   rO   r(   rN   ri   r   r   r#   rj   r   r+   r   rQ   rR   r   r   floatr&   r*   r   r   r   r   r2   r2   r2   r3   r:   D   s      
W
)   
 $
			  

    
 

           r:   c                       s&   e Zd Zeedd fddZ  ZS )PdfFileMergerN)r   kwargsr/   c                    s8   t dd d|kr&t|dk r&d|d< t j|| d S )Nr   ZPdfMerger;   r   T)r   rI   superr4   )r1   r   r   	__class__r2   r3   r4     s    
zPdfFileMerger.__init__)r5   r6   r7   r   r4   __classcell__r2   r2   r   r3   r     s   r   N)8ior   r   r   typingr   r   r   r   r	   r
   r   r   rH   r   Z_pager   rn   r   _utilsr   r   r   Z_writerr   	constantsr   r   rh   r   r   Zgenericr   r   r   r   r   r   r   r    r!   r"   r#   Z	pageranger$   r%   typesr&   r'   r(   r)   r*   rf   r+   r:   r   r2   r2   r2   r3   <module>   s(   (4
    A