U
    dS                     @   s   d dl T d dlmZmZ d dlmZmZ d dlmZ ddl	m
Z
 e
dk rZddlmZ eZndd	lmZ dd
lmZ eZG dd deZG dd deZG dd deZdS )   )*)isStringstr_)PdfFileReaderPdfFileWriter)	PageRange    )version_info)   r   )StringIO)BytesIO)FileIOc                   @   s   e Zd ZdZdd ZdS )_MergedPagez
    _MergedPage is used internally by PdfFileMerger to collect necessary
    information on each page that is being merged.
    c                 C   s   || _ || _d | _|| _d S N)srcpagedataout_pagedataid)selfr   r   r    r   1/tmp/pip-unpacked-wheel-eeeohlmn/PyPDF3/merger.py__init__1   s    z_MergedPage.__init__N)__name__
__module____qualname____doc__r   r   r   r   r   r   ,   s   r   c                   @   s   e Zd ZdZd&ddZd'ddZd(dd	Zd
d Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zd)ddZdd Zd*ddZd+d d!Zd,d"d#Zd$d% ZdS )-PdfFileMergera  
    Initializes a PdfFileMerger object. PdfFileMerger 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 ``True``.
    Tc                 C   s0   g | _ g | _t | _g | _g | _d| _|| _d S )Nr   )inputspagesr   output	bookmarksnamed_destsid_countstrict)r   r#   r   r   r   r   F   s    zPdfFileMerger.__init__Nc                 C   s  d}d}t |r t|d}d}nt|drTt|drT|d | }t|}d}nRt|tr|j	 }	|jd t|j }|j|	 |}t|dr|j
}d}t|| jd	}
|dk	r||
_
|dkrd|
 f}n.t|tr||
 }nt|tstd
g }|r*tt|t| jtd}g }|rJ|
 }| |
||}|rd|  j||g7  _n|  j|7  _|
j}| |
||}|  j|7  _t| D ]:}|
|}| j}|  jd7  _t||
|}|| q|  | | !| || j"||< | j#||
|f dS )a  
        Merges 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 :ref:`Page Range <page-range>` 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``.
        FNrbTseekreadr   _decryption_key)r#   z0"pages" must be a tuple of (start, stop[, step])z/Fitr   )$r   filehasattrr%   r&   StreamIO
isinstancer   streamtellr'   r#   ZgetNumPagesr   indicestuple	TypeErrorBookmarkTextStringObjectNumberObjectr"   
NameObjectZgetOutlines_trim_outliner    ZnamedDestinations_trim_destsr!   rangegetPager   append_associate_dests_to_pages_associate_bookmarks_to_pagesr   r   )r   positionfileobjbookmarkr   import_bookmarksmy_fileZdecryption_keyZfilecontentZ	orig_tellpdfrZsrcpagesoutlinedestsiZpgr   mpr   r   r   mergeO   sf    








zPdfFileMerger.mergec                 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 :ref:`Page Range <page-range>` 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)rF   lenr   )r   r=   r>   r   r?   r   r   r   r9      s    zPdfFileMerger.appendc                 C   s   d}t |rt|d}d}| jD ]4}| j|j | j| jj d d  |_	q | 
  |   | j| |r~|  dS )z
        Writes 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.
        FwbT/KidsN)r   r(   r   r   ZaddPager   ZgetReference_pages	getObjectr   _write_dests_write_bookmarkswriteclose)r   r=   r@   pager   r   r   rO      s    

$zPdfFileMerger.writec                 C   s4   g | _ | jD ]\}}}|r|  qg | _d| _dS )zd
        Shuts all file descriptors (input and output) and clears all memory
        usage.
        N)r   r   rP   r   )r   forA   Zminer   r   r   rP      s    
zPdfFileMerger.closec                 C   s   | 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   addMetadata)r   Zinfosr   r   r   rS      s    zPdfFileMerger.addMetadatac                 C   s   | j | dS )a  
        Set the page layout

        :param str layout: The page layout to be used

        Valid layouts are:
             /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   setPageLayout)r   Zlayoutr   r   r   rT     s    zPdfFileMerger.setPageLayoutc                 C   s   | j | dS )a  
        Set the page mode.

        :param str mode: The page mode to use.

        Valid modes are:
            /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   setPageMode)r   moder   r   r   rU     s    zPdfFileMerger.setPageModec           	      C   s   g }d}t | D ]j\}}t| D ]X}|| |d  kr$|d  |td< t|t|d ksnt||  qq$q|S )zg
        Removes any named destinations that are not a part of the specified
        page set.
        T/Page/Title)	listitemsr7   r8   rL   r4   r   AssertionErrorr9   )	r   pdfrC   r   Z	new_destsprev_header_addedkojr   r   r   r6   #  s    
zPdfFileMerger._trim_destsc           
      C   s   g }d}t |D ]\}}t|trV| |||}|r|sJ|||d   || qd}t| D ]D}	||	 |d  krb|d  |td< || d} qqbq|S )zm
        Removes any outline/bookmark entries that are not a part of the
        specified page set.
        Tr   FrW   )		enumerater+   rY   r5   r9   r7   r8   rL   r4   )
r   r\   rB   r   Znew_outliner]   rD   r_   subr`   r   r   r   r5   3  s"    

zPdfFileMerger._trim_outlinec                 C   sv   | j }|D ]f}d }d }d|kr\t| jD ]2\}}|j|d kr(|j|td< |}|j} q\q(|d kr
| j| q
d S )NrW   )	r!   ra   r   r   r   r4   r   r   ZaddNamedDestinationObject)r   rC   vpagenor\   rD   pr   r   r   rM   K  s    zPdfFileMerger._write_destsc           
      C   s  |d kr| j }d }|D ]j}t|tr4| || qd }d }d|kr`t| jD ]\}}|j|d krPt|jt|d g}	|d dks|d dkrd|krt|d t	s|	
t|d  n|	
td |d= nN|d dks|d dkr8d	|kr t|d	 t	s |	
t|d	  n|	
td |d	= n|d d
krd	|krtt|d	 t	st|	
t|d	  n|	
td d|krt|d t	s|	
t|d  n|	
td d|krt|d t	s|	
t|d  n|	
td |d= |d= |d	= n|d dkr&d	|krLt|d	 t	sL|	
t|d	  n|	
td d|krt|d t	s|	
t|d  n|	
td d|krt|d t	s|	
t|d  n|	
td d|kr t|d t	s |	
t|d  n|	
td |d	= |d= |d= |d= ttdtdtdt|	i|td< |}|j} q`qP|d kr|d= |d= | j||}qd S )NrW   z/Type/FitHz/FitBHz/Topr   z/FitVz/FitBVz/Leftz/XYZz/Zoomz/FitRz/Bottomz/Right/S/GoTo/D/A)r    r+   rY   rN   ra   r   r   r3   r4   Z
NullObjectr9   ZFloatObjectDictionaryObjectArrayObjectr   r   ZaddBookmarkDict)
r   r    parentZ
last_addedbrd   r\   rD   re   argsr   r   r   rN   [  sn    




(zPdfFileMerger._write_bookmarksc                 C   sv   | j D ]j}d }|d }t|tr"q|D ]}| |j kr&|j}q&|d kr^t||td< qtd|d f qd S )NrW   z!Unresolved named destination '%s'rX   )r!   r+   r3   rL   r   r   r4   
ValueError)r   r   Zndrd   npre   r   r   r   r:     s    

z'PdfFileMerger._associate_dests_to_pagesc                 C   s   |d kr| j }|D ]}t|tr.| || qd }|d }t|trFq|D ]}| |j krJ|j}qJ|d krt||td< qt	d|d f qd S )NrW   zUnresolved bookmark '%s'rX   )
r    r+   rY   r;   r3   rL   r   r   r4   rp   )r   r   r    rn   rd   Zbpre   r   r   r   r;     s     

z+PdfFileMerger._associate_bookmarks_to_pagesc                 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 )NrX   )r    ra   r+   rY   findBookmark)r   r>   rootrD   rn   resr   r   r   rr     s    
zPdfFileMerger.findBookmarkc           	      C   s   |dkrt | jd g}nt|tr*|}n
| |}tt|t|tdtd}|dkrh| j	| nd| j}|dd D ]}|| }qz|d d }|t |k rt|| tr|| 	| n|
||g |S )a  
        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.
        Nr   rf   :  rJ   )rG   r    r+   rY   rr   r1   r2   r3   r4   r9   insert)	r   titlepagenumrm   ZilocdestZbmparentrD   Znposr   r   r   addBookmark  s     	


zPdfFileMerger.addBookmarkc                 C   s.   t t|t|td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.
        rf   ru   N)ZDestinationr2   r3   r4   r!   r9   )r   rw   rx   ry   r   r   r   addNamedDestination  s    z!PdfFileMerger.addNamedDestination)T)NNT)NNT)NN)N)N)N)r   r   r   r   r   rF   r9   rO   rP   rS   rT   rU   r6   r5   rM   rN   r:   r;   rr   rz   r{   r   r   r   r   r   8   s$   
	
h


J


r   c                   @   s.   e Zd Zd
ddZdd Zdd Zdd	 ZdS )OutlinesObjectNc                 C   s    t |  || _|| _|| _d S r   )rY   r   treer\   rm   )r   r\   r}   rm   r   r   r   r     s    
zOutlinesObject.__init__c                 C   s   | | }| |= | j | d S r   )r}   removeChild)r   indexobjr   r   r   remove  s    zOutlinesObject.removec                 C   s   | j | j jd | }t }|tdt|tdtdgtdtdi | j |}t	 }|td|tdt
|i | j | | j| d S )	NrI   ri   rf   ru   rg   rh   rj   rX   )r\   rL   rK   rk   updater4   rl   r3   Z
_addObjectZ
TreeObjectZcreateStringObjectr}   ZaddChild)r   rw   rx   ZpageRefactionZ	actionRefr>   r   r   r   add  s$        zOutlinesObject.addc                 C   s2   dd | j  D D ]}| j | |   qd S )Nc                 S   s   g | ]}|qS r   r   ).0xr   r   r   
<listcomp>'  s     z,OutlinesObject.removeAll.<locals>.<listcomp>)r}   childrenr~   pop)r   childr   r   r   	removeAll&  s    zOutlinesObject.removeAll)N)r   r   r   r   r   r   r   r   r   r   r   r|     s   
r|   N)Zgenericutilsr   r   r\   r   r   Z	pageranger   sysr	   	cStringIOr   r*   ior   r   r(   objectr   r   rY   r|   r   r   r   r   <module>   s       R