o
    ei                     @   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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/m0Z0 ddl1m2Z2m3Z3 ddlm4Z4m5Z5m6Z6m7Z7m8Z8 dZ9G dd dZ:G dd dZ;G dd de;Z<dS )    )BytesIOFileIOIOBase)Path)TracebackType)	AnyDictIterableListOptionalTupleTypeUnioncast   )
Encryption)
PageObject)	PdfReader)StrByteTypedeprecate_bookmarkdeprecate_with_replacementstr_)	PdfWriter)GoToActionArguments)PagesAttributes)TypArgumentsTypFitArguments)ArrayObjectDestinationDictionaryObject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dedededdfddZdS )	_MergedPagez@Collect necessary information on each page that is being merged.pagedatasrcidreturnNc                 C   s   || _ || _d | _|| _d S N)r1   r0   out_pagedatar2   )selfr0   r1   r2    r7   >D:\Projects\ConvertPro\env\Lib\site-packages\PyPDF2/_merger.py__init__N   s   
z_MergedPage.__init__)__name__
__module____qualname____doc__r   r   intr9   r7   r7   r7   r8   r/   K   s    r/   c                   @   s  e Zd ZdZedd	d\dedeeef dd	fd
dZ	d]ddZ
deee  dee dee dd	fddZeddd					d^dedeeeef dee dee dedd	fddZdeeeef deeee f fddZeddd					d^deeeef dee ded	eeeef eeeef f dedd	f
ddZdeeef dd	fdd Zd_d!d"Zd#eeef dd	fd$d%Zd#eeef dd	fd&d'Z d(e!dd	fd)d*Z"d(e!dd	fd+d,Z#d-e$dd	fd.d/Z%d-e$dd	fd0d1Z&d2ed3eeeeef f deeeef eeeef f de'eeef  fd4d5Z(d2ede)deeeef eeeef f de)fd6d7Z*d_d8d9Z+edd				d`dee,e-  d:ee. dd	fd;d<Z/edd=dee-e0f d>e1dd	fd?d@Z2de'e1 dd	fdAdBZ3edd		dade'e1 dee,e-  dd	fdCdDZ4edd=		dadeeef dEee) dee'e  fdFdGZ5edd=		dadeeef dEee) dee'e  fdHdIZ6							JdbdKedLed:ed	e.e7f dMeee8e8e8f  dNedOedPe9dQe:de7fdRdSZ;							JdbdKedLed:ed	e.e7f dMeee8e8e8f  dNedOedPe9dQe:de7fdTdUZ<							JdbdKedLed:ed	e.e7f dMeee8e8e8f  dNedOedPe9dQe:de7fdVdWZ=dKedLedd	fdXdYZ>dKedLedd	fdZd[Z?d	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 strictfileobjr3   Nc                 C   s6   g | _ g | _t | _g | _g | _d| _|| _|| _d S )Nr   )	inputspagesr   outputr@   named_destsid_countrC   rB   )r6   rB   rC   r7   r7   r8   r9   f   s   
zPdfMerger.__init__c                 C   s   | S r4   r7   )r6   r7   r7   r8   	__enter__s   s   zPdfMerger.__enter__exc_typeexc	tracebackc                 C   s   | j r	| | j  |   dS )z*Write to the fileobj and close the merger.N)rC   writeclose)r6   rJ   rK   rL   r7   r7   r8   __exit__w   s   zPdfMerger.__exit__outline_itemimport_outline)bookmarkZimport_bookmarksTpositionrE   c                 C   sl  |  |\}}t|| jd}| j||f |dur||_|du r)dt|jf}nt|t	r7|
t|j}n	t|ts@tdg }	g }
|rP|j}
| ||
|}
|rjt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 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.

        :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``.
        )rB   Nr   z0"pages" must be a tuple of (start, stop[, step])r   )_create_streamr   rB   rD   append_encryptionlenrE   
isinstancer(   indicestuple	TypeErrorr@   _trim_outliner%   r&   r$   rH   r"   r   ZFITZnamed_destinations_trim_destsrG   ranger/   _associate_dests_to_pages!_associate_outline_items_to_pages)r6   rS   rC   rP   rE   rQ   streamencryption_objreaderZsrcpagesr@   Zoutline_item_typdestsZtrimmed_destsipager2   mpr7   r7   r8   merge   sH   !




zPdfMerger.mergec                 C   s   d }t |ttfrt|d}||fS t |tr9|jr|j}|j }|jd t	|j
 }|j| ||fS t|drTt|drT|d |
 }t	|}||fS td)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   ra   tellrj   r   rk   hasattrNotImplementedError)r6   rC   rb   ra   Z	orig_tellZfilecontentr7   r7   r8   rT      s(   	



zPdfMerger._create_streamc                 C   s   |  t| j|||| dS )aT  
        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.

        :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)rh   rW   rE   )r6   rC   rP   rE   rQ   r7   r7   r8   rU      s   zPdfMerger.appendc                 C   s   | j du r	tt| jD ]$}| j |j tttt	f | j j
 }| j |tj d  |_q|   |   | j |\}}|rI|  dS 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)rF   RuntimeErrorERR_CLOSED_WRITERrE   Zadd_pager0   r   r   rl   r   Z_pages
get_objectZget_referencePAZKIDSr5   _write_dests_write_outlinerM   rN   )r6   rC   rf   Z	pages_objZmy_fileZret_fileobjr7   r7   r8   rM     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)rE   rD   rN   rF   )r6   fo_readerr7   r7   r8   rN   =  s
   

zPdfMerger.closeinfosc                 C   "   | j du 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)rF   rq   rr   add_metadatar6   ry   r7   r7   r8   r{   F  s   
zPdfMerger.add_metadatac                 C      t dd | | dS )zW
        .. deprecated:: 1.28.0

            Use :meth:`add_metadata` instead.
        addMetadatar{   N)r   r{   r|   r7   r7   r8   r~   R     
zPdfMerger.addMetadatalayoutc                 C   r}   )zZ
        .. deprecated:: 1.28.0

            Use :meth:`set_page_layout` instead.
        setPageLayoutset_page_layoutN)r   r   r6   r   r7   r7   r8   r   [  r   zPdfMerger.setPageLayoutc                 C   rz   )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)rF   rq   rr   Z_set_page_layoutr   r7   r7   r8   r   d  s   
zPdfMerger.set_page_layoutmodec                 C   r}   )zX
        .. deprecated:: 1.28.0

            Use :meth:`set_page_mode` instead.
        setPageModeset_page_modeN)r   r   r6   r   r7   r7   r8   r     r   zPdfMerger.setPageModec                 C   rz   )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)rF   rq   rr   r   r   r7   r7   r8   r     s   
zPdfMerger.set_page_modepdfrd   c                 C   s|   g }|  D ]5\}}t| D ],}|j|  |d  kr:|d  |td< t|t|d ks3J ||  nqq|S )zHRemove named destinations that are not a part of the specified page set./Page/Title)itemsr^   rE   rs   r"   r   rU   )r6   r   rd   rE   Z	new_destskeyobjjr7   r7   r8   r]     s   
zPdfMerger._trim_destsc           
      C   s   g }d}t |D ]S\}}t|tr+| |||}|r*|s%|||d   || qd}t| D ])}	|d du r:q1|j|	  |d  krZ|d  |td< || d} nq1q|S )zJRemove outline item entries that are not a part of the specified page set.Tr   Fr   N)		enumeraterX   listr\   rU   r^   rE   rs   r"   )
r6   r   r@   rE   Znew_outlineZprev_header_addedre   rP   subr   r7   r7   r8   r\     s4   



zPdfMerger._trim_outlinec                 C   sv   | j d u r	tt| jD ],}d }d|v r.t| jD ]\}}|j|d kr-|j|td<  nq|d ur8| j 	| qd S )Nr   )
rF   rq   rr   rG   r   rE   r2   r5   r"   Zadd_named_destination_object)r6   
named_destpagenorf   r7   r7   r8   ru     s   

zPdfMerger._write_destsparentc                 C   s   | j d u r	tt|d u r| j}|d usJ dd }|D ]>}t|tr*| || qd }d|v rIt| jD ]\}}|j	|d krH| 
||  nq5|d urZ|d= |d= | j ||}qd S )Nhint for mypyr   /Type)rF   rq   rr   r@   rX   r   rv   r   rE   r2   _write_outline_item_on_pageZadd_outline_item_dict)r6   r@   r   Z
last_addedrP   Zpage_norf   r7   r7   r8   rv     s,   

zPdfMerger._write_outline)rR   rf   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 ]!}||v rWt|| tsW|t||  n|td ||= q@tttjtdttjt|i|td< d S )Nr   z/Zoomr   z/GoToz/A)r   rl   r$   r2   r"   r   FIT_Hr   ZTOPZFIT_BHZFIT_VLEFTZFIT_BVZXYZZFIT_RZBOTTOMRIGHTgetrZ   rX   r#   rU   r    r   r   SDr   )r6   rP   rf   Zoi_typeargsZfit2arg_keysZarg_keyr7   r7   r8   r     s4   




z%PdfMerger._write_outline_item_on_pagec                 C   sv   | j D ]5}d }|d }t|trq|D ]}| |j kr!|j}q|d u r0td|d  dt||td< qd S )Nr   zUnresolved named destination 'r   ')rG   rX   r$   rs   r0   r2   
ValueErrorr"   )r6   rE   r   r   nprf   r7   r7   r8   r_     s   

z#PdfMerger._associate_dests_to_pagesc                 C   s   |d u r| j }|d usJ d|D ]7}t|tr| || qd }|d }t|tr+q|D ]}| |j kr;|j}q-|d urHt||td< qd S )Nr   r   )	r@   rX   r   r`   r$   rs   r0   r2   r"   )r6   rE   r@   rP   r   Zoutline_item_pagepr7   r7   r8   r`   1  s&   

z+PdfMerger._associate_outline_items_to_pagesrootc                 C   sz   |d u r| j }t|D ]/\}}t|tr$| ||}|r#|g|   S q||ks5ttttf |d |kr:|g  S qd S )Nr   )r@   r   rX   r   find_outline_itemr   r   r   )r6   rP   r   re   Zoi_enumresr7   r7   r8   r   J  s   

zPdfMerger.find_outline_itemc                 C   s   |  ||S )zZ
        .. deprecated:: 2.9.0
            Use :meth:`find_outline_item` instead.
        )r   )r6   rP   r   r7   r7   r8   find_bookmarkc  s   
zPdfMerger.find_bookmark/Fittitlepagenumcolorbolditalicfitr   c           
      G   s4   | j }	|	du rtt|	j|||||||g|R  S )a  
        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 pagenum: 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 str fit: The fit of the destination page. See
            :meth:`add_link()<add_link>` for details.
        N)rF   rq   rr   add_outline_item)
r6   r   r   r   r   r   r   r   r   writerr7   r7   r8   r   o  s   zPdfMerger.add_outline_itemc           	      G   (   t dd | j|||||||g|R  S )zZ
        .. deprecated:: 1.28.0
            Use :meth:`add_outline_item` instead.
        addBookmarkr   r   r   	r6   r   r   r   r   r   r   r   r   r7   r7   r8   r        
zPdfMerger.addBookmarkc           	      G   r   )zY
        .. deprecated:: 2.9.0
            Use :meth:`add_outline_item` instead.
        r   r   r   r   r7   r7   r8   add_bookmark  r   zPdfMerger.add_bookmarkc                 C   s   t dd | ||S )z_
        .. deprecated:: 1.28.0
            Use :meth:`add_named_destination` instead.
        addNamedDestinationadd_named_destination)r   r   )r6   r   r   r7   r7   r8   r     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   rG   rU   )r6   r   r   destr7   r7   r8   r     s   zPdfMerger.add_named_destination)FrA   )r3   r?   )NNT)r3   N)NNr4   )NNFFr   )@r:   r;   r<   r=   r   boolr   r   r   r9   rI   r   r   BaseExceptionr   rO   r>   r   rl   r)   rh   r   r   r   rT   r(   rU   rM   rN   r   r   r{   r~   r+   r   r   r-   r   r   r
   r]   r,   r\   ru   r	   r%   r'   rv   r   r/   r   r_   r`   r   r   r!   floatr*   r.   r   r   r   r   r   r7   r7   r7   r8   r?   U   s   




W

# 
 				




"




	

$	

	

r?   c                       s*   e Zd Zdededdf fddZ  ZS )PdfFileMergerr   kwargsr3   Nc                    s<   t dd d|vrt|dk rd|d< t j|i | d S )Nr   r?   rB   r   T)r   rW   superr9   )r6   r   r   	__class__r7   r8   r9     s   
zPdfFileMerger.__init__)r:   r;   r<   r   r9   __classcell__r7   r7   r   r8   r     s    "r   N)=ior   r   r   pathlibr   typesr   typingr   r   r	   r
   r   r   r   r   r   rV   r   Z_pager   rx   r   _utilsr   r   r   r   Z_writerr   	constantsr   r   rt   r   r   Zgenericr   r   r   r    r!   r"   r#   r$   r%   r&   r'   Z	pageranger(   r)   r*   r+   r,   r-   r.   rr   r/   r?   r   r7   r7   r7   r8   <module>   s.   ,4
    ~