From f2f9a4b687fd7a62d90fc648516cb03436b61e63 Mon Sep 17 00:00:00 2001 From: Craig Jones Date: Tue, 11 Aug 2020 11:43:32 -0700 Subject: [PATCH 1/5] Added to gitignore: .venv .vscode --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 782ab4a934..ddd15c5da6 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,6 @@ build htmlcov/ .coverage MANIFEST +.venv +.vscode + From 0ddeb69ac0e12ab1c92db2e78d99ff0bb5d4c157 Mon Sep 17 00:00:00 2001 From: Craig Jones Date: Tue, 11 Aug 2020 11:45:05 -0700 Subject: [PATCH 2/5] Added some details to the docs for the existing sample code. --- samplecode/README.md | 22 +++++++++++++++++++--- samplecode/basic_features.py | 5 +++++ samplecode/basic_merging.py | 4 +++- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/samplecode/README.md b/samplecode/README.md index 823c4908a4..35509a5608 100644 --- a/samplecode/README.md +++ b/samplecode/README.md @@ -1,7 +1,6 @@ # PyPDF4 Sample Code Folder -This will contain demonstrations of the many features PyPDF4 is capable of. -Example code should make it easy for users to know how to use all aspects of -PyPDF4. +This folder contains demonstrations of just a few of PyPDF4's many features. + ## How to run Invoke the Python interpeter you prefer by specifying the script you wish to @@ -11,6 +10,23 @@ python2 ./samplecode/basic_features.py python3 ./samplecode/basic_features.py ``` +## `basic_features.py` + +Sample code that demonstrates: + +* Getting metadata from a PDF. +* Copying a PDF, one page at a time, and performing different operations on each page (resize, rotate, add a watermark). +* Encrypting a PDF. +* Adding javascript that runs when the PDF is opened. + + +## `basic_merging.py` + +Sample code that demonstrates merging together three PDFs into one, picking and choosing which pages appear in which order. +Selected pages can be added to the end of the output PDF being built, or inserted in the middle. + + + ## Contributing to `samplecode` Feel free to add any type of PDF file or sample code, either by: diff --git a/samplecode/basic_features.py b/samplecode/basic_features.py index b3df9a0b3c..982ff07c1d 100644 --- a/samplecode/basic_features.py +++ b/samplecode/basic_features.py @@ -1,6 +1,11 @@ #!/usr/bin/env python """ Showcases basic features of PyPDF. + +* Getting metadata from a PDF. +* Copying a PDF, one page at a time, and performing different operations on each page (resize, rotate, add a watermark). +* Encrypting a PDF. +* Adding javascript that runs when the PDF is opened. """ from __future__ import print_function diff --git a/samplecode/basic_merging.py b/samplecode/basic_merging.py index 855db803b2..0a3f977739 100644 --- a/samplecode/basic_merging.py +++ b/samplecode/basic_merging.py @@ -1,6 +1,8 @@ #!/usr/bin/env python """ -Merges three PDF documents input from the command line. +Sample code that demonstrates merging together three PDFs into one, picking and choosing which pages appear in which order. +Selected pages can be added to the end of the output PDF being built, or inserted in the middle. +This example takes input from the command line. """ from __future__ import print_function From b55f2064862557af389c540b1e93913005c7b67e Mon Sep 17 00:00:00 2001 From: Craig Jones Date: Tue, 11 Aug 2020 11:53:56 -0700 Subject: [PATCH 3/5] Added sample code that copies a PDF, changing field values along the way (i.e. using a PDF with fillable fields as a template). This required modifying the PdfFileWriter.updatePageFormFieldValues() method (in pdf.py) to let you flag the filled-in field as read-only. This also required adding a new method to PdfFileWriter called have_viewer_render_fields(). It sets the /AcroForm/NeedAppearances flag. The example PDF (fillable_form.pdf) was created in LibreOffice using the attached fillable_form.odt document. NOTE: updatePageFormFieldValues() didn't have a unit test that I could see. When I added one, I also had to fix two adjacent tests (to close the temp file before deleting it) to get test_pdf.py running again. NOTE: I'm not set up for tox at the moment. I tested it using 3.8 only. --- pypdf/pdf.py | 20 +++++- samplecode/README.md | 9 ++- samplecode/fillable_fields.py | 61 ++++++++++++++++++ samplecode/fillable_form.odt | Bin 0 -> 10776 bytes samplecode/fillable_form.pdf | Bin 0 -> 19884 bytes .../fillable_form.pdf | Bin 0 -> 19884 bytes tests/test_pdf.py | 61 +++++++++++++++--- 7 files changed, 141 insertions(+), 10 deletions(-) create mode 100644 samplecode/fillable_fields.py create mode 100644 samplecode/fillable_form.odt create mode 100644 samplecode/fillable_form.pdf create mode 100644 tests/fixture_data/testUpdatePageFormFieldValues/fillable_form.pdf diff --git a/pypdf/pdf.py b/pypdf/pdf.py index da10e9beae..0ce880a226 100644 --- a/pypdf/pdf.py +++ b/pypdf/pdf.py @@ -526,7 +526,7 @@ def appendPagesFromReader(self, reader, afterPageAppend=None): if callable(afterPageAppend): afterPageAppend(writerPage) - def updatePageFormFieldValues(self, page, fields): + def updatePageFormFieldValues(self, page, fields, read_only = False): """ Update the form field values for a given page from a fields dictionary. Copy field texts and values from fields to page. @@ -545,6 +545,24 @@ def updatePageFormFieldValues(self, page, fields): writer_annot.update( {NameObject("/V"): TextStringObject(fields[field])} ) + if read_only: + writer_annot.update({NameObject("/Ff"): NumberObject(1)}) + + def have_viewer_render_fields(self): + """ + Some PDF viewers need to be coaxed into rendering field values. + This does so by setting a `/NeedAppearances` attribute to True + (which adds to the processing time slightly). + Credit for figuring this out: https://stackoverflow.com/users/8382028/viatech + """ + try: + catalog = self._rootObject + if "/AcroForm" not in catalog: + self._rootObject.update({NameObject("/AcroForm"): IndirectObject(len(self._objects), 0, self)}) + need_appearances = NameObject("/NeedAppearances") + self._rootObject["/AcroForm"][need_appearances] = BooleanObject(True) + except Exception as e: + warnings.warn("Unable to set the /NeedAppearances flag. Filled-in field values may not render correctly. [{}]".format(repr(e))) def cloneReaderDocumentRoot(self, reader): """ diff --git a/samplecode/README.md b/samplecode/README.md index 35509a5608..8e11cafdb4 100644 --- a/samplecode/README.md +++ b/samplecode/README.md @@ -8,7 +8,7 @@ run, e.g.: ``` python2 ./samplecode/basic_features.py python3 ./samplecode/basic_features.py -``` +``` ## `basic_features.py` @@ -26,6 +26,13 @@ Sample code that demonstrates merging together three PDFs into one, picking and Selected pages can be added to the end of the output PDF being built, or inserted in the middle. +## `fillable_fields.py` + +Sample code that copies a PDF, changing field values along the way (i.e. using +a PDF with fillable fields as a template). + +FYI: The fillable_form.pdf used in this demo was created via LibreOffice. + ## Contributing to `samplecode` Feel free to add any type of PDF file or sample code, either by: diff --git a/samplecode/fillable_fields.py b/samplecode/fillable_fields.py new file mode 100644 index 0000000000..8e3e004f19 --- /dev/null +++ b/samplecode/fillable_fields.py @@ -0,0 +1,61 @@ +""" +Sample code that copies a PDF, changing field values along the way (i.e. using +a PDF with fillable fields as a template). + +FYI: The fillable_form.pdf used in this demo was created via LibreOffice. +""" +import sys +from pypdf import PdfFileWriter, PdfFileReader + +root_folder = "samplecode/" +template_name = "fillable_form.pdf" + +def discover_fields(template_pdf): + available_fields = template_pdf.getFields() + if available_fields: + print("Available fields:") + for fieldname in available_fields: + print(" %s" % fieldname) + else: + print("ERROR: '" + template_name + "' has no text fields.") + sys.exit(1) + +def fill_in_pdf(template_pdf, field_values, filename): + output = PdfFileWriter(filename) + output.have_viewer_render_fields() + for page_no in range(template_pdf.numPages): + template_page = template_pdf.getPage(page_no) + output.addPage(template_page) + page = output.getPage(page_no) + output.updatePageFormFieldValues(page, field_values, read_only=True) + output.write() + print("Created '%s'" % (filename)) + + +def main(): + template_pdf = PdfFileReader(open(root_folder + template_name, "rb"), + strict=False) + + employee_john = { + "employee_name": "John Hardworker", + "employee_id": "0123", + "department": "Human Resources", + "manager_name": "Doris Stickler", + "manager_id": "0072" + } + employee_cyndi = { + "employee_name": "Cyndi Smartworker", + "employee_id": "0199", + "department": "Engineering", + "manager_name": "Ida Wright", + "manager_id": "0051" + } + + discover_fields(template_pdf) + fill_in_pdf(template_pdf, employee_john, root_folder + + "JohnHardworder.pdf") + fill_in_pdf(template_pdf, employee_cyndi, root_folder + + "CyndiSmartworker.pdf") + +if __name__ == "__main__": + main() diff --git a/samplecode/fillable_form.odt b/samplecode/fillable_form.odt new file mode 100644 index 0000000000000000000000000000000000000000..e4fa56b9a1c0fa95b24d4dd020745dde918374e9 GIT binary patch literal 10776 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 z zl6=h8JJPCk_~?VLPHs`Ft5l*|@1eYq*Y}R(#C?;PrKsz@bXuJ^`))-I3SBXg4UV`_ zk5Ioabx^BWmCqR1Nv%-dR`;5R*10W?Omr|~|A_74hLWYZy>cXZ-mN!;^vYH5#xy_E z4}U2O2xi}6Gn=~>EuRi4>TCxu9F99Z4S11=OFC}u^fkXTNGC6ML*3Zdj!O0J)bh7c z2&iTI#fPoKauUy%(w_~dt8aZ-95-&%rP>haF*J2DkZ^eFb9Lie;uEaX5?@?!v_LF4 z$0p%9!F1q+Wc>2ja8zOFlpOwyRSh{CYer(u>F4M-cVc?jLm6AlKx+xpIiC!=zBSL^ zR2^&aYVWQ0{6JHVFQyWnvU$ULko{p7g~~hEeR;7QM0?-EQZg+BqB!<#Zl3lO?Q~Nj zr0OFPSs(JlHpzi^-wZl{k6Q*Rt0YHJa!Hs4jGJf9g~Y9NYWqy7!9(R>8e$r2!pbVG!(Qlf3)?e?rdMe z*nb2Frd|eER}N6QX_bEVeQ)u3B{R#s{0m6SuGexp4rw#o&YVo9PIQ{xR{Q)km4&P9 zzKPHM3LPmUmTHFT+EkKFdW+_llkY126*gA0zZhvTeJ*mdmhHD zgonVjP~@bNeCBW7TMD9N>AJI2mIoRdR>JSzqvUm2x|*BiC3mo6RZaD-|K?*!`534T zD<`CR>2W$_6uBxqEnbwqFrdNtC|PIE#8=%MybhR?B_55kswQ)fHcO7~(MYZkwzqw9 zQeRHJGTaIxRmmKe6wK;=I=5EY+6wMNzBhdt+G+w#k|E5!lgfqDpd?AeoMq>Pf^|(=8GBfrf^|Ze3C@XDPR9Vmh`X&BLl4%eh>dQ_S zsIy~W_}uw0WhFDByPyN58NmcnO43xEJ!bx5vrFjnDKRw_KPk1b!$OKI>nbxY%A$mf0cCY11x*tNX(tD38EXxW z{0>~I_pU*4p^c;8Qv%4S$%B(BJcqbiU%GgP-A$$5v$xFu*4Ta)?;6i__5s>`VVs+; zV~9;!ta6?}=pcAM&Sm{hZpa6d5YKUBcD6ZdchIZMQxwsA9LaK2T3k$#3TFYw7)gPw zrA$4lC`$QJTwD@jxW;fye?YtWqyA(aVlQ;_EXnq6kWPSdaBxSHvD-zc;Yf%|ny9Q- zG(A+NFd_u9;Z|iHH+;LO#3<3bo(Du0Bk#0L2QQ=6Cf;OGTi90%(C= z>tJV_Z%89=d9hN3z-WsCe?$y ztm<+`^$5wBYX3OVPJT)11c;47(NUrtelE`T4zxmd~`7PByllpWa&zm6lg7(}~#+EY=eW!_BRxoHS;eSkfp+i8wjH zT`xEtHXr0a6mkD%wzuneW)n*v$wnT<|5~M(B1zJakaS^YKQqN(x3ibM%OkIG_oTQt<4gsvAq5%?Rf?~tOk|uGYY;;(679C;bl-O7 zn7!dj)aqthjY)K2y1Uc|ERg7@@@g{Ksy!s%@Zjra5t}pj(RHEcl*r5ZTR-aarL#QkP}06OtY?`K zo9h&usJu5f(r&$LVv$R>`cW}S6>Bm<+_vv-$AZ~Bg@MpmreJ~9{eiL`@iGZq-{SsS zrdW-m4~N3CRDIh^2i+bXC*V^31NO@MiN!DoM7oqsh{f|DNs&pF%!jq3DAi~5v0-#- zqc9V5sM@C2KuAw4f`c^6d>hIl)1K4zg{U5w<(kJNA}Vh!$CJuBAe>H3MNXcc_9EV> zoWRwQW}{8~V|VhTvQ}J4p&@^ha&qq>MAx`P6qeT&e!=;qhwDjyoojA z;G3g;Q*TyTNAlyc)H#FmOkhp@eTJQitSose!LrWUtKg`Wl`nz?UpP4~qzx5LlP`A2 zc9M=0_~YL{R2HtW-YMp2=;WqpeWIiIK_$$ou4E>14AJBE=>>ukHp_z&b63~1$+P;sOww=h_K5ms4l#OqX^~KBG7YeU zcQ6|m-DbQ0yt^M7_o~QP)f5!9JXoZ6+hay*#A9F-8|5RA;*=~S^nBjWOWWs>eI&e~FLK#gtppBuy%Yfj}PWzE0KqP%&Vf4Tl(+-i@{I+xRT z-dvC$S17Dd!sv)b-e9Ww8=>3Yn!r_XQO&R&6}y|!aE#j?`9VNcbyH;04rp+GE;DO> z&Q*hd33_v=Qn_*g8s}D2Wj0npxD@^(yhzbY%Q1SrAx-v6XdwaBJL~l_S>oP{RKtwM zxEU2|_YLL81IyFaz157g3Kk4QDjH(qJ0Cw_Z+PjXktMDUC3cCnOC#NP3qO+c-n|aZ z0f;a&H$EsMH*HHv8D^J{hCqiOW#8vE)A7y($ePY7@qoCvDs)m*#;IbTznceCiFu9dUPNrLyQ@9wguHPnmEkG3 zC3EQ`Q?Kanal>&8<~Zftn5LhjUPgHPPk3p$+*C5NqfZ=jbj06V*a%vR_T9aD@6a|` zu`Ec@g(z|D9^Vkew7|N{`-=5T`c?O+knPI;&kd_@Xv+oGeC>>3Uv^f{+gX}Gp+jv$ zQx*GbhUXn0w(Yza_FC#WYNmGkiz}X)mcqbC>!r`~_qKL->9j6 z!-<}7Grcfy29gcfm4G@1Q1OpdlQ{3Q&X-bF?yDAUK~A8?sjlBcWiBQ9oDcepqYXlz z?t`(cE0>^3&f)KoaaFCTGArAhiv?}}$)t}&y16Ojx(8cDzL z3_RQX)WFC0`S4?KN1I+oOiEo1B&*&&THX;h0;h*pQWhrb7ZtqL8B#5?>S`}22~D(` z8&quX+*H!dowrmfG=F3Fh`Y6#C4ukb*W|en*|GP|nd|euUzMD46C=;QB<&Z8x0Py3 zRx9q2?YhXbfU)v`KG9!8YM*5p6R_p)iVlb0>yN}><+z@RopgHqedOT(8-f3I!0{O=xhmo{9CWLde z#{A>SkNK^;2*tSZ=0p-i3VK#QsyD1RF;2Uv__74m7mbyfeT_h9%ikBWE8CzEh)b>1 zc{QVu(#vRCF`|-JR*OJ%gqodTC%0`X2wvMmxoNFC^V*ZH8+~Oq0G~EDW^nn?S6SGT z+GoOp_EAfk=rwz~c5+fI)Nk9T>;6q~^wgm=-o1E3J1gD-_q?BZS9m0|uGuP6-sDjg zdvWDg9aLHxY)_^B4(-Px9U4k=Q_-HTSFAsRS}v1XE|D$5Y}4#1cYBLVbVlwbrEKN9d+2S@{>GW-wS;^fJ-u#b+qJSc zR%b5e)NYM%#{IzGq)JZGVz1)Xs!Tb_94z^9t2n7stTUbR*}bQ)MBZb+t|ZDi79eTP zw&fA~)>0}dnh@W;e9=+Wun<+DQ*U%s(a&!=^Sxq=!^&u1yOPzsX{D27&1kGZ8esb4 z{dqdctN}^kZfZ|YRHRI8Ok7-X)&0A8>@FfE!-c^{c+_y*RoP8d%SsJi-6&=9 zbs=S-rp&6fN^oRMJ560vH7y9>VqC9K6GB+UvvF9F2AFc6Xl$52b<{w& znAh|+C54XFTDg|ytsjkFS3Zt33BFtE^df~eD)14WPlypWxU8@c%v?_*n!BA&L>izY zap6gl6s;>kXK>v58EyoTA8seh^huqh6_G3X5*xF=ve$xNF6qUnTXNyIk*RWvvz=J=knd8h{&S_6tbhq*-OB@;8 z9qZhC6;~5FVp^!Lpk)!NQ6lLZ{4qYTdgA`Ht$|;C*IyVN3WJ#{mJqgW}?=6;9#;{i{DjVy)rziw?2t z$V=;3*=T_tD)uOuAMe;lVj|**HSGX#Uk})$=$F1~#Zpan+=F+VA*teJpCi<3F?K$e+TxXO-J(6Eh<{`xb8~5k1@w4yLQc7f&*i;W9 z<2Pg@T=$ox=|mQ;nB!YYf5QE|4Wt_&hW46gKIk}cQ@^@r!n)^V7$~4k@3EJEko_`h zTZWkIP2ppG{tjaw_by$lDT-_vWRE-xZ}aTAr{^)hX@ECQUh*fBkpKy+XxayOJuXh1 z_YJaE%=HcOTV)fa@`FpYt=z=MaoqcXRz!})Y+ZEUJoMn8rMAlX`OS`6L;l@EL&FaW zGQ7-Rb^*`W*TPK=0+(@5(oT6O>%0ioA1~7Pwg$(ETVzC*c64gb&3nPZ>rPID#jI#z zCq*f0bdtt9v~Q=-xzNby1Q?vvLe<>tO7P5_0=!dgaLgT2Z*mR{$a1L%-6 zIg12U;Lwf8bvJ())*FZqz71fJ!`Dn@GX>cTMLx<)zhwQ`UV=~cbk9fi>)y9{Cn||8 z){#rB?8AV-+RgIqLSnzO6N@L(y)vUm--0#QNgIP|ecKXDCh>*6ubUJcCff4v9T3rX z_BBV*%szT3fPZ%2AVhLVw!p&HRmIgWP_c^#F^c5-$jR8osnF|42+Q);7%)fbjkFSu zz9jSJ+&w#$`0!-Q*LQGq^{%RlP;%@jKXH0EUs`mwZ8bQnW{~cW@@r zEiaJYNFFc!VJ{-1oK=|dFoxlhi4i!VcXzu z>$ivW0+0JW;@l%*wBOD$DyNNfNJCq+7={_V^Y)MZJ;a2&L;$%5uvr#ic^V!(~EdJoV#U=lVK+sA{7F? zZ6?&E^*F2cIdSoiTyD+W+WXBm<2Y^E|v}XZW;M_AB~mNM|Xn3;rGgm zG&Y?+!FQB1JUuBJ+MnCMsyI24dUa`fE$_Ziew5Z&FbZPdxA9DY=@9-X;`@*CYnJH_EHL&9D2iSLM+B^12sqDLucD(3fPDgM)xI-GevLop;jL=LAMNO=18w zN-mLkGkV{*a>`(?@190S;!w6LgnjxTHbtlVa>sO2-K!=urXl(3MR)Oqu*`01r5&s^ z@F+J>z2YfZx5#}4J}m@qzM>bUZr8OanTyG38H%a5Plm60a~U4wCZ){uv^Pm@80Xi| zi~Gu-?>QltJ@Yv)_8u8{e+bj$YO;(Q-+#`0=p+*P1NTUE8Yf10m?CM1E9pJpSvfD| zemNyXIBYBObLX+iw-ekG{DlbZy0)+|3mdxSJWqAndAAo02nyN4-86w%72R?6E}y{B zLM)f5ye6lqys?3n^R<9U`A+xkx!XSbBC}#vSi8Q~3`7l;sbGdGni>Si_=^H--GA?5vnKy#`=pUF-LX<(kN6~S6f2KR8a|NbuT zz0Z35rDN@9)1i}Ej{_b>RlSjnB(Ut@cj9L4u$JW5nVu<{4tbI*(xttmUF)pX=Pd=R zD3)`{xMZ%X#PQ+Z`!RYxb{vsX)Ay-DHPw=6Z?E?7bjOOvCFK8)Nq zo9Gz%{L-;34oCDV)G?%9OEqfMJo!=U;mf{KaxsF!f^UKra}~OujcDFp1({#i%UBXO z(~l37ruW846B$E?wy`D z72RXCj{JAJk#lr(haR^-9k=;kvCep#rX9=XK{!mwW?*;O_HuB6b}!tkU&5~ExGP~0 z47+1GzaM`5JoK4^nB+WG&M^P%k;kO3G|erS4&FDU)aiuo4fx4hzHTjrijhQ~SLH3* z3Te_OSL+CFYgif* zqP~-!@^~z5X8`Xg;S<$;Sk9Ini^%n@$Mj2iHaEkgg5&nZ1S79Y5^t3OwC;WhTktq-2SB-i3T(Fd;)JWkLS@@=Me|v zsCRpCm4`&Ay&@j3UQ6%iYhFA-Wp59$W_Y%B2ygGEkx7`$=uVU7Z=S#ATcZ_v?aplM z_+(l!!i49!AC)!U@pGHb#x2$B<83@E4tHSUGvXS=5hmhiqo_%ILQ{?K_S+kG9dLPg z?O&S$ZztW*ii^7$>Ghl`%Mn-pEk{nqRkHaHSVwJL{%S{8?xQrNl`gY8X{hhfeHc`= zHvaNFhK$UYPBA<-meprICgBVVLE1s_#H_D;?3M6C$1c5W!qewuJT4jIA%4U;v>H3u zQxD(p^Q;jBex7Qv4+*!&&*Pu-udowvV^=ZqP;yK~ACXLXyF zPzzX4LA2u#Mzce7EYTa2=*hE~;b2x{^Rb{H>=l+9i4zT7@)4UO8NPA2;ndbe!sl~BN_lXo7v9%pKR?H4})x)aZ3CAXT$rKNKv=Z+5+TccQ{iMKO^XwaT zU46WuM(#%@t|8O4$H`<1k@)LD_zf1(^zE z{iR2)#%z4Y(ap7D(lKVEpxx&)hlze8Yuc<-Cg43*5XN>X`p*>$|qSrknZ(A{!} zd47?GF!Dq4PTj_Vr^H|j#m1cuv6Xq;Qndtu$x+em%t8+v;kL-|r-h;icL)?z!=5wt zf{5MYQ}mBA193*bzb6Ur4(3d1zACDWwb1~9uug48h)h`5-+Q%Wmy=cKqvzx!*@!aw z65;F{UEWximp?U>^;$+-NlztxaQe;H$^$mNq=~h#S3%Q}B|%$uIgJXI)8hltyYuViY|%I{BsJ z)J7@~A}_0?t>TngSe2`=`qagx(vAP|v8VII@Z|7lpz6J9Xyw7|uC-*^;9DZRoOk)T zRk6gH^Q{~2j?dS|g-+{}`1uc5l{SkHh`NewTY9am^r+e%>S!2PEA0(4ip?z2*qXtS*5i#Nh6OYhl1-hO`Y+fskc1wr$I?t`$K*AxJ&e(oaU8$zLdRWwmTnb z4!vAAYQH=vox42M-g$OWczpTs8TsWWDx(WuI(nzo1yaY*PtM`hxq5pEOSrY4ZIb8; zjuq50JVI*0+}K7}e(1L^`-@!_#r38*Cj6e)66{Zm)lB4#tbM7x$Hx}D|DbZuhQtxH z0F%27BM?y~4Lf|5ZPBE#MjwDAS-2;6drkC3c`{_9&?j^$(}Z`mQaW)!pSAlsDuuiI z7F?9R+XF=%w}1pL%R4?qT}7oZcKgB);e2dxIn-;QxdI=3cP-Ea6)ry)zi=OZC_fit zDuptJ2LX5F`B+0_QCRRv)V@NwENTk1fileln#-37a(4^Dhvn6{;E6zMpe|=OJ6xWLEjn8V#Q>*96}`%Sh{A^NGIhrQwNd1#Q6^n3 zcqA|s2!)q3b)!rZfm(1rrfwwA00oAtF_p=osmg(H6j1(298etP4p&6A!AUtnR8e=} zgs2s!kT{?`X)5p$9E^Ghe<{C`0<1v)&**|ATok$B1OGwa?S(owKsCd6OMuT}7r0U9 zx+pRDZY0oNVOJI&sj!O+pGGYx!KaZ6E^uG&?rq>nF|av$VFq|o1uTW{766-33*>NL zwr*~qhb}4}=%I>ASJ-_H{G_l8f~UnS=)%*Y7xGZToZaduVYY5E)VUOjPGPqeD27_# zh5NF069Z40fKl?hBJd`TZa1KZ6e^g>Lk@-J{~Aav=hzH9g7YzUH=-sPyQfgpF$-L9 z29%-#Y21P`d<(gthnnQ-R)sgQb@KyH>VY+I$3kF@oMQ#hC}yD$d$2G*&fxD|Gp z;C9G`FqA%bw+qT!9EBDS1}}+SxCbwZTc|*J%b*H@b!sRT1;;>OI%**Xr3iPd1IEK0 z^MUblj%7f;jg0?;FBaVNToUm=`W=--{PwMsMEslY`qmRu87EcXyN^K$FqAEpK0s|* zwwwb?R%(q5yFbjd6YFN!S9+{vd;!+k2f#v{r^>*>n{SO;M6qHr?*rAuv9O{&T!DoY zJoJzCTN2*zvA1x~7Il^5v>0NEVliR|T_==|8@k%S0AX!meEh&q??JPl2)1jO>pLl{ zJU`I&4U*3+ueDoTu_mt7UfaL1Lh+gDwfci#KUXYU>}q@q^0(3t6xzlKEhs+UE~~x* zC9nwBskw5GVOZ-yqn{vFRc4V)r4#-eip_#+DfEwH-qfi+$gyY=e-P+*fIW<-!y(8) z`H$mY)Ns!$2{bWdvQ+@gtuE%vNg0g-L<73xM z3A#w%D*9CPHZ(PvvNNmR!C;=eSo-W2LTV>OEN?mb~yGE zsYG!_;H#dUkqP>YnC{3gA>a>w3q){1J~>kwl7P;xmLC> zquM32S~JD>BtLEGvC?Y|41CYnW+|}^DZZoL>}JYc=(i9=S8n<(Gg?ku5hMGa(&eqy z0>buXpS4t7WW!Pk?Pa-kF4YosU6`xjT&~50VJ{fl7chHS4#(rdI>ZUh3%vn6s?5CAD$gp7w1aDP@A%k9Q-oZrNC zYVz-Wa_r}ji=dUob!6O30bnem_SkHcBt$+yH}i*nB5W2KWq#Mso-vAHOpCi*E{*C#Ej z#iEqGf7LJSn*N$3+%%iqns3t3cWUHYi-YTds%YU_Mj2FI&9UB>}s79w+MFqb!WVl@N5Arn&{h5 z2`^w^qMIIYQKDs7PM-I*rp6ey0QxpX}#2%I=b-OYg zTJDI2h;CzOxu@#n0*vOg(F8`P_F>H1qwG$GoS&p~wc3M>m7)g^n*4;Z>Y}A`bI7qb zGCwV5exe>oWbiD*>!R2!zjmMOF*%YA!1!ePx?EI(+topaB@sUjED9_(Y}9pN2u?_* zzpg3sjhB>Db@OV zQ}R18U|aHsf5Q>-$gOJzur2W;^t}1OkMMFa`iq+jwq11eoza)LU3#ouWUKsuQb}Lp z6NB@&n>9O()iV!%5baubS$BDnA9HkZAdMI<2xfbb@c?cKUpv8`!{?S&n;x^D6n!V0 za)l=72Xu9gqFY1X`BX&k8*w7NLU+N+cOjRL&MZJV$g*beVc zM9doDT#_!}eCN(AT^|^6Sy?COIul-SLR!<0JSYkBrq~n>_))@FJyrs)o)ERAt~M}k zXg_3|x2+DVs;dsGB(Em04BW&XxixYk8&xa%O>jeSd&O9L!}y-psHc0+Hz#5`k@H<+ zbG6DHUeHW$LNzdLt*iyMy{0lMCZ+&VxD0iiw0uR+obCDCNOZc)b+=E%9qdpgxxNcZ(KjY#M(?|ECXXc&XhXuj#R@QWCuuO8g-2qA!{qsqqtfBh24* z7?87X@ zEX^FLqB*G1+^^M__0pdrPc13QN-a4Ig=$mn)@a!{RMAe&S>;zSK;9g|zJXdYjqwbNwNqVA@VdI0vW_ zZ&fA7I%PFbIs(s9CFg>Da}#V(4k~_|9i5$|9;;CtSj_2St-{#3=ILKJvRgH-w&@Xp zN0IcnOczXKueZV^r9du^2f12_^A#q;SuL|!bMh>dGxVV+`Kp6WA}_Lp(^#@I(b!X0 zpe9))HC3o}AU-g}x-+ry%PZgdsLLAcR<;eX!*R~=o?CaSItL+tz zZ_F#REIWmhX{Hu;v`x%GHh3vZ zT{=n)XA&NlCxSP4%?EP@mAZ`Ad!p7?EEQi?wOi>Am2H;YGq-Uu$O2WnYtG9Kdr<1- z-5I+z9?`k=xaT)ZHu&#IBwZ-(f-j%7id@KQT;0H%BSR%-MA;u)o(2DK zQ<;7CL-w2!YPAHWj27<;L=pg&B_kh*V!?OFYHvij_p@5rR@^bXqS5U;=0SgjZ4>pjCNa~l^W#Z-Z zx<~{G2apV%p$BJ+tI<=);RElYuEAd<(BmQ9U*eJCh6LWB=Owu+MH~_&CGHGya<`(t zcO#I5PcB;4oSp?hCn4(BKzxF`AksBM|16+^;Dlp=8!0CF3F#Ws% z&*SQ@;KC7dM%Yl&<3Yar(^*OQVtL%%C0&s2`b5wDAT9WuaF=>Pw+n~VWnq|1$d#$OoQjt|R}#odqtrYkWj_l3On(u}&x!T)R}ee)T`dWO|JE*(L8%LQ>Hi1$pB+UR?-7 zuG5c*H(fdT)$i=y?b1YY(5DCKW1ZYyh(WS-Eh2jW@e*AA`ieN#kq=Xzh3=_1{9x-B zYd^^oxV*ibK6kGE?}1lIj<4X;J@|H&)%!{y@$2tcw?+M0aUcF)0{`SE+CG*iaCX}~ zeQrZN#V52v#o>^x9}T?RKKyX`LCoiJitL!~2mSlm%$9JU!J`f4OWd-ID5rmMAn)f% zJIpaWUNA4Oz(3C9{c%taebQ0G<0*n$#@^0Z3gKkpX!+FH9(~dgeW`40i{O?J$9y;> zjcqKSI9lRkjzF3_0l?@68bd&4AAE; z5$Jv~2ME>h(We3bJW>e$+mS*L59B`_(=>?gu?yfKkv{r?&;3REh0-*sgghLnv!5~O zdu3G8D*sLo^7=EQPYKm(l&?WiUXV0+=$e`?h^f@~Aw;nOq~&!d_?>o(UhUl;(~niE zUq}ax4kAq8pNIDZ#Er)6y7=N60>=eT5=;9%Ex!3PaT^BkA9iTdNz=@oZcS3|KW5?5 zNpm7H`0imf>GVZXqQE6ba!hegQ0~XQX>(lR9Gwo;udj`rBd}*isopBSOfg3!g5I7Q zDbZ$SZ+ML4I6)znLN3 zBudH`IGqw5HYzC^-=();y{{78)0GgTKbp2jPJNzybmQewY9N!UqBH@xjnFKL8Bj1At-t z=xZnd3Wfl{{4f9?6nzch1wheKfxrR)5D1Kqp%H+9(f4@(2EUomKa3i{`|~g_KDUOw zrky3`5HEliV@LmNS~jyuAOsB0#WTR>ZIN&;Ku^{4XZrPhq9)(BrnWGe;}jPTbDP@{eouF#eny5Fg+l zlfwr=3;6r&@bRNHjxHdyh9MB>&mtfI13;lr056OOJp-WM3K|9x0R4uGhW$>5{|C)~ zs{i1F>Eq7=f#UP>pr;zc3{&{|_v);b1`VI+VS;3qCWKmJd; z-|_yWL(^c|Ffi!PzM<&;{tyCFgQ4gFp#{JU@K52eEE3G{{{Z|^V+8)C;QyRPG~UmtM&J9j#;E8I6ZjMF*FMn#{5}o84es~B zV_+B?{;Bp~U>Nu>yfN*6OaHT9v|=!3^EV!tDaG{5!-M}XJQBv+sQt3Ae{rxfynvtn z7JW<}9Re{6{+}I{02+b`?C1!Nakc;qsTw}_Lq~fPb%e7XH~Q@c+!_dXXM=wVoc|#D z>8c+ZnEZwMpn#v_0Q?jZ@RJGv!_Z=!u&krK%Tu(F>gWJrZ0Gb8!_35kTT&gJ3AkFC zAk<_fxZwb2bnp-r<(5Q`1TBjb;O7eheo@R%;eH?PpOQP_|4mx_e~60~;7@rmf+$#; zI_Uv^<`S4oNqZN}pnv6ok@;61Ix0`B5GKxOAN+fWld*TS#pnK+_Fy^(@q)Nu=qSa@ z#REb2_*c!LW87~qk-$W_zrR8PGcSL>L*ff@{==ucE=!KrpIo`kj6L!%Qn_Dpo}U`{ zIRk%+hW63s2xo2?Om3!z7Fv%V$^}NRSSXZ-3lkdv9t5|PI4edSJOD>? zz)x!x0BD$@=~V&fcqaZ(SQwvM866?e2tQ5u7nSp2sQ&k={IAKte^2EQ7?g{L=NFap z@^kTk|AWdcP5)mj{HJdJrtn{0#_`jN{&(5QV-I67K!@&6keH$|X5 zkh3k?$^1Xp_n+I8Uk&`1SIYb^)b}qz?7{~t+ zmx7M(|H7sGb!+>-%fkN}WBz*<4n`jt`PGYq`N03yi~phV{{fHk+Xf14-oIM-U*nRb zF?#cFZ;nnY%rQv>#>1oY5|yV2J8=_dOM5%L-$F3Aj_xCXor{glZ@+lZ5lPY5&YTrt z$Em4~UYp`3j`o;%i-|Ut2pe?l{;zWle0&3LDYZY67G(s&RQ%~vgfTkjz~nN&+`zL)Tyo z3g#M(hR(uFT}%*v;DIH7!@+d-6CaHSmO;ayzZWz;6of8lI2wfqor3f5Nuz6?KUkvm zCWU_a6swdV9|l7Jy%&Ok!MtEj9)1=c9u~G=CdAzlVTRrepr59od;0wYfI=W32*3>R z8;lnU(XD@*|MKnnBu zlP|9TufX4U2tXizgP}8*zxIdL5cF?&UPkQUt#>{rwD(6L3q)7+rPp< z0%(iHeEuOb1Oi5fs(*$-A^d-%g~I+OGcP}%z~Aur(F*))e*!#wf8#3vg8d!FkKVxj zMHT_fcJ@!0v!gNkL7F3GtDtV_i9nkMx0=1ZGXVXB;^*3g+nL#;H=Dm-NCET!!cb|5 zBtL`){a^(o0Ry2EMsf7(s`zCDqy-@SG7{1tQT+dmg2}R_>`f#s5GK}6F17$}2nZ^} z2j+uH$$%umPyzH)94J3T9Lguo&jXc`5`g`d5u?NNPZQ>a@j`ju@QTj^ar41=1GWq5y9WM>h@NQ}$y z%ZZL8>ot1>3Dmkp^PqHlERhkB#k{VuJWRVe53 zYvgwtoCF1UdIh_gvldNJkH<9zx-E*WsKKQn!^!0B*|n_`?{RMzCx_r8>`Z@G0=k9K z8$L!|m4WE<++KAU4%92R8QW#B z4=w(r+8}L+8iiA{jPBl>aA@EtlceY=x8dj_K&2p&pWg=P;d6ebkSDO!9S?ebA3GuE zf!?^FU8Asgh7k&#@Uw3t*6+|QD$ zIqekLO1JZNBd3=(%O;SST2`bsbP&c{#m|oAJ$iGr)0}dqknM%neL23Gn$g6`zUKjT6&#`w_{X5-TOI=H{{&@Y^7PTYhy^E zT(HZKv@MN}J|4-@HMC&7%Xb$*`P@L(j-du+kK{SId2-9+o0t=A1#YGcJmt`kR0)Nb z==E&tc%vAZ_~uv|rp*{zq)y?u)a&$2m~A_%Lip+ecZz3&&pZzM$0n2q#aYJ0`+-8;T!Si;I+uXE^r99^_vcu$OvCd!9zw&H zNz}X^_5?f%=l*(+g$#KGFB)D>EJijf4r%|`zqAT3rxRO7UR?md;;9*ehn9WQoNh4T zdYn>sc`T5PChm1#Pl4ZtQKG`S+DEGtx)BSzQA!4)pK`lcy7S(CN@vzii!&+%x{&*d zN{SMA)duM+h{`ryd3VfE_bq$!)86@dcYJrm+q+t>oQ`%2;jyA}z7MvT-H<}vBKq;P z7D^UUYlxTYPq76BUXUBsT69P}J6o=Dp&jlYhUS#)Q!g03ebX+g8CA3t_=e5%)>(@u z%p1jA(t7WjkxsOnLC;7t@|_L`T|CEu!v}^w@94ZcLa-y}bEgFb0e_?SF_y7qrOydm z8JENMnuU#ynA3jTt4o}G-dGy}3Sn5*`aaP$;!xcTk3>!ERJ2fn{N0fDJE;UQmZbD< z(I%taUR{l*LCeqd$MSc#)%F8J zx}4FcSSR$tU*{J(YYWpDW@OjkKfDR^^SVI`y1UpA|BF`*{>yl~&R^~2g!A8vxQgw2 zUmc4`zid^}U@k)@FHI*;h#jR>hY$|Xo|3H`6n_4g#~L`3aQTpmcguWc<6brmEU)3q+*EcP-zag}-Vxur}eg#Y&YhBHuzD=q)?R!qF;52Ea>|AnU(8{Ve z*O2s(3-*4JN3w{UCAe=f2BggACv_}mUMk07+H#M+Urp9X=gTK~+Gr*UN)8x+6Bjo}M52JxTKP46Hxw z7pQ%8J2JT?nj6$V{WRZ)A>~OaIXN=pt;lzmqg`gJil_1h3Hx4OwZ07oc|y5!j0>6# z6_E#s?TyB$SAC6w1|>S%?2L=qQGJXlkAjuDtrOO0sPQLGiv!+%qR$ygB6B?y_whM2 zw5OY3dI!@#W)JH5#<;7cGXbwcAgUdGO2k)(bgF!8YLFS=Ipfl)7ucZcFqW~%VLLU? z{Mat5JJQAPM^V1W&r8FQG6qiTMIO6@R#(AQ~d240yUGXFMC)6v}Qj&b0Zt*fji?zoA5jP7bwbG`0zwCAA z#)Kv#%2NBRt*o9VSvV!K>E*GpsJf(Y5Yz~rZhXTE776aFsI?e>Fz4uby8cv)>f6>v zgx$L*TKDoMK~Azbxw)zR`5{3+qUBS<*u3^;Up2mSi-}cfDm;370H6{IvB}W$v>J#F z`l>v!ib(yU?5TScIepga9$#0K$Df&zRR3eVX_cIHy-|g}t=kE5KORy3qLs8Lj|)iH z&~zZmLNDu{A8G!*(maSX%^d0R%H0gi@aaCz$N8(U5F92!)wx$yE?uCP4UCzt{*Na7 zNI@KR>9Y*<4G+C@@zmdbxw8lsFiCN^7lXr&(7m-V8CB2wYLZ-5>8oIb=sWjALJ>Zi z`O4`|uQfGmT5+W~H&an!kogdW%Zr`1Rs#Z#r<*H{9Feb|{g8@ybm&i>8`To@G#$(u z(EH=&L4@ML5%0FRnsMQAj-|oR%?REq5hMY1(OZVmCeow<2Y5`Y^E^&b zG}39l(xYc}3jdZs>ip8E!$cwBQ^?1mql1v{ zy{|b|*TZdZc0Q5u2-C=i`nf**+Pn08MuAsT>p-X|x&Q7ULJYSgMk(niTh?Lp)x<`} zCi8eFL#H7<6;%RRxaOI=#=_dz$NAT8wJ#FuCN^*#DST#yMmIY*qI9-Dh%@=9vzWj5 z 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 Date: Tue, 11 Aug 2020 12:14:50 -0700 Subject: [PATCH 4/5] Added a unit test for the new PdfFileWriter.have_viewer_render_fields() method. Corrected a minor detail in testUpdatePageFormFieldValues(). --- tests/test_pdf.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/test_pdf.py b/tests/test_pdf.py index 6417634174..2b07f7f9cb 100644 --- a/tests/test_pdf.py +++ b/tests/test_pdf.py @@ -439,8 +439,45 @@ def testProperties(self): "%s.%s() is not callable" % (PdfFileReader.__name__, m), ) + def testHave_viewer_render_fields(self): + """ + Tests that PdfFileWriter.have_viewer_render_fields(). + """ + + testfile_handle, testfile_name = tempfile.mkstemp() + + field_values = { + "employee_name": "John Hardworker", + "employee_id": "0123", + "department": "Human Resources", + "manager_name": "Doris Stickler", + "manager_id": "0072" + } + try: + # copy fillable_fields.pdf, filling in the fields along the way + with PdfFileReader(join(TEST_DATA_ROOT, "testUpdatePageFormFieldValues/fillable_form.pdf")) as reader: + with PdfFileWriter(testfile_name) as writer: + writer.have_viewer_render_fields() + template_page = reader.getPage(0) + writer.addPage(template_page) + writer.write() + + # check the results by depleating entries from field_values_sought + # until it's empty + field_values_sought = field_values + with PdfFileReader(testfile_name) as pdf: + catalog = pdf._trailer["/Root"].getObject() + self.assertTrue("/AcroForm" in catalog) + self.assertTrue("/NeedAppearances" in catalog["/AcroForm"]) + + finally: + os.close(testfile_handle) + os.remove(testfile_name) + def testUpdatePageFormFieldValues(self): """ + Tests that PdfFileWriter.updatePageFormFieldValues() populates fields + (annotations) with corresponding values. """ testfile_handle, testfile_name = tempfile.mkstemp() @@ -469,6 +506,7 @@ def testUpdatePageFormFieldValues(self): with PdfFileReader(testfile_name) as pdf: # For caching _cachedObjects data for page_no in range(pdf.numPages): + page = pdf.getPage(0) for j in range(len(page["/Annots"])): annotation = page["/Annots"][j].getObject() if (field := annotation.get("/T")): From 236c18ce935f14ffe383179400a0f06106bad6a1 Mon Sep 17 00:00:00 2001 From: Craig Jones Date: Tue, 11 Aug 2020 12:29:56 -0700 Subject: [PATCH 5/5] Forgot to clean up the have_viewer_render_fields test. --- tests/test_pdf.py | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/tests/test_pdf.py b/tests/test_pdf.py index 2b07f7f9cb..0ff7dfa27d 100644 --- a/tests/test_pdf.py +++ b/tests/test_pdf.py @@ -441,20 +441,12 @@ def testProperties(self): def testHave_viewer_render_fields(self): """ - Tests that PdfFileWriter.have_viewer_render_fields(). + Tests that PdfFileWriter.have_viewer_render_fields() adds + /AcroForm/NeedAppearances to the catalog. """ testfile_handle, testfile_name = tempfile.mkstemp() - - field_values = { - "employee_name": "John Hardworker", - "employee_id": "0123", - "department": "Human Resources", - "manager_name": "Doris Stickler", - "manager_id": "0072" - } try: - # copy fillable_fields.pdf, filling in the fields along the way with PdfFileReader(join(TEST_DATA_ROOT, "testUpdatePageFormFieldValues/fillable_form.pdf")) as reader: with PdfFileWriter(testfile_name) as writer: writer.have_viewer_render_fields() @@ -462,9 +454,6 @@ def testHave_viewer_render_fields(self): writer.addPage(template_page) writer.write() - # check the results by depleating entries from field_values_sought - # until it's empty - field_values_sought = field_values with PdfFileReader(testfile_name) as pdf: catalog = pdf._trailer["/Root"].getObject() self.assertTrue("/AcroForm" in catalog)