U
    
3g7                    @   s  d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	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mZ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# dd	l$m%Z%m&Z& dd
l'm(Z( ddl)m*Z*m+Z+m,Z, ddl-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5 ddl6m7Z7 ddl6m8Z9 ddl6m:Z: ddl6m;Z< ddl6m=Z> ddl6m?Z?m@Z@mAZAmBZBmCZC ddl6mDZE ddl6mFZG ddl6mHZI ddl6mJZK ddl6mLZLmMZM ddlNmOZOmPZPmQZQmRZRmSZSmTZTmUZUmVZVmWZWmXZXmYZYmZZZm[Z[m\Z\m]Z]m^Z^m_Z_m`Z`maZambZbmcZcmdZd ddlemfZfmgZg ddlmhZhmiZimjZjmkZkmlZlmmZmmnZn eoepZqe@d ZreMdZsG dd dZte eeuef euevee f e^ddd Zwe deZf eue eexexexf eudf eyeyebd!d"d#ZzG d$d% d%etZ{dS )&    N)md5)BytesIOFileIOIOBase)Path)TracebackType)IOAnyCallableDequeDictIterableListOptionalPatternTupleTypeUnioncast   )
Encryption)
PageObject_VirtualList)	PdfReader)_alg33_alg34_alg35)StrByteType
StreamType_get_max_pdf_version_headerb_deprecate_with_replacementdeprecation_bookmarkdeprecation_with_replacementlogger_warning)AnnotationDictionaryAttributes)CatalogAttributes)CatalogDictionary)Core)EncryptionDictAttributes)FieldDictionaryAttributes	FieldFlag"FileSpecificationDictionaryEntriesGoToActionArgumentsInteractiveFormDictEntries)PageAttributes)PagesAttributes)StreamAttributes)TrailerKeys)TypFitArgumentsUserAccessPermissions)PAGE_FITAnnotationBuilderArrayObjectBooleanObjectByteStringObjectContentStreamDecodedStreamObjectDestinationDictionaryObjectFitFloatObjectIndirectObject
NameObject
NullObjectNumberObject	PdfObjectRectangleObjectStreamObjectTextStringObject
TreeObjectcreate_string_object
hex_to_rgb)	PageRangePageRangeSpec)BorderArrayTypeFitType
LayoutTypeOutlineItemTypeOutlineTypePagemodeTypeZoomArgTypeic                   @   s  e Zd ZdZd#eddddZd ddd	Zeee	  ee	 ee
 dd
ddZeedddZejeddddZeedddZd$edeef ee edddZeeef edddZd%eeeegdf ee edddZddddZd&eee ed d!d"Zd'eee ed d#d$Zd(eeee ed&d'd(Z d)eeee ed&d)d*Z!d*ee ee ed+d,d-Z"eed.d/d0Z#edd1d2Z$edd3d4Z%ee&e dd5d6Z'd+ee( ee( ed7d8d9Z)d,ee( ee( ed7d:d;Z*d-ee+j, ee+j, eed<d=d>Z-d.ee+j, ee+j, eed<d?d@Z.eede/e0e1f ddAdBZ2e2jedee/ef ddCdDdBZ2eddEdFdGZ3eddEdHdIZ4eeeef ddJdKdLZ5eeeef ddMdNdOZ6d/e7eeegdf  ddPdQdRZ8d0e7eeegdf  ddPdSdTZ9e:fee;eef e<ddUdVdWZ=e:fee;eef e<ddUdXdYZ>e7ddZd[d\Z?e7ddZd]d^Z@d1e7eeegdf  ddPd_d`ZAd2e7eeegdf  ddPdadbZBdddceCddfee ee eDeEee ee ddddedfZFeGddgdhdiZHeeIef eJeDeKf dgdjdkZLeGe&e dgdldmZMeGe&e edndodpZNeGddgdqdrZOe;eef ddsdtduZPe;eef ddsdvdwZQeeReSeTeUeeVeeWe0eXf
 ddxdydzZYeed{d|d}ZZeedd~dZ[eedddZ\e]dddZ^eRdddZ_eeRdddZ`e]dddZaeRdddZbeRdddZcd3edee]f ede]ef ede]ef edee]f edddZdd4eee]f ede]ef edddZed5eee] edddZfegddd6ehede]ef ede]ef edddZiegddd7ehee] edddZjegddd8ehee] edddZkdddddeldfeedeeef ede]ef ede]ef eeeJe(e(e(f ef  eDeDemee ed
ddZnd9eeede]ef eeJe(e(e(f  eDeDeoeped	ddZqd:eeede]ef eeJe(e(e(f  eDeDeoeped	ddZrddddZse0eeeRf ddddZtd;ee ee edddZue/edCddZvd<eee ee edddZweeedddZxddddZyddddZzd=eDddddZ{d>eDddddÄZ|d?eDddddńZ}d@eDddddǄZ~dAeeeeeR ee ddȜddʄZdBeeeeeR dd˜dd̈́ZdCeeeeeR eoepddΜddЄZdDeeeeeR eoepddΜdd҄ZdZee dddՄZee dddׄZeeVef dd؜ddڄZedd؜dd܄Zedd؜ddބZeee dddZejedd؜ddZeee dddZejedd؜ddZdZee dddZee dddZeddddZeddddZeee dddZejeddddZeee dddZejeddddZee;eef ddddZeeef edddZeeIee7f eJeee f dddZdEeee7eIf eedeeJeef eJeeef e&e f edeeJeef eJeeef e&e f eDeee&e eJedf f  dddd ZegddddFee eeIee7f ee ee eDeee&e eJedf f  ddddZeTe;eef e7edddZeeef e;eef e7dd	d
dZedeeeeXf e;eef e7ee dddZeee&eT f ee;eef e7e&e/ dddZee;eef e7e&e/ dddZe/e]dCddZdGe&e/ ee]ef ede]ef ddddZddddZdHe;eef ee ee&e  dddZegdddIe;eef ee ee&e  ddd ZdJede7ef ddZd!d"ZdS (K  	PdfWriterz
    This class supports writing PDF files out, given pages produced by another
    class (typically :class:`PdfReader<PyPDF2.PdfReader>`).
     N)fileobjreturnc                 C   s   d| _ g | _i | _i | _t }|ttjtdttj	t
dttjt i | || _t }|tdttjdd i | || _t | _| jttjttjttj| ji | | j| _|| _d| _d S )Ns   %PDF-1.3z/Pagesr   z	/ProducerZPyPDF2zutf-16beF)_header_objects_idnum_hash_id_translatedr=   updaterA   PATYPECOUNTrC   KIDSr7   _add_object_pagesrI   codecsBOM_UTF16_BEencode_info_root_objectCOZCATALOGZPAGES_rootrV   with_as_usage)selfrV   pagesinfo rn   2/tmp/pip-unpacked-wheel-ifm06wwb/PyPDF2/_writer.py__init__   sF          zPdfWriter.__init__)rW   c                 C   s
   d| _ | S )z+Store that writer is initialized by 'with'.T)rj   rk   rn   rn   ro   	__enter__   s    zPdfWriter.__enter__)exc_typeexc	tracebackrW   c                 C   s   | j r| | j  dS )zWrite data to the fileobj.N)rV   write)rk   rs   rt   ru   rn   rn   ro   __exit__   s    zPdfWriter.__exit__c                 C   s   | j S )z
        Header of the PDF document that is written.

        This should be something like b'%PDF-1.5'. It is recommended to set the
        lowest version that supports all features which are used within the
        PDF file.
        rX   rq   rn   rn   ro   
pdf_header   s    	zPdfWriter.pdf_header)
new_headerrW   c                 C   s
   || _ d S Nrx   )rk   rz   rn   rn   ro   ry      s    objrW   c                 C   sB   t |dr|jj| kr|jS | j| tt| jd| |_|jS )Nindirect_referencer   )hasattrr~   pdfrY   appendr@   lenrk   r}   rn   rn   ro   ra      s
    zPdfWriter._add_object)r~   idorW   c                 C   sp   |d k	r*|d k	rt dn|}tdt |d k	s6tt|trN| j|d  S |j| kr`t d| j|j	d  S )NzGPlease only set 'indirect_reference'. The 'ido' argument is deprecated.zGThe parameter 'ido' is depreciated and will be removed in PyPDF2 4.0.0.r   zpdf must be self)

ValueErrorwarningswarnDeprecationWarningAssertionError
isinstanceintrY   r   idnum)rk   r~   r   rn   rn   ro   
get_object   s"    

zPdfWriter.get_object)r   rW   c                 C   s   t ddd | |S )zU
        .. deprecated:: 1.28.0

            Use :meth:`get_object` instead.
        	getObjectr   3.0.0)r#   r   )rk   r   rn   rn   ro   r      s    zPdfWriter.getObjectrn   )pageactionexcluded_keysrW   c                 C   s  t t|tj tjkst|}t|}|tjdg7 }z| j	t
|jj |jj= W n tk
rd   Y nX t d|| d|}|jd k	r|jj}t|tr| }t| j|| _| j|ttj< t t| | j}|jd k	st||tj |j t t|tj }t|d |ttj< |S )Nz/StructParentsr   Fr   )r   strr]   r^   rh   ZPAGEr   listPARENTr[   idr~   r   r   	Exceptionclonery   r   re   r   rb   rA   r=   r   r`   r   r_   rC   )rk   r   r   r   Zpage_orgotherrl   Z
page_countrn   rn   ro   	_add_page   s.    

zPdfWriter._add_pagec              
   C   s   zV| j }tj|kr6| j ttjtt| jd| i ttj	}t
d| j tj |< W n2 tk
r } ztdt| W 5 d }~X Y nX d S )Nr   Tz&set_need_appearances_writer() catch : )rg   r'   Z	ACRO_FORMr\   rA   r@   r   rY   r.   ZNeedAppearancesr8   r   loggererrorrepr)rk   catalogZneed_appearancesrt   rn   rn   ro   set_need_appearances_writer  s     
   
z%PdfWriter.set_need_appearances_writer)r   r   rW   c                 C   s   |  |tj|S )ar  
        Add a page to this PDF file.
        Recommended for advanced usage including the adequate excluded_keys

        The page is usually acquired from a :class:`PdfReader<PyPDF2.PdfReader>`
        instance.

        :param PageObject page: The page to add to the document. Should be
            an instance of :class:`PageObject<PyPDF2._page.PageObject>`
        )r   r   r   rk   r   r   rn   rn   ro   add_page2  s    zPdfWriter.add_pagec                 C   s   t ddd | ||S )zS
        .. deprecated:: 1.28.0

            Use :meth:`add_page` instead.
        addPager   r   )r#   r   r   rn   rn   ro   r   C  s    
zPdfWriter.addPager   )r   indexr   rW   c                    s   |  | fddS )a  
        Insert a page in this PDF file. The page is usually acquired from a
        :class:`PdfReader<PyPDF2.PdfReader>` instance.

        :param PageObject page: The page to add to the document.
        :param int index: Position at which the page will be inserted.
        c                    s   |   |S r{   )insert)lpr   rn   ro   <lambda>]      z'PdfWriter.insert_page.<locals>.<lambda>)r   rk   r   r   r   rn   r   ro   insert_pageP  s    zPdfWriter.insert_pagec                 C   s   t ddd | |||S )zV
        .. deprecated:: 1.28.0

            Use :meth:`insert_page` instead.
        
insertPager   r   )r#   r   r   rn   rn   ro   r   _  s    zPdfWriter.insertPage)page_number
pageNumberrW   c                 C   sr   |dk	r(|dk	rt dtddd |}|dkr@|dkr@t dttttf | | j}tt|t	j
 |  S )z
        Retrieve a page by number from this PDF file.

        :param int page_number: The page number to retrieve
            (pages begin at zero)
        :return: the page at the index given by *page_number*
        Nz)Please only use the page_number parameterzget_page(pageNumber)zget_page(page_number)4.0.0zPlease specify the page_number)r   r!   r   r   r   r	   r   rb   r   r]   r`   )rk   r   r   rl   rn   rn   ro   get_pagem  s    
  zPdfWriter.get_page)r   rW   c                 C   s   t ddd | |S )zd
        .. deprecated:: 1.28.0

            Use :code:`writer.pages[page_number]` instead.
        getPagezwriter.pages[page_number]r   )r#   r   )rk   r   rn   rn   ro   r     s    zPdfWriter.getPagec                 C   s*   t tttf | | j}t|td S )Nz/Count)r   r   r   r	   r   rb   r   rA   )rk   rl   rn   rn   ro   _get_num_pages  s    zPdfWriter._get_num_pagesc                 C   s   t ddd |  S )z\
        .. deprecated:: 1.28.0

            Use :code:`len(writer.pages)` instead.
        getNumPageszlen(writer.pages)r   )r#   r   rq   rn   rn   ro   r     s    zPdfWriter.getNumPagesc                 C   s   t | j| jS )zNProperty that emulates a list of :class:`PageObject<PyPDF2._page.PageObject>`.)r   r   r   rq   rn   rn   ro   rl     s    zPdfWriter.pages)widthheightrW   c                 C   s   t | ||}| | |S )a  
        Append a blank page to this PDF file and returns it. If no page size
        is specified, use the size of the last page.

        :param float width: The width of the new page expressed in default user
            space units.
        :param float height: The height of the new page expressed in default
            user space units.
        :return: the newly appended page
        :raises PageSizeNotDefinedError: if width and height are not defined
            and previous page does not exist.
        )r   create_blank_pager   )rk   r   r   r   rn   rn   ro   add_blank_page  s    
zPdfWriter.add_blank_pagec                 C   s   t ddd | ||S )zY
        .. deprecated:: 1.28.0

            Use :meth:`add_blank_page` instead.
        addBlankPager   r   )r#   r   )rk   r   r   rn   rn   ro   r     s    zPdfWriter.addBlankPage)r   r   r   rW   c                 C   sX   |dks |dkr:|   d |kr:| j| }|jj}|jj}t| ||}| || |S )a8  
        Insert a blank page to this PDF file and returns it. If no page size
        is specified, use the size of the last page.

        :param float width: The width of the new page expressed in default user
            space units.
        :param float height: The height of the new page expressed in default
            user space units.
        :param int index: Position to add the page.
        :return: the newly appended page
        :raises PageSizeNotDefinedError: if width and height are not defined
            and previous page does not exist.
        Nr   )r   rl   Zmediaboxr   r   r   r   r   )rk   r   r   r   Zoldpager   rn   rn   ro   insert_blank_page  s     
zPdfWriter.insert_blank_pagec                 C   s   t ddd | |||S )zZ
        .. deprecated:: 1.28.0

            Use :meth:`insertBlankPage` instead.
        insertBlankPager   r   )r#   r   )rk   r   r   r   rn   rn   ro   r     s    zPdfWriter.insertBlankPagec              
   C   s   d| j krdS | j d }t|ttfr2tt|S t|trz8|dd \}}|dd }t|t|}td||W S  t	k
r } zt	d| d| W 5 d}~X Y qX ndS dS )a  
        Property to access the opening destination ("/OpenAction" entry in the
        PDF catalog).
        it returns `None` if the entry does not exist is not set.

        :param destination:.
        the property can be set to a Destination, a Page or an string(NamedDest) or
            None (to remove "/OpenAction")

        (value stored in "/OpenAction" entry in the Pdf Catalog)
        /OpenActionNr      Z
OpenActionzInvalid Destination : )
rg   r   r   bytesrI   r7   r>   tupler<   r   )rk   Zoar   typarrayfitrt   rn   rn   ro   open_destination  s    


(zPdfWriter.open_destination)destrW   c                 C   s   |d kr,z| j d= W q tk
r(   Y qX nnt|trJt|| j td< nPt|trf|j| j td< n4t|trtd|j	d k	r|j	nt
 tj| j td< d S )Nr   ZOpening)rg   KeyErrorr   r   rG   rA   r<   
dest_arrayr   r~   rB   r5   rk   r   rn   rn   ro   r     s"    


)
javascriptrW   c              	   C   s   d| j krt | j ttj< tt| j tj }d|krPttdt i|td< tttt|d d }t }|ttj	tdtdtdtdt
| i |ttt  || | dS )a  
        Add Javascript which will launch upon opening this PDF.

        :param str javascript: Your Javascript.

        >>> output.add_js("this.print({bUI:true,bSilent:false,bShrinkToFit:true});")
        # Example: This will launch the print window when the PDF is opened.
        z/Namesz/JavaScriptz/Action/Sz/JSN)rg   r=   rA   CANAMESr   r7   r\   r]   r^   rG   r   rI   r   uuidZuuid4ra   )rk   r   namesZjs_listZjsrn   rn   ro   add_js  s.    

    zPdfWriter.add_jsc                 C   s   t ddd | |S )zQ
        .. deprecated:: 1.28.0

            Use :meth:`add_js` instead.
        addJSr   r   )r#   r   )rk   r   rn   rn   ro   r   ;  s    zPdfWriter.addJS)filenamedatarW   c                 C   s   t  }|| |ttjtdi t }|td|i t }|ttjtdttjt	|ttj
|i t }|ttjtt	||gi t }|td|i | jttj|i dS )a  
        Embed a file inside the PDF.

        :param str filename: The filename to display.
        :param str data: The data in the file.

        Reference:
        https://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf
        Section 7.11.3
        z/EmbeddedFile/Fz	/Filespecz/EmbeddedFilesN)r;   set_datar\   rA   r]   r^   r=   r,   FrI   ZEFr   r   r7   rg   )rk   r   r   Z
file_entryZef_entryZfilespecZembedded_files_names_dictionaryZembedded_files_dictionaryrn   rn   ro   add_attachmentD  s<    
    

zPdfWriter.add_attachment)fnamefdatarW   c                 C   s   t ddd | ||S )zY
        .. deprecated:: 1.28.0

            Use :meth:`add_attachment` instead.
        addAttachmentr   r   )r#   r   )rk   r   r   rn   rn   ro   r     s    zPdfWriter.addAttachment)readerafter_page_appendrW   c                 C   s@   t |j}t|D ](}|j| }| |}t|r|| qdS )a  
        Copy pages from reader to writer. Includes an optional callback parameter
        which is invoked after pages are appended to the writer.

        :param PdfReader reader: a PdfReader object from which to copy page
            annotations to this writer object.  The writer's annots
            will then be updated
        :param Callable[[PageObject], None] after_page_append:
            Callback function that is invoked after each page is appended to
            the writer. Signature includes a reference to the appended page
            (delegates to append_pages_from_reader). The single parameter of the
            callback is a reference to the page just appended to the document.
        N)r   rl   ranger   callable)rk   r   r   Zreader_num_pagesZreader_page_numberZreader_pageZwriter_pagern   rn   ro   append_pages_from_reader  s    


z"PdfWriter.append_pages_from_readerc                 C   s   t ddd | || dS )zc
        .. deprecated:: 1.28.0

            Use :meth:`append_pages_from_reader` instead.
        appendPagesFromReaderr   r   N)r#   r   rk   r   r   rn   rn   ro   r     s    
  zPdfWriter.appendPagesFromReader)r   fieldsflagsrW   c                 C   s  |    tj|kr tdt dS tt|tj D ]}|tj |  }i }tj|kr`|tj }|D ]}|	t
j|kr|	t
jdkr|ttjt|| i |tt
jt|| i |r|tt
jt|i qd|	t
j|krd|tt
jt|| i qdq2dS )a  
        Update the form field values for a given page from a fields dictionary.

        Copy field texts and values from fields to page.
        If the field links to a parent object, add the information to the parent.

        :param PageObject page: Page reference from PDF writer where the
            annotations and field data will be updated.
        :param dict fields: a Python dictionary of field names (/T) and text
            values (/V)
        :param int flags: An integer (0 to 7). The first bit sets ReadOnly, the
            second bit sets Required, the third bit sets NoExport. See
            PDF Reference Table 8.70 for details.
        z No fields to update on this pageNz/Btn)r   PGANNOTSr$   __name__r   r   r   r   getr*   TZFTr\   rA   r%   ZASVrG   ZFfrC   )rk   r   r   r   jZwriter_annotZwriter_parent_annotfieldrn   rn   ro   update_page_form_field_values  sT    




   z'PdfWriter.update_page_form_field_valuesc                 C   s   t ddd | |||S )zh
        .. deprecated:: 1.28.0

            Use :meth:`update_page_form_field_values` instead.
        updatePageFormFieldValuesr   r   )r#   r   )rk   r   r   r   rn   rn   ro   r     s      z#PdfWriter.updatePageFormFieldValues)r   rW   c                 C   s   t t|jtj | _dS )z
        Copy the reader document root to the writer.

        :param reader:  PdfReader from the document root should be copied.
        N)r   r=   trailerTKROOTrg   rk   r   rn   rn   ro   clone_reader_document_root  s    z$PdfWriter.clone_reader_document_rootc                 C   s   t ddd | | dS )ze
        .. deprecated:: 1.28.0

            Use :meth:`clone_reader_document_root` instead.
        cloneReaderDocumentRootr   r   N)r#   r   r   rn   rn   ro   r   %  s      z!PdfWriter.cloneReaderDocumentRootc                 C   s   |  | | || dS )a)  
        Create a copy (clone) of a document from a PDF file reader

        :param reader: PDF file reader instance from which the clone
            should be created.
        :param Callable[[PageObject], None] after_page_append:
            Callback function that is invoked after each page is appended to
            the writer. Signature includes a reference to the appended page
            (delegates to append_pages_from_reader). The single parameter of the
            callback is a reference to the page just appended to the document.
        N)r   r   r   rn   rn   ro   clone_document_from_reader0  s    
z$PdfWriter.clone_document_from_readerc                 C   s   t ddd | || dS )ze
        .. deprecated:: 1.28.0

            Use :meth:`clone_document_from_reader` instead.
        cloneDocumentFromReaderr   r   N)r#   r   r   rn   rn   ro   r   D  s    
  z!PdfWriter.cloneDocumentFromReaderT)user_passwordowner_password
use_128bitpermissions_flaguser_pwd	owner_pwdrW   c                 C   s  |dk	r(|dk	rt dntd |}|dkr8t d|dk	rx|dk	rRt dn&d}d}tj| d| d	td
 |}|dkr|}|rd}	d}
td}nd}	d}
td}|}tt|||
|}tttt		 
d }tttt 
d }t||f| _|
dkr(t||||\}}n&|
dks6tt||
||||d\}}t }td|ttj< t|	|td< |	dkrt|d |ttj< t|
|ttj< t||ttj< t||ttj< t||ttj< | || _|| _dS )a  
        Encrypt this PDF file with the PDF Standard encryption handler.

        :param str user_password: The "user password", which allows for opening
            and reading the PDF file with the restrictions provided.
        :param str owner_password: The "owner password", which allows for
            opening the PDF files without any restrictions.  By default,
            the owner password is the same as the user password.
        :param bool use_128bit: flag as to whether to use 128bit
            encryption.  When false, 40bit encryption will be used.  By default,
            this flag is on.
        :param unsigned int permissions_flag: permissions as described in
            TABLE 3.20 of the PDF 1.7 specification. A bit value of 1 means the
            permission is grantend. Hence an integer value of -1 will set all
            flags.
            Bit position 3 is for printing, 4 is for modifying content, 5 and 6
            control annotations, 9 for form fields, 10 for extraction of
            text and graphics.
        NzGPlease only set 'user_password'. The 'user_pwd' argument is deprecated.z|Please use 'user_password' instead of 'user_pwd'. The 'user_pwd' argument is deprecated and will be removed in PyPDF2 4.0.0.zuser_password may not be NonezIThe argument owner_pwd of encrypt is deprecated. Use owner_password only.r   r   G is deprecated as an argument and will be removed in PyPDF2 4.0.0. Use  insteadmessagecategoryr      g      0@r   g      @utf8Fz	/Standard/V   ) r   r   r   r   r   r9   r   r   r   timere   digestrandomr7   _IDr   r   r   r=   rA   SAZFILTERrC   ZLENGTHEDROUPra   _encrypt_encrypt_key)rk   r   r   r   r   r   r   old_termnew_termr   revZkeylenr  r
  ZID_1ZID_2r  keyencryptrn   rn   ro   r  S  sh    


zPdfWriter.encrypt)streamrW   c                 C   s   t |dr(d|jkr(td|j dt | js<| | j| _| | j | 	|}| 
||}| | |td| d d S )NmodebzFile <zH> to write to is not in binary mode. It may not be written to correctly.z
startxref
z
%%EOF
)r   r  r$   namer   ri   ra   rg   _sweep_indirect_references_write_header_write_xref_table_write_trailerrv   r    )rk   r  object_positionsxref_locationrn   rn   ro   write_stream  s    


zPdfWriter.write_streamc                 C   s^   d}|dkrt d| dt|ttfr>t|d}d| _d}| | | jrV|  ||fS )ae  
        Write the collection of pages added to this object out as a PDF file.

        :param stream: An object to write the file to.  The object can support
            the write method and the tell method, similar to a file object, or
            be a file path, just like the fileobj, just named it stream to keep
            existing workflow.
        FrU   zOutput(stream=z) is empty.wbT)r   r   r   r   r   rj   r  close)rk   r  Zmy_filern   rn   ro   rv     s    	

zPdfWriter.writec           
      C   s$  g }| | jd  | d t| jD ]\}}| j| }|d k	r(|d }||  | tt|d  d }t| dr|| j	j
krtd|d d d }tddd d	 }| j| | }t|t| jd
 kstt| }	|	d tdt| jd
  }||| | d q(|S )N   
s   %
r   s    0 obj
r  z<ir   r   r         s   
endobj
)rv   ry   	enumeraterY   r   tellr    r   r   r  r   structpackr  r   r   r   r  minwrite_to_stream)
rk   r  r  ir}   r   r  Zpack1Zpack2Zmd5_hashrn   rn   ro   r    s(    

zPdfWriter._write_header)r  r  rW   c                 C   s|   |  }|d |tdt| jd  d |tddddd	d
 |D ]"}|t|dddd	d qT|S )Ns   xref
z0 r   
r   z0>10 i  z0>5z f 
z n 
)r%  rv   r    r   rY   )rk   r  r  r  offsetrn   rn   ro   r    s    
  zPdfWriter._write_xref_tablec                 C   s   | d t }|ttjtt| jd ttj	| j
ttj| ji t| drd| j|ttj< t| dr~| j|ttj< ||d  d S )Ns   trailer
r   r  r  )rv   r=   r\   rA   r   ZSIZErC   r   rY   r   ri   INFOrf   r   r  ZIDr  ZENCRYPTr)  )rk   r  r   rn   rn   ro   r    s     
   

zPdfWriter._write_trailer)infosrW   c                 C   s@   i }t | D ]\}}t||t|< q| | 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.
        N)r   itemsrI   rA   r   rf   r\   )rk   r/  argsr  valuern   rn   ro   add_metadata  s    zPdfWriter.add_metadatac                 C   s   t ddd | | dS )zW
        .. deprecated:: 1.28.0

            Use :meth:`add_metadata` instead.
        addMetadatar3  r   N)r#   r3  )rk   r/  rn   rn   ro   r4  !  s    zPdfWriter.addMetadata)rootrW   c                 C   s~  t  }g }d }g }d }|||||f t|rz| \}}}}t|ttfr| D ],\}}	||	|||d k	r~||g ng f qZnNt|t	r|j
| kr| |}t||kr|t| || d d g f t|ttfr*t|tr| | |}g }
|| |kr4| gdd |D  }
|||< |
D ]>}| j|d }|d k	r8| }|d k	r8|| j| < q8q*d S )Nc                 S   s   g | ]}|  qS rn   )
hash_value).0Zgrant_parentrn   rn   ro   
<listcomp>j  s    z8PdfWriter._sweep_indirect_references.<locals>.<listcomp>)collectionsdequer   r   popr   r7   r=   r0  r@   r   _resolve_indirect_objectr   r   rF   ra   r6  rZ   )rk   r5  stackZ
discoveredparentZgrant_parentsZ	key_or_idr   r  r2  Zupdate_hashesZold_hashr~   Zindirect_reference_objrn   rn   ro   r  *  sT    





z$PdfWriter._sweep_indirect_references)r   rW   c                 C   s   t |jdr*|jjjr*td|jjj |j| kr8|S |j|}|dkrntd|jj	 d| dt	 t
 }| }|| jkr| j| S |j| krt|jd| | j|< n| || j|< | j| S )z
        Resolves indirect object to this pdf indirect objects.

        If it is a new object then it is added to self._objects
        and new idnum is given and generation is always 0.
        r  zI/O operation on closed file: NzUnable to resolve [r   z], returning NullObject insteadr   )r   r   r  closedr   r  r   r$   	__class__r   rB   r6  rZ   r@   r   ra   )rk   r   Zreal_objr6  rn   rn   ro   r<  {  s$    



z"PdfWriter._resolve_indirect_objectc                 C   s0   | j |d }t|d| }| |ks,t|S Nr   r   )rY   r   r@   r   r   )rk   r}   r   refrn   rn   ro   get_reference  s    zPdfWriter.get_referencec                 C   s   t ddd | |S )zX
        .. deprecated:: 1.28.0

            Use :meth:`get_reference` instead.
        getReferencerC  r   )r#   rC  r   rn   rn   ro   rD    s    zPdfWriter.getReferencec                 C   sz   t j| jkrLtt| jt j }| j|d }t|d| }| |ksvt	n*t }|
i  | |}|| jtt j< |S rA  )rh   OUTLINESrg   r   rH   rY   r   r@   r   r   r\   ra   rA   )rk   outliner   Zoutline_refrn   rn   ro   get_outline_root  s    

zPdfWriter.get_outline_rootc                 C   s:   t j| jkr tt| jt j }nt }|| jtt j< |S )u   
        the list of threads see §8.3.2 from PDF 1.7 spec

                :return: an Array (possibly empty) of Dictionaries with "/F" and "/I" properties
        )rh   ZTHREADSrg   r   r7   rA   )rk   threadsrn   rn   ro   get_threads_root  s
    zPdfWriter.get_threads_rootc                 C   s   |   S )u   
        Read-only property for the list of threads see §8.3.2 from PDF 1.7 spec

        :return: an Array (possibly empty) of Dictionaries with "/F" and "/I" properties
        )rI  rq   rn   rn   ro   rH    s    zPdfWriter.threadsc                 C   s   t ddd |  S )z[
        .. deprecated:: 1.28.0

            Use :meth:`get_outline_root` instead.
        getOutlineRootrG  r   )r#   rG  rq   rn   rn   ro   rJ    s    zPdfWriter.getOutlineRootc                 C   s"  t j| jkrt| jt j trtt| jt j }|j}t j|krt|t j trtt|t j }|j}t j|krtt|t j }qt }||t	t j< n2t }| 
|}||t	t j< t }||t	t j< nRt }| 
|}|| jt	t j< t }| 
|}||t	t j< t }||t	t j< |S r{   )r   r   rg   r   r=   r   r~   ZDESTSr7   rA   ra   )rk   r   Z	names_refZdestsZ	dests_refndrn   rn   ro   get_named_dest_root  s6    
 



zPdfWriter.get_named_dest_rootc                 C   s   t ddd |  S )z^
        .. deprecated:: 1.28.0

            Use :meth:`get_named_dest_root` instead.
        getNamedDestRootrL  r   )r#   rL  rq   rn   rn   ro   rM    s    zPdfWriter.getNamedDestRoot)page_destinationr>  beforer   rW   c                 C   s   |d k	r|d k	rt d|d k	rFd}d}tj| d| dtd |}|d krVt d|d krf|  }tt| }| |}|d k	r|j	}|
|||  |S )Nz[The argument dest of add_outline_item_destination is deprecated. Use page_destination only.r   rN  r   r   r    page_destination may not be None)r   r   r   r   rG  r   rH   r   ra   r~   insert_child)rk   rN  r>  rO  r   r  r  page_destination_refrn   rn   ro   add_outline_item_destination  s,    
z&PdfWriter.add_outline_item_destination)r   r>  rW   c                 C   s   t ddd | ||S )zf
        .. deprecated:: 2.9.0

            Use :meth:`add_outline_item_destination` instead.
        add_bookmark_destinationrS  r   r#   rS  rk   r   r>  rn   rn   ro   rT  0  s    
  z"PdfWriter.add_bookmark_destinationc                 C   s   t ddd | ||S )zg
        .. deprecated:: 1.28.0

            Use :meth:`add_outline_item_destination` instead.
        addBookmarkDestinationrS  r   rU  rV  rn   rn   ro   rW  ?  s      z PdfWriter.addBookmarkDestinationoutline_item)bookmark)rX  r>  rO  rW   c           
      C   s   t  }t| D ]\}}||tt|< q|| d|krt }tt|d }t| D ]\}}||tt|< q^| |}	|	|td< | 	|||S )N/A)
rH   r   r0  rA   r   r\   r=   r   ra   rS  )
rk   rX  r>  rO  Zoutline_item_objectkvr   Za_dict
action_refrn   rn   ro   add_outline_item_dictL  s    

zPdfWriter.add_outline_item_dict)rX  r>  rW   c                 C   s   t ddd | ||S )z_
        .. deprecated:: 2.9.0

            Use :meth:`add_outline_item_dict` instead.
        add_bookmark_dictr^  r   r#   r^  rk   rX  r>  rn   rn   ro   r_  b  s    	  zPdfWriter.add_bookmark_dictc                 C   s   t ddd | ||S )z`
        .. deprecated:: 1.28.0

            Use :meth:`add_outline_item_dict` instead.
        addBookmarkDictr^  r   r`  ra  rn   rn   ro   rb  p  s    	  zPdfWriter.addBookmarkDictF)
titler   r>  rO  colorbolditalicr   pagenumrW   c
              
   C   sD  t |tr6|dk	r|dkr|}| |||d||||S |dk	rN|	dk	rNtd|dkr\d}
nt |trl|}nJt |tr~|j}n8t |trz| j| j}W n t	k
r   t
|}Y nX |dkrtd| t t }ttd| d ||}| tttj|jttjtdi}
t|
||||}|dkr6|  }| |||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 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 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 or as a Hex String (#RRGGBB)
        :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.
        NMThe argument pagenum of add_outline_item is deprecated. Use page_number only.zcan not find reference of page /z outline item/GoTo)r   r>   add_outline_itemr   r@   r   r~   r   rl   
IndexErrorrC   r$   r   rB   r<   rA   ra   r=   r-   Dr   S_create_outline_itemrG  rS  )rk   rc  r   r>  rO  rd  re  rf  r   rg  r]  page_refr   rX  rn   rn   ro   rk  ~  sh    
       


  
zPdfWriter.add_outline_item/Fit)	rc  rg  r>  rd  re  rf  r   r1  rW   c           	      G   s*   t ddd | ||||||t||dS )zZ
        .. deprecated:: 2.9.0

            Use :meth:`add_outline_item` instead.
        add_bookmarkrk  r   Zfit_typefit_argsr#   rk  r>   	rk   rc  rg  r>  rd  re  rf  r   r1  rn   rn   ro   rr    s    
zPdfWriter.add_bookmarkc           	      G   s,   t ddd | |||d|||t||dS )z[
        .. deprecated:: 1.28.0

            Use :meth:`add_outline_item` instead.
        addBookmarkrk  r   Nrs  ru  rv  rn   rn   ro   rw    s    
zPdfWriter.addBookmarkc                 C   s   t dd S )NzIThis method is not yet implemented. Use :meth:`add_outline_item` instead.)NotImplementedErrorrq   rn   rn   ro   add_outline  s    zPdfWriter.add_outline)rc  destinationrW   c                 C   sd   |   }d}|t|k rN||| k rD||| ||t| d S |d7 }q|t||g d S )Nr   r   )rL  r   r   rG   extend)rk   rc  rz  rK  r*  rn   rn   ro   add_named_destination_array  s    
z%PdfWriter.add_named_destination_array)rN  r   rW   c                 C   s|   |d k	r|d k	rt d|d k	rFd}d}tj| d| dtd |}|d krVt d| |j}| td|d	 | |S )
Nz[The argument dest of add_named_destination_object is deprecated. Use page_destination only.r   rN  r   r   r   rP  rG   /Title)r   r   r   r   ra   r   r|  r   )rk   rN  r   r  r  rR  rn   rn   ro   add_named_destination_object  s(     z&PdfWriter.add_named_destination_objectc                 C   s   t ddd | |S )zg
        .. deprecated:: 1.28.0

            Use :meth:`add_named_destination_object` instead.
        addNamedDestinationObjectr~  r   )r#   r~  r   rn   rn   ro   r  3  s      z#PdfWriter.addNamedDestinationObject)rc  r   rg  rW   c           
      C   s   |d k	r|d k	rt d|d k	rFd}d}tj| d| dtd |}|d krVt d| | jtj | }t }|	t
tjt|t
tjtdgt
tjt
d	i | |}|  }	t|tstt|}|	||g |S )
Nrh  rg  r   r   r   r   zpage_number may not be Nonei:  rj  )r   r   r   r   r   rb   r]   r`   r=   r\   rA   r-   rm  r7   r3   ZFIT_HrC   rn  ra   rL  r   rG   r   r{  )
rk   rc  r   rg  r  r  rp  r   Zdest_refrK  rn   rn   ro   add_named_destination@  s>      	

zPdfWriter.add_named_destination)rc  rg  rW   c                 C   s   t ddd | ||S )z`
        .. deprecated:: 1.28.0

            Use :meth:`add_named_destination` instead.
        addNamedDestinationr  r   )r#   r  )rk   rc  rg  rn   rn   ro   r  i  s      zPdfWriter.addNamedDestinationc                 C   sR   t t| | j}t t|tj }|D ]&}t t| |}tj|kr&|tj= q&dS )z.Remove links and annotations from this output.N)	r   r=   r   rb   r7   r]   r`   r   r   )rk   pg_dictrl   r   rp  rn   rn   ro   remove_linksv  s    
zPdfWriter.remove_linksc                 C   s   t ddd |  S )zW
        .. deprecated:: 1.28.0

            Use :meth:`remove_links` instead.
        removeLinksr  r   )r#   r  rq   rn   rn   ro   r    s    zPdfWriter.removeLinks)ignore_byte_string_objectrW   c                 C   st  t t| | j}t t|tj }d}|D ]B}t t| |}|d  }t|ts`t||}g }d}	|j	D ]\}
}|dkr|
d }|rt|t
st
 |
d< nn|dkr|
d }|rt|t
st
 |
d< nD|dkrtt|
d D ](}|rt|
d | t
st
 |
d |< q|d	krd
}	|dkr*d}	|	r<||kr<qn|dkrHqn||
|f qn||_	|td| q*dS )z
        Remove images from this output.

        :param bool ignore_byte_string_object: optional parameter
            to ignore ByteString Objects.
        )s   cm   w   J   j   M   ds   ri   is   gs   W   b   s   S   f   F   n   m   l   c   v   y   h   Bs   Dos   sh	/ContentsFs   Tj   'r      "r      TJ   qT   Qs   reN)r   r=   r   rb   r7   r]   r`   r   r:   
operationsrG   r   r   r   __setitem__rA   )rk   r  r  rl   Zjump_operatorsr   rp  contentZ_operationsZseq_graphicsoperandsoperatortextr*  rn   rn   ro   remove_images  sV    


  

 


zPdfWriter.remove_images)ignoreByteStringObjectrW   c                 C   s   t ddd | |S )zX
        .. deprecated:: 1.28.0

            Use :meth:`remove_images` instead.
        removeImagesr  r   )r#   r  rk   r  rn   rn   ro   r    s    zPdfWriter.removeImagesc                 C   s  t t| | j}t tt |tj }|D ]N}t t| |}|d  }t	|t
s`t
||}|jD ] \}}|dkr|d }	|st	|	trt |d< nt	|	ttfrt |d< qf|dkr|d }	|st	|	trt |d< nt	|	ttfrt |d< qf|dkrftt|d D ]V}
|s>t	|d |
 trdt |d |
< n&t	|d |
 ttfrt |d |
< qqf|td| q*dS )z
        Remove text from this output.

        :param bool ignore_byte_string_object: optional parameter
            to ignore ByteString Objects.
        r  r  r   r  r   r  N)r   r=   r   rb   r   r@   r]   r`   r   r   r:   r  rG   r9   r   r   r  rA   )rk   r  r  rl   r   rp  r  r  r  r  r*  rn   rn   ro   remove_text  sB    





 zPdfWriter.remove_textc                 C   s   t ddd | |S )zV
        .. deprecated:: 1.28.0

            Use :meth:`remove_text` instead.
        
removeTextr  r   )r#   r  r  rn   rn   ro   r    s    zPdfWriter.removeText)r   urirectborderrg  rW   c                 C   s  |dk	rt jdtd |}| | jtj | }ttt	t
f | |}|dk	rdd |dd D }t|dkrtdd |d D }	||	 ntd	gd }t|t	rt|}nt|trnt|}t }
|
td
tdtdt|i t }|ttjttjttjtdttj|ttj|tdtdttjt|td|
i | |}tj|kr~|tj | nt|g|ttj< dS )a  
        Add an URI from a rectangular area to the specified page.
        This uses the basic structure of :meth:`add_link`

        :param int page_number: index of the page on which to place the URI action.
        :param str uri: URI of resource to link to.
        :param Tuple[int, int, int, int] rect: :class:`RectangleObject<PyPDF2.generic.RectangleObject>` or array of four
            integers specifying the clickable rectangular area
            ``[xLL, yLL, xUR, yUR]``, or string in the form ``"[ xLL yLL xUR yUR ]"``.
        :param ArrayObject border: if provided, an array describing border-drawing
            properties. See the PDF spec for details. No border will be
            drawn if this argument is omitted.
        NzoThe 'pagenum' argument of add_uri is deprecated and will be removed in PyPDF2 4.0.0. Use 'page_number' instead.)r   c                 S   s   g | ]}t |qS rn   rA   r7  nrn   rn   ro   r8  8  s     z%PdfWriter.add_uri.<locals>.<listcomp>r      c                 S   s   g | ]}t |qS rn   r  r  rn   rn   ro   r8  :  s     r   r   z/URI/Linkz/H/IrZ  )r   r   r   r   rb   r]   r`   r   r   r   r	   r   r7   r   rC   r   rA   rE   r=   r\   rG   r%   r   r   r   ZSubtyper  ZRectZBorderra   )rk   r   r  r  r  rg  Z	page_linkrp  Z
border_arrZdash_patternZlnk2ZlnkZlnk_refrn   rn   ro   add_uri  sf    


         
zPdfWriter.add_uri)rg  r  r  r  rW   c                 C   s   t ddd | ||||S )zR
        .. deprecated:: 1.28.0

            Use :meth:`add_uri` instead.
        addURIr  r   )r#   r  )rk   rg  r  r  r  rn   rn   ro   r  b  s    zPdfWriter.addURI)rg  rN  r  r  r   r1  rW   c                 G   sz   t dd t|tr>| dd }tdd |dD }nt|trJnt|}tj|||t||dd	}| j	||d
S )Nadd_link+add_annotation(AnnotationBuilder.link(...))r   c                 S   s    g | ]}t |d krt|qS )r   )r   float)r7  numrn   rn   ro   r8    s      z&PdfWriter.add_link.<locals>.<listcomp>r,  rs  )r  r  target_page_indexr   )r   
annotation)
r#   r   r   striprE   splitr6   linkr>   add_annotation)rk   rg  rN  r  r  r   r1  r  rn   rn   ro   r  q  s&    	 


zPdfWriter.add_linkc                 G   s$   t ddd | j|||||f| S )zS
        .. deprecated:: 1.28.0

            Use :meth:`add_link` instead.
        addLinkr  r   )r!   r  )rk   rg  rN  r  r  r   r1  rn   rn   ro   r    s      zPdfWriter.addLink)z	/NoLayoutz/SinglePagez
/OneColumnz/TwoColumnLeftz/TwoColumnRightz/TwoPageLeftz/TwoPageRightc                 C   s.   zt t| jd W S  tk
r(   Y d S X d S )N/PageLayout)r   rO   rg   r   rq   rn   rn   ro   _get_page_layout  s    zPdfWriter._get_page_layoutc                 C   s   t ddd |  S )Y
        .. deprecated:: 1.28.0

            Use :py:attr:`page_layout` instead.
        getPageLayoutpage_layoutr   )r#   r  rq   rn   rn   ro   r    s    zPdfWriter.getPageLayout)layoutrW   c                 C   sP   t |ts8|| jkr0tddd| jf t t|}| jtd|i 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
        zLayout should be one of: rU   r  N)r   rA   _valid_layoutsr$   joinr   rg   r\   rk   r  rn   rn   ro   _set_page_layout  s    

zPdfWriter._set_page_layoutc                 C   s   |  | 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  r  rn   rn   ro   set_page_layout  s    zPdfWriter.set_page_layoutc                 C   s   t ddd | |S )r  zwriter.setPageLayout(val)zwriter.page_layout = valr   )r#   r  r  rn   rn   ro   setPageLayout  s      zPdfWriter.setPageLayoutc                 C   s   |   S )a  
        Page layout property.

        .. list-table:: Valid ``layout`` values
           :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
        )r  rq   rn   rn   ro   r    s    zPdfWriter.page_layoutc                 C   s   |  | d S r{   r  r  rn   rn   ro   r    s    c                 C   s   t ddd | jS )r  
pageLayoutr  r   r#   r  rq   rn   rn   ro   r    s    zPdfWriter.pageLayoutc                 C   s   t ddd || _dS )r  r  r  r   Nr  r  rn   rn   ro   r  )  s    )z/UseNonez/UseOutlinesz
/UseThumbsz/FullScreenz/UseOCz/UseAttachmentsc                 C   s.   zt t| jd W S  tk
r(   Y d S X d S )N	/PageMode)r   rR   rg   r   rq   rn   rn   ro   _get_page_mode<  s    zPdfWriter._get_page_modec                 C   s   t ddd |  S )W
        .. deprecated:: 1.28.0

            Use :py:attr:`page_mode` instead.
        getPageMode	page_moder   )r#   r  rq   rn   rn   ro   r  B  s    zPdfWriter.getPageMode)r  rW   c                 C   sR   t |tr|}n*|| jkr2tdd| j t t|}| jtd|i dS )r  zMode should be one of: z, r  N)r   rA   _valid_modesr$   r  r   rg   r\   )rk   r  Z	mode_namern   rn   ro   set_page_modeK  s    

 zPdfWriter.set_page_modec                 C   s   t ddd | | dS )r  zwriter.setPageMode(val)zwriter.page_mode = valr   N)r#   r  rk   r  rn   rn   ro   setPageMode[  s      zPdfWriter.setPageModec                 C   s   |   S )a  
        Page mode property.

        .. list-table:: Valid ``mode`` values
           :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
        )r  rq   rn   rn   ro   r  f  s    zPdfWriter.page_modec                 C   s   |  | d S r{   )r  r  rn   rn   ro   r  }  s    c                 C   s   t ddd | jS )r  pageModer  r   r#   r  rq   rn   rn   ro   r    s    zPdfWriter.pageModec                 C   s   t ddd || _dS )r  r  r  r   Nr  r  rn   rn   ro   r    s    )r   r  rW   c                 C   s   t tt|}| | jd | |td< | j| }|jd krLt |td< |jd k	sZt	|
ddkrtd|krt t|td }ttd|d t|d	 t|d
 d}|j|td< | |}|j| d S )Nz/Kids/P/Annots/Subtyper  /Destz	/LinkNamer  r   rt  rs  )r   r=   _pdf_objectifyr   rb   rA   rl   annotationsr7   r   r   dictr<   r>   r   ra   r   )rk   r   r  to_addr   tmpr   Zind_objrn   rn   ro   r    s&    

 

zPdfWriter.add_annotation)r   rW   c                 C   s   t d| }|dg D ]v}| }|dd}|dd}t|trZt||td< q|dk	r| }|dd}t|trt||td< q|S )z
        Perform some clean up in the page.
        Currently: convert NameObject nameddestination to TextStringObject (required for names/dests list)
        r   r  r  NrZ  /D)r   r   r   r   rA   rG   )rk   r   aZa_objdZactrn   rn   ro   
clean_page  s    

zPdfWriter.clean_pagec              	   C   s   d }t |ttfr6t|d}t| }W 5 Q R X nt |tr~|jrL|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.)r   r   r   r   r   r  r   _encryptionr  r%  r  r   rx  )rk   rV   encryption_objfr  Z	orig_tellZfilecontentrn   rn   ro   _create_stream  s&    	



zPdfWriter._create_stream.)rV   rX  rl   import_outlineexcluded_fieldsrW   c                 C   sj   |dkrd}t |tttfrRt |tr8t |ts4|}|}|}| d|d||| n| d||||| dS )a0  
        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 a string to build an outline
            (aka 'bookmark') to identify the
            beginning of the included file.

        :param pages: can be a :class:`PageRange<PyPDF2.pagerange.PageRange>`
            or a ``(start, stop[, step])`` tuple
            or a list of pages to be processed
            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``.

        :param List excluded_fields: provide the list of fields/keys to be ignored
            if "/Annots" is part of the list, the annotation will be ignored
            if "/B" is part of the list, the articles will be ignored
        Nrn   )r   r   r   rK   boolmerge)rk   rV   rX  rl   r  r  rn   rn   ro   r     s"    '

     zPdfWriter.appendr  )rY  Zimport_bookmarks)positionrV   rX  rl   r  r  rW   c                 C   s  t |tr|}n| |\}}	t|dd}|dkr6d}|dkrTttdt|j}nft |trxtt|t|j }nBt |trn6t |t	rt|dkrtt| }nt |t	st
di }
|D ]}|j| }|jdk	st|dkr
| |t|dd	g |
|jj< n*| ||t|dd	g |
|jj< |d
7 }||
|jj _q|j|_|j D ]Z}|j}t |d trrn<|d jj|
krV|
|d jj j|td< | |d | qV|dk	rtd| jt|t|
 d jtd }n|  }td|jtj  }|r<t!j"|kr<| #|$t!j"d|
|}| %||d d	|kr|
 D ]D}| &|j$d	d||
|}t|dkr||t'd	< | (| qNd|kr| )d|
| dS )ae  
        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 a string to build an outline
            (aka 'bookmark') to identify the
            beginning of the included file.

        :param pages: can be a :class:`PageRange<PyPDF2.pagerange.PageRange>`
            or a ``(start, stop[, step])`` tuple
            or a list of pages to be processed
            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``.

        :param List excluded_fields: provide the list of fields/keys to be ignored
            if "/Annots" is part of the list, the annotation will be ignored
            if "/B" is part of the list, the articles will be ignored
        F)strictNrn   r   r   z:"pages" must be a tuple of (start, stop[, step]) or a list/Br  r   /Pager}  rH   )r   r=   rU   )*r   r   r  r   r   r   rl   rK   indicesr   	TypeErrorr~   r   r   r   r   original_pageZnamed_destinationsZ_namedDestsvaluesr   rB   rC   r|  r   rk  rG   r5   r   rG  r   r   r   rh   rE  _get_filtered_outliner   _insert_filtered_outline_insert_filtered_annotationsrA   r  add_filtered_articles)rk   r  rV   rX  rl   r  r  r   r  r  Zsrcpagesr*  Zpgr   arrZoutline_item_typZ_rorF  paglstrn   rn   ro   r  	  s    '





   

	    
   
zPdfWriter.merge)threadrl   r   rW   c                 C   sz  |j | ddd}| j|j td|d }|}d}|dk	rd| td|d ||}|dk	r,|dkrtd| t  }|}	|j|t	d< n4td| tt	d	|ji }
|
j|t	d
< |
}||t	d< |j|t	d< |d |t	d< td| }d|krt
 |t	d< td|d |j td|d
 }||kr4|	j|t	d
< |j|	t	d	< d}q4|jdk	stt|jS )zE
        clone the thread with only the applicable articles

        T)r   )Zforce_duplicateignore_fieldsr=   r   Nr   r  r  z/N/Tz/Rr  r7   )r   rH  r   r~   r   _get_cloned_pagera   r=   r   rA   r7   r   )rk   r  rl   r   ZnthreadZfirst_articleZcurrent_articleZnew_articler  Z	new_firstZnew_article2Zpag_objrn   rn   ro   _add_articles_thread	  sb    
  
  

zPdfWriter._add_articles_thread)fltrrl   r   rW   c                 C   s   t |trt|}nt |ts*td}| D ]^}|j}|ddD ]F}| d }|j	j
| jt| krH||d d rH| ||| qHq2dS )z<
        Add articles matching the defined criteria
        rU   r  rn   r  r  r}  N)r   r   recompiler   r  r  r   r   r~   r   r[   r   searchr	  )rk   r
  rl   r   r   ppr  Zthrrn   rn   ro   r  	  s    	



zPdfWriter.add_filtered_articles)r   rl   r   rW   c                 C   s   t |trd S t |tr&|j| j}n0t |trH|dddkrH|j}nt |trV|}z||j jW S  t	k
rz   Y d S X d S )N/TyperU   r  )
r   rB   r   rl   r~   r=   r   r@   r   r   )rk   r   rl   r   Z_irn   rn   ro   r  	  s    


zPdfWriter._get_cloned_page)annotsr   rl   r   rW   c                 C   s  t  }t|trtd| }|D ]}td| }|d dksjd|ksjtd|d d dksjd|krd|kr||| j n|d }t|trt|| 	 kr||| j n^td	|}| 
|d
 ||}	|	d k	r|j| dd}
t |	g|dd   |
td< ||
j q"td|d d }t|tr`t|| 	 kr||| j q"td	|}| 
|d
 ||}	|	d k	r"|j| dd}
td|
}
t |	g|dd   td|
d td< ||
j q"|S )Nr   r=   r  r  rZ  r   rj  r  r7   r   )r  )r  r   r  )r  )r7   r   r@   r   r   r   r   r~   r   rL  r  rA   )rk   r  r   rl   r   ZoutlistZanZanor  r   Zancrn   rn   ro   r    
  sP    







z&PdfWriter._insert_filtered_annotations)noderl   r   rW   c                 C   s  g }|  }|dddks$d|krT|dd}|dk	r|  }|| |||7 }n|dk	r|  }td||}| td|d	 ||}|dkrt }||td	< d|kr| |d |||_ng |_t	|d	 trt
|jd
kr|| |dd}qT|S )zEExtract outline item entries that are part of the specified page set.r  rU   	/Outlinesr}  /FirstNr<   r   r  r   /Next)r   r   r  r   Z_build_outline_itemr  rB   rA   childsr   r   r   )rk   r  rl   r   Znew_outlineor\  rn   rn   ro   r  3
  s*    
zPdfWriter._get_filtered_outlinec                 C   s   t  }| | t|d |td< t|d tsn|jd k	r`d|jkr`|jd | |td< n|j|td< |jd k	rt	|j
dd|td< t|j
dtdtdtdg|td< |S )	Nr}  r  rZ  r  r   r   /Cg        )rH   ra   rG   rA   r   rB   r  r   r   rC   r   r7   r?   )rk   r   Zn_olrn   rn   ro   _clone_outlineS
  s     

 zPdfWriter._clone_outline)outlinesr>  rO  rW   c                 C   s^   |D ]T}| dddks d|kr&|}n"| |}tt| |||  | |j|d  qd S )Nr  rU   r  r}  )r   r  r   rH   r   rQ  r  r  )rk   r  r>  rO  r   nprn   rn   ro   r  j
  s    
z"PdfWriter._insert_filtered_outlinec                 C   s   dS )z"To match the functions from MergerNrn   rq   rn   rn   ro   r   z
  s    zPdfWriter.close)rX  r5  rW   c                 C   s   |d kr|   }n
td|}d}|d k	r|j|ksB|dd |krH|gS d|kr| |tt|d }|rd|krx|gng | S d|kr|d7 }tt|d }q d S q d S )NrH   r   r}  r  r  r   )rG  r   r~   r   find_outline_itemrQ   rH   )rk   rX  r5  r  r*  resrn   rn   ro   r  
  s*    

 zPdfWriter.find_outline_itemc                 C   s   |  ||S )zZ
        .. deprecated:: 2.9.0
            Use :meth:`find_outline_item` instead.
        )r  )rk   rX  r5  rn   rn   ro   find_bookmark
  s    
zPdfWriter.find_bookmarkc                 C   s   |dkri | _ nnt|trBz| j t|= W q~ tk
r>   Y q~X n<t|trvz| j t|j= W q~ tk
rr   Y q~X ntddS )a)  
        reset the translation table between reader and the writer object.
        late cloning will create new independent objects

        :param reader: PdfReader or IndirectObject refering a PdfReader object.
                       if set to None or omitted, all tables will be reset.
        Nzinvalid parameter {reader})r[   r   r   r   r   r@   r   r   rn   rn   ro   reset_translation
  s    


zPdfWriter.reset_translation)rU   )NN)rn   )rn   )rn   )r   rn   )r   rn   )NN)NN)NN)NNr   )NNr   )N)N)N)N)NNNN)N)N)NN)N)N)NNFFrq  )NNFFrq  )NN)NN)F)F)F)F)NN)N)Nrq  )Nrq  )NNTN)NNTrn   )N)N)N)N)r   
__module____qualname____doc__r   rp   rr   r   r   BaseExceptionr   rw   propertyr   ry   setterrD   r@   ra   r   r   r   r   r   r
   r	   r   r   r   r   r   r   r   r   r   r   r   r   r   rl   r  r   r   decimalDecimalr   r   r<   rG   r9   r   r   r   r   r   r   r   r   OPTIONAL_READ_WRITE_FIELDr   r+   r   r   r   r   r   r   ALL_DOCUMENT_PERMISSIONSr  r4   r  r   r  r   r   r   rv   r  r  r  r3  r4  r7   r8   r=   r?   rA   rC   rB   r  r<  rC  rD  rH   rG  rI  rH  rJ  rL  rM  rS  rT  rW  r"   rP   r^  r_  rb  r5   r>   rk  rN   rS   rr  rw  ry  r|  r~  r  r  r  r  r  r  r  r  r  rE   r  r  r  r  r  rO   r  r  r  r  r  r  r  r  rR   r  r  r  r  r  r  r  r  r   r   r  rK   r   rL   r  r	  r   r  r  r   r  r  r  r   rQ   r  r  r  rn   rn   rn   ro   rT      s  (


	 
"     		          "	S 

E
^ 	Q&		#   (
    P         
  * 		N- P $ 
	!						)   $"5    
;



5
 




rT   r|   c                 C   s   t | tr| S t | trLt }|  D ] \}}t|}t|}|||< q&|S t | trxt }| D ]}|	t| q`|S t | t
r| drt| S t| S n*t | ttfrt| S tdt|  dd S )Nri  z
type(obj)=z! could not be casted to PdfObject)r   rD   r  r=   r0  rA   r  r   r7   r   r   
startswithrG   r   r  r?   rx  type)r}   r  r  r2  Zname_keyZcasted_valuer  elrn   rn   ro   r  
  s.    






r  )r]  rc  rd  rf  re  rW   c                    s   t  }| d k	r| |td< |tdt|i |rtt|trFt|}td |tdt	 fdd|D i |s||rd}|r|d7 }|r|d	7 }|td
t
|i |S )NrZ  r}  z1.00000r  c                    s    g | ]}t t| qS rn   )r?   r%  r&  quantize)r7  cprecrn   ro   r8  
  s     z(_create_outline_item.<locals>.<listcomp>r   r   r   r   )rH   rA   r\   rI   r   r   rJ   r%  r&  r7   rC   )r]  rc  rd  rf  re  rX  Zformat_flagrn   r.  ro   ro  
  s6     

 ro  c                       s&   e Zd Zeedd fddZ  ZS )PdfFileWriterN)r1  kwargsrW   c                    s   t ddd t j|| d S )Nr0  rT   r   )r#   superrp   )rk   r1  r1  r@  rn   ro   rp     s    zPdfFileWriter.__init__)r   r  r   r	   rp   __classcell__rn   rn   r3  ro   r0    s   r0  )|rc   r9  r%  loggingr  r  r&  r  r   r   hashlibr   ior   r   r   pathlibr   typesr   typingr   r	   r
   r   r   r   r   r   r   r   r   r   r   r  r   Z_pager   r   Z_readerr   Z	_securityr   r   r   _utilsr   r   r   r    r!   r"   r#   r$   	constantsr%   r&   r   r'   r(   rh   r)   r  r*   r+   r,   r-   r.   r/   r   r0   r]   r1   r  r2   r   r3   r4   Zgenericr5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rF   rG   rH   rI   rJ   Z	pagerangerK   rL   rM   rN   rO   rP   rQ   rR   rS   	getLoggerr   r   r'  r(  rT   r   r   r  r  r  ro  r0  rn   rn   rn   ro   <module>   s   <(
`$

                    R(
$