U
    Nf_                     @   s@  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 dd
lmZ ddlmZm Z 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-m.Z.m/Z/m0Z0m1Z1 ddl2m3Z3m4Z4 ddlm5Z5m6Z6m7Z7 dZ8G dd dZ9G dd dZ:dS )    )BytesIOFileIOIOBase)Path)TracebackType)	AnyDictIterableListOptionalTupleTypeUnioncast   )
Encryption)
PageObject)	PdfReader)StrByteTypedeprecate_with_replacementstr_)	PdfWriter)GoToActionArgumentsTypArgumentsTypFitArguments)PagesAttributes)PAGE_FITArrayObjectDestinationDictionaryObjectFitFloatObjectIndirectObject
NameObject
NullObjectNumberObjectOutlineItemTextStringObject
TreeObject)	PageRangePageRangeSpec)
LayoutTypeOutlineTypePagemodeTypez=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)r0   r/   out_pagedatar1   )selfr/   r0   r1    r6   1/tmp/pip-unpacked-wheel-zevpxvmc/pypdf/_merger.py__init__N   s    z_MergedPage.__init__)__name__
__module____qualname____doc__r   r   intr8   r6   r6   r6   r7   r.   K   s   r.   c                   @   s  e Zd ZdZdEe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dFeeeeef e
e e
e eddddZeeeef eee
e f dddZdGe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 ddd d!Z!e"dd"d#d$Z#e$e
e" dd%d&Z%e%j&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  d(d)d*Z'ee(eeeef eeeef ee f e(d+d,d-Z)ddd.d/Z*dHe
e+e,  e
e- dd0d1d2Z.ee,e/f e0dd3d4d5Z1ee0 dd6d7d8Z2dIee0 e
e+e,  dd9d:d;Z3dJeeef e
e( e
ee  d<d=d>Z4dddde5feeede-e6f e
ee7e7e7f  eee8e6d?d@dAZ9eeddBdCdDZ:dS )K	PdfMergerzD
    Use :class:`PdfWriter` instead.

    .. deprecated:: 5.0.0
    F N)strictfileobjr2   c                 C   sB   t ddd g | _g | _t | _g | _g | _d| _|| _|| _	d S )Nr>   r   5.0.0r   )
r   inputspagesr   outputoutlinenamed_destsid_countrA   r@   )r5   r@   rA   r6   r6   r7   r8   \   s    zPdfMerger.__init__)r2   c                 C   s   t ddd | S )Nr>   r   rB   )r   r5   r6   r6   r7   	__enter__i   s    zPdfMerger.__enter__)exc_typeexc	tracebackr2   c                 C   s   | j r| | j  |   dS )z*Write to the fileobj and close the merger.N)rA   writeclose)r5   rK   rL   rM   r6   r6   r7   __exit__n   s    zPdfMerger.__exit__T)page_numberrA   outline_itemrD   import_outliner2   c                 C   sx  |  |\}}t|| jd}| j||f |dk	r:||_|dkrRdt|jf}n:t|t	rn|
t|j}nt|trznt|tstdg }	g }
|r|j}
| ||
|}
|rtt|t| jt }|  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.

        Args:
            page_number: The *page number* to insert this file. File will
                be inserted after the given number.
            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.
            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.
            pages: can be a :class:`PageRange<pypdf.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.
           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``.
        )r@   Nr   z0"pages" must be a tuple of (start, stop[, step])r   )_create_streamr   r@   rC   append_encryptionlenrD   
isinstancer)   indiceslisttuple	TypeErrorrF   _trim_outliner&   r'   r%   rH   r    fitZnamed_destinations_trim_destsrG   ranger.   _associate_dests_to_pages!_associate_outline_items_to_pages)r5   rQ   rA   rR   rD   rS   streamencryption_objreaderZsrcpagesrF   Zoutline_item_typdestsZtrimmed_destsipager1   mpr6   r6   r7   mergey   sL    





zPdfMerger.merge)rA   r2   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.)rX   strr   r   r   rV   rc   tellrl   r   rm   hasattrNotImplementedError)r5   rA   rd   rc   Z	orig_tellZfile_contentr6   r6   r7   rT      s$    	



zPdfMerger._create_stream)rA   rR   rD   rS   r2   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.

        Args:
            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.
            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.
            pages: can be a :class:`PageRange<pypdf.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.
            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)rj   rW   rD   )r5   rA   rR   rD   rS   r6   r6   r7   rU      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.

        Args:
            fileobj: Output file. Can be a filename or any kind of
                file-like object.
        N)rE   RuntimeErrorERR_CLOSED_WRITERrD   Zadd_pager/   r   r   rn   r   Z_pages
get_objectZget_referencePAZKIDSr4   _write_dests_write_outlinerN   rO   )r5   rA   rh   Z	pages_objZmy_fileZret_fileobjr6   r6   r7   rN     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)rD   rC   rO   rE   )r5   Zfile_descriptor_readerr6   r6   r7   rO   2  s
    
zPdfMerger.close)infosr2   c                 C   s"   | j dkrtt| j | dS )z
        Add custom metadata to the output.

        Args:
            infos: a Python dictionary where each key is a field
                and each value is your new metadata.
                An example is ``{'/Title': 'My title'}``
        N)rE   rs   rt   add_metadata)r5   rz   r6   r6   r7   r{   ;  s    	
zPdfMerger.add_metadata)layoutr2   c                 C   s"   | j dkrtt| j | dS )a  
        Set the page layout.

        Args:
            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)rE   rs   rt   Z_set_page_layout)r5   r|   r6   r6   r7   set_page_layoutH  s    
zPdfMerger.set_page_layout)moder2   c                 C   s
   || _ dS aW  
        Set the page mode.

        Args:
            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)	page_moder5   r~   r6   r6   r7   set_page_modee  s    zPdfMerger.set_page_modec                 C   s   | j dkrtt| j jS r   rE   rs   rt   r   rI   r6   r6   r7   r   ~  s    
zPdfMerger.page_modec                 C   s   | j d krtt|| j _d S r3   r   r   r6   r6   r7   r     s    
)pdfrf   rD   r2   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 )z
        Remove named destinations that are not a part of the specified page set.

        Args:
            pdf:
            dests:
            pages:
        /Page/Title)
rX   rZ   r`   itemsrD   ru   r#   r   AssertionErrorrU   )	r5   r   rf   rD   Z	new_destslstkeyobjjr6   r6   r7   r_     s    
zPdfMerger._trim_dests)r   rF   rD   r2   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 )z
        Remove outline item entries that are not a part of the specified page set.

        Args:
            pdf:
            outline:
            pages:

        Returns:
            An outline type
        Tr   Fr   N)	rX   rZ   r`   	enumerater]   rU   rD   ru   r#   )r5   r   rF   rD   Znew_outlineZprev_header_addedr   rg   rR   subr   r6   r6   r7   r]     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   )
rE   rs   rt   rG   r   rD   r1   r4   r#   Zadd_named_destination_object)r5   
named_dest
page_indexrh   r6   r6   r7   rw     s    

zPdfMerger._write_dests)rF   parentr2   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)rE   rs   rt   rF   r   rX   rZ   rx   r   rD   r1   _write_outline_item_on_pageZadd_outline_item_dict)r5   rF   r   Z
last_addedrR   Zpage_norh   r6   r6   r7   rx     s&    

zPdfMerger._write_outline)rR   rh   r2   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}||dD ]B}||krt|| ts|t||  n|td ||= q~tttjtdttjt|i|td< d S )Nr   z/Zoomr6   r   z/GoToz/A)r   rn   r%   r1   r#   r   ZFIT_Hr   ZTOPZFIT_BHZFIT_VLEFTZFIT_BVZXYZZFIT_RZBOTTOMRIGHTgetrX   r$   rU   r!   r   r   SDr   )r5   rR   rh   Zoi_typeargsZfit2arg_keysZarg_keyr6   r6   r7   r     sD         
   z%PdfMerger._write_outline_item_on_page)rD   r2   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   ')rG   rX   r%   ru   r/   r1   
ValueErrorr#   )r5   rD   r   r   nprh   r6   r6   r7   ra   -  s    

z#PdfMerger._associate_dests_to_pages)rD   rF   r2   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   )
rF   r   rX   rZ   rb   r%   ru   r/   r1   r#   )r5   rD   rF   rR   r   Zoutline_item_pagepr6   r6   r7   rb   ?  s     

z+PdfMerger._associate_outline_items_to_pages)rR   rootr2   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   )rF   r   rX   rZ   find_outline_itemr   r   r   )r5   rR   r   rg   Zoi_enumresr6   r6   r7   r   W  s    
zPdfMerger.find_outline_item)titlerQ   r   colorbolditalicr^   r2   c           	   
   C   s.   | j }|dkrtt||||d||||S )aQ  
        Add an outline item (commonly referred to as a "Bookmark") to this PDF file.

        Args:
            title: Title to use for this outline item.
            page_number: Page number this outline item will point to.
            parent: A reference to a parent outline item to create nested
                outline items.
            color: Color of the outline item's font as a red, green, blue tuple
                from 0.0 to 1.0
            bold: Outline item font is bold
            italic: Outline item font is italic
            fit: The fit of the destination page.
        N)rE   rs   rt   add_outline_item)	r5   r   rQ   r   r   r   r   r^   writerr6   r6   r7   r   o  s    zPdfMerger.add_outline_item)r   rQ   r2   c                 C   s,   t t|t|tjdd}| j| dS )z
        Add a destination to the output.

        Args:
            title: Title to use
            page_number: Page number this destination points at.
        i:  )topN)r   r'   r%   r    Zfit_horizontallyrG   rU   )r5   r   rQ   destr6   r6   r7   add_named_destination  s    
zPdfMerger.add_named_destination)Fr?   )NNT)NNT)NN)N)N);r9   r:   r;   r<   boolr   r   r   r8   rJ   r   r   BaseExceptionr   rP   r=   r   rn   r*   rj   r   r   r   rT   r)   r
   rU   rN   rO   r   r   r{   r+   r}   r-   r   propertyr   setterr_   r,   r]   rw   r	   r&   r(   rx   r   r.   r   ra   rb   r   r   r"   floatr    r   r   r6   r6   r6   r7   r>   U   s       

   X&   " 	"")  

 "  
 

(r>   N);ior   r   r   pathlibr   typesr   typingr   r   r	   r
   r   r   r   r   r   rV   r   Z_pager   ry   r   _utilsr   r   r   Z_writerr   	constantsr   r   r   r   rv   Zgenericr   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   Z	pageranger)   r*   r+   r,   r-   rt   r.   r>   r6   r6   r6   r7   <module>   s    ,<
