From 6822d03bb667ad81c561d889443596d5a1836249 Mon Sep 17 00:00:00 2001 From: FriedrichFroebel Date: Wed, 22 Nov 2023 13:20:58 +0100 Subject: [PATCH] add tests for the labels module and work around `brother_ql` issues --- brother_ql_web/__init__.py | 38 ++ brother_ql_web/labels.py | 21 +- tests/__init__.py | 24 -- tests/data/hello_world.png | Bin 0 -> 8165 bytes .../hello_world__label_size_62__rotated.data | Bin 0 -> 57419 bytes .../hello_world__label_size_62__standard.data | Bin 0 -> 13709 bytes ...llo_world__label_size_62red__standard.data | Bin 0 -> 27214 bytes tests/data/hello_world__label_size_62x29.data | Bin 0 -> 25427 bytes ...ello_world__label_size_62x29__rotated.data | Bin 0 -> 25427 bytes ...llo_world__label_size_62x29__standard.data | Bin 0 -> 25427 bytes tests/test_labels.py | 342 +++++++++++++++++- tests/test_web.py | 42 ++- 12 files changed, 419 insertions(+), 48 deletions(-) create mode 100644 tests/data/hello_world.png create mode 100644 tests/data/hello_world__label_size_62__rotated.data create mode 100644 tests/data/hello_world__label_size_62__standard.data create mode 100644 tests/data/hello_world__label_size_62red__standard.data create mode 100644 tests/data/hello_world__label_size_62x29.data create mode 100644 tests/data/hello_world__label_size_62x29__rotated.data create mode 100644 tests/data/hello_world__label_size_62x29__standard.data diff --git a/brother_ql_web/__init__.py b/brother_ql_web/__init__.py index e69de29..83a0375 100644 --- a/brother_ql_web/__init__.py +++ b/brother_ql_web/__init__.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +import logging +from typing import Any + + +def patch_deprecation_warning() -> None: + """ + Avoid the deprecation warning from `brother_ql.devicedependent`. This has been + fixed in the Git version, but not in PyPI one: + https://github.com/pklaus/brother_ql/commit/5c2b72b18bcf436c116f180a9147cbb6805958f5 + """ + original_logger = logging.getLogger("brother_ql.devicedependent").warning + + def warn(message: str, *args: Any, **kwargs: Any) -> None: + if ( + message + == "deprecation warning: brother_ql.devicedependent is deprecated and will be removed in a future release" # noqa: E501 + ): + return + original_logger(message, *args, **kwargs) + + logging.getLogger("brother_ql.devicedependent").warn = warn # type: ignore[assignment,method-assign] # noqa: E501 + + +patch_deprecation_warning() + + +import brother_ql.conversion # noqa: E402 +import PIL # noqa: E402 + + +# Renamed in version 2.7.0: +# https://pillow.readthedocs.io/en/stable/releasenotes/2.7.0.html#antialias-renamed-to-lanczos +brother_ql.conversion.Image.ANTIALIAS = PIL.Image.LANCZOS # type: ignore[attr-defined] + + +__all__: list[str] = [] diff --git a/brother_ql_web/labels.py b/brother_ql_web/labels.py index be13b51..39c3541 100644 --- a/brother_ql_web/labels.py +++ b/brother_ql_web/labels.py @@ -26,8 +26,8 @@ class LabelParameters: configuration: Configuration - font_family: str - font_style: str + font_family: str | None = None + font_style: str | None = None text: str = "" font_size: int = 100 label_size: str = "62" @@ -40,7 +40,9 @@ class LabelParameters: margin_left: int = 35 margin_right: int = 35 label_count: int = 1 - high_quality: bool = True + # TODO: Not yet taken into account. The number of dots in each direction has to be + # doubled. The generator/calculation methods have to be updated accordingly. + high_quality: bool = False @property def kind(self) -> FormFactor: @@ -73,12 +75,13 @@ def fill_color(self) -> tuple[int, int, int]: def font_path(self) -> str: try: if self.font_family is None or self.font_style is None: + assert self.configuration.label.default_font is not None self.font_family = self.configuration.label.default_font.family self.font_style = self.configuration.label.default_font.style fonts = utils.collect_fonts(self.configuration) path = fonts[self.font_family][self.font_style] except KeyError: - raise LookupError("Couln't find the font & style") + raise LookupError("Couldn't find the font & style") return path @property @@ -209,13 +212,15 @@ def generate_label( if save_image_to: image.save(save_image_to) - red: bool = False + red: bool = "red" in parameters.label_size rotate: int | str = 0 if parameters.kind == ENDLESS_LABEL: rotate = 0 if parameters.orientation == "standard" else 90 elif parameters.kind in (ROUND_DIE_CUT_LABEL, DIE_CUT_LABEL): rotate = "auto" - red = "red" in parameters.label_size + + if parameters.high_quality: + logger.warning("High quality mode is not implemented for now.") qlr = BrotherQLRaster(configuration.printer.model) create_label( @@ -226,7 +231,7 @@ def generate_label( threshold=parameters.threshold, cut=True, rotate=rotate, - dpi_600=parameters.high_quality, + dpi_600=False, ) return qlr @@ -240,7 +245,7 @@ def print_label( ) -> None: backend = backend_class(configuration.printer.printer) for i in range(parameters.label_count): - logger.info("Printing label %d of %d ...", i, parameters.label_count) + logger.info("Printing label %d of %d ...", i + 1, parameters.label_count) backend.write(qlr.data) backend.dispose() del backend diff --git a/tests/__init__.py b/tests/__init__.py index 1246eca..69d879c 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,34 +1,10 @@ -import logging from functools import cached_property from pathlib import Path from unittest import TestCase as _TestCase -from typing import Any from brother_ql_web.configuration import Configuration -def patch_deprecation_warning() -> None: - """ - Avoid the deprecation warning from `brother_ql.devicedependent`. This has been - fixed in the Git version, but not in PyPI one: - https://github.com/pklaus/brother_ql/commit/5c2b72b18bcf436c116f180a9147cbb6805958f5 - """ - original_logger = logging.getLogger("brother_ql.devicedependent").warning - - def warn(message: str, *args: Any, **kwargs: Any) -> None: - if ( - message - == "deprecation warning: brother_ql.devicedependent is deprecated and will be removed in a future release" # noqa: E501 - ): - return - original_logger(message, *args, **kwargs) - - logging.getLogger("brother_ql.devicedependent").warn = warn # type: ignore[assignment,method-assign] # noqa: E501 - - -patch_deprecation_warning() - - class TestCase(_TestCase): @cached_property def example_configuration_path(self) -> str: diff --git a/tests/data/hello_world.png b/tests/data/hello_world.png new file mode 100644 index 0000000000000000000000000000000000000000..5608007da7c65c34664b8d7012843a5319935a03 GIT binary patch literal 8165 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 LYBCj4=3)O2lBBQ< literal 0 HcmV?d00001 diff --git a/tests/data/hello_world__label_size_62__rotated.data b/tests/data/hello_world__label_size_62__rotated.data new file mode 100644 index 0000000000000000000000000000000000000000..154367363606c1be214911a893342590b44dec62 GIT binary patch literal 57419 zcmeI5O^PE|5QIzCLSPKqyTN7fJuKhBJFg8xU%?yI(R2czp^hN$X3=yx^Ht-)qj*I| z!>QAY7@%~@6hT;ElJ^k|Z{Oi;6AAf%P^YH1L{7g^JzyCCR8h+D#KEt85 zmc_C_1z^x_u`Eyl7_?g~3se9G?H0=d6@Wpz#j-#JV9;){EKmU$d<3`bKd&GCFhdDY zurABtWjHT+Dd5LfA$(j62W4+rfGEQtl||}vX$^gATQt=l7Q}Y2-f(Sm;9bKl3se9G z?Usj?<=93<@#7UrfP!_m7>@KCEQ@9NAeHECUZJV}!*Yqy=-ZSI7WqxEF3WD2hT-^f zL)Zw^;rk^phkBD3udc%zx4pwguK&J8z*CW3reD75@FsT?UIA}L$x4%bG)NEXzlh#S3V#bS#TysW)793v|mnf_2Re ze}@9_SFHJeA&Y7)x8=4It+yBsi{7&IWl^mwws+i%R_FBagEI4jXz8!X635Vpi|i~$ zYQcqspG2#3Z^OAsB8%ZrR?A{p>ec^#-2zK_J6M-xn*;9}ZdsrLF!&g5*(rBh#)X>8 zQG0W_tw@cDm`$kMZKZ~a47}}dL(BDogcVzFG4((wPQYW|kKFkq;OB&^wuzI?*@eiw z!9|0A>At`8#6rNQBUg*+njf+-Ri{J_d7$7Vnui{9^4xx)$_Qh1S&o^sYI@!#&#G06 zHhESp{b}K?7os}4dV!9HqbgxpkScG7=I_#q*?rz+^_RAa+V))86G{6}Y40x`w@61^ z(y^lUjHq;ceone-W^qdR1vbZ>V7>R(9zd1OL(_}Yl!%!@=iHwvPYOPggr zXWsfxPW3u`eaezD3<2j;C*XYQ47@eEjOq-0T@)cyr{HYr6r4?+gSXU0Bd+#vE7AXR znYT3;S>`$FlEH^j36IounTKC=aHZyHbXn$SAzV6}%fyL(l&Ya@Uqr#l#EEfB{*{ur zR6Wrt;g=XmRWCx8mN+$vCg619gywCIOC?UgTNih!%H3X9mnGp`;$-Gr;vAezoP(2z zb8xCO;x&d)*LNRojuEq<2|LXK^JOSETU zIChIQN4ngxTkf{{`#EUj#MlX$b$?65&p|`YrDH`u2Msk}x3@3&9*)+B&}|o&I8PYw zN5G}?(DWiTYhg0a;}FzLk%EuhfkI027~*oOP?=-DZA1yTY*0G442Qy47Rv$^fWf+3 z+R9(Fy2Qez;nuvq`e(O1tXtp*-wxK@vdw{a4Yw>%0T{Gf9#$3)ieS-O7Ryp^73~)2 zmUjf}nj8KO1>mn(^GBAYohyI>;2`0a@8bEe8B;n@0{%n5+a`AhbsHw&r-0Yz{rOe| z{5-`1`gEILKSIElOTgzo>h?|@zFX#iQ~L@moGQ^eJif0nGN(2c>hSnlg@99bVc>%f z9$WJPCmxz*e4g;D4E_@Ek*Y;?&5sFJeOX4dx8qgzWf`9XE;}S9hYz|#V&m2DuiO4O z4P{xr7NwoE6v~p-UuMOGtEzu%&sAUW9p7i6YZc=}v93Ko#L(iZ`r4+$aviU#FPu6o zuj5~;4qAG0UV4s83fCSIJI7#d5slB+b6oRnbJ>s7M_g?fN_GCsgsUyjP5nG??+}@% z(W$XNlX-fPni4VaJR~;Xe)f$BAxoaj+aQ5k4174xfUpsw;2Rux%W%sA6@Wpz5};t+Eruig))V5mhb-t D`yW%! literal 0 HcmV?d00001 diff --git a/tests/data/hello_world__label_size_62__standard.data b/tests/data/hello_world__label_size_62__standard.data new file mode 100644 index 0000000000000000000000000000000000000000..d8ca354f86019df1b2c110534f8e7d893c3f6270 GIT binary patch literal 13709 zcmeI0F>d5G6oxezAOoaP9~Ufgk7e$VZtDPnuaJi7QZDvJ1Ef!muoL70v)CdEEQtC4 z_efEa84qns0oEX~Yg=!~Pd|S?K2g&&Z=>D)aCiUX-Tg1WfBUZaC{wz-|LObY=jQ!> z^Q-Wzx7C(vOV)vGux3lOCF?*oShJ(tl3g+$vTh?)@-S^WF5!`YqnHdvJPZ} zZz)?`FH^KbcBYGw}DIH zw!;A%2Tk^k!h5NVQ!o|_tqFy-#WE%AaP+_N598%Q(KX%^PIL%Hc z|3$d-08;rJF2M-5p37VY|Ho4+m45;J;5~jazx}64xdtO#dKAJRJf}(cgJ6Bw_Wsil zZ8?E=k!POk<@PdFc(W`It3wfnI1J=|1e}^%{OmdCKsd_)ng)Y%_UlV+L0@V6!7nW&Mb9D1`A*=!j!J-J2~P0NmczS~z_E(V5vGX3PZ1u10d7ZR z4;QIOd2>K&v9BYXI|sjD3u=xKm5<<<8_%a@$`c%$ zo|bT^D(@7Yf>e%A`TrGgcWuXm-vo{XU|xvwPIS4x9cFM1LNAqHbdib{6t*CB13bP? zM7W&&V=%#Sk78TaaONA8pXslj)R|ENXQprh#c;Dyj-kC7n(g6GN?pBy(n+}ngL03C z9!1+9p3jvB_@HoDKwC68gKGvb1=u09%=Ui*{wMw218%XZJHgFhk<>fG&wJQnMk@cT z>$UZQn$e*)@d$>tHM|`iO7{N_=TzbY;Dvdv${%=~UD?7w8JzuAo2Zk5ij&W!F%w*a zvO_UM3&hRsul*jC+#U~Utfk@M2TeQHa3x zB|_lGV9WB&0zt0!O;ZZQ(vB|HR!E$9Ky z%9VH0w+tTc^b)v%ESjP6gDoMb%ELt&{BPiNmQ>DH*q(53`K}}_1Qi}G%HUt7w{60) zd$7DKcnB&S`xbu`dj5I(o`CT1)ru(R&Xunq9Zpd$Ci|P$!iO;l@}bKBk)_>>XeJx!uk|GlwT}?kJ=)* wxR`fc!RH^n{_hIUdRT3#wqza125YudTe1#hgEd>KEm;S$!I~{^%$D!|1zz$r6951J literal 0 HcmV?d00001 diff --git a/tests/data/hello_world__label_size_62red__standard.data b/tests/data/hello_world__label_size_62red__standard.data new file mode 100644 index 0000000000000000000000000000000000000000..05067bcf386b74bf29864662ce980ab68bd5cfe7 GIT binary patch literal 27214 zcmeI4v5wnD5Qa&!5R!&{RItcvBQHSXiYPci zoBy9#lH%RaFpOBcJj~*(lSVxI+kgL^-5tueKm1%4FQo0i-=jDC!<+r#*T260uJ}{> zwLiQ@{0GE;{Az#r<=f(I`O}x{@Y`2k@-KICYvf#WOBMIIsY>B)F?I2*Xv^aH+|tF} zVyWV}#Z<*tq7_*@w^+h>Zn0GH++wQYxn)Hb&n=cPo?9$cJhzytcy3vd#dC`#jOP|h z70)fEDxO863(?u{0MZ9_u zo?hJ9Elv*QbI_avQC$Jk4U-p&A|tnyGt1KFB;N%<vYLEKkTW zU$;zt+@R(hfjS%u+G%d{2qBiKTV4YBX_kDMTXNML8L>v*D8tss8<01fCa*TD`EsS% zLT*vFoQe&SW94t*lfJXR!sH)*cHksRGX4>NGfV+e3K z$sdI|#I^H=yh3+Qa&&RPvd&3WB9 z3(WxnZ;a%Pa6!v5{BbF`^Fq^LB;Vl*u~!zF_Y-+5Tu;a~ctbAs%8>lZq<*V8$pNeT z7FtK_l?C}}(!3KcoIlI(`?YA8xg}E)R>>Q=0zZ(R{8VG2jy?xr7mgsW0@l_@uEB}? z*viC6PkyW*CL~1G?u&qFIg^X95L<$gyuC_UK;BB573pdr$0?{Uk?>fqh?*<;6qL$8 zVmn;X(loLr(NEIuozLM{;F7T+Ik&b-UIjI?^h|<6j>U*2fmXnA>D`4DqUw&X`qv>WOR$)$WQr%?do3thp8$dpb$Lt*7x%_I5wqvYs7 zCT_WoZsCmz)mF&q48427;H-Hz@9A_g;zM^L6qQsm6hbnrBXaQO&nU-jKX|Pfweg>jIFYTbfIY>9}R`K3B~< z>`=@ZDw?G`U;W$*(OovL7}`USH9vmgPFMO=&)oAD@vkP;~jaMaY{6?qZ&3 z&Va1`*cK8bV#auq()ZB4mVu4Lh&XT@PIFOHZMYx4CQ_07mx}`qi zjpXDF5?q)DU&ytV`-D6ec%|Ob_EPOltT`6SE*xY1T;^NQQaNhrG=*xuteH0nN$**Zw8x!i_65Tr| zoKsJzbnr>u0t?Vf@)%Td`GF#_<`cO}Nb&~cR9f+)<}s+`Ev`V{(z<1Z{A`gUsN}I5 z8Ib=24OK#FjtvU{K?%8eXG>ZPDmm}uBAx;H!!-CL=jRblPsw9Y$zwOtlCz56eV8O9 zdHg5~Pnr-uY95119$#cYKE%%yX+CGJp+gqrF{tG6MPl*}34CZFwb+)LBe_UI=_of) zwP`St>x;zX4Z-BIa}kl#vY(z$PZmMx;PlqblY7?BZ~oc;;i;3GBKmLRv}N(%^lRzj zZn0Fk>;F|W0X{qES<#fveQwL*S<%wP-D0WYS)=ReU8{k!7>F<(vNil|`Uu literal 0 HcmV?d00001 diff --git a/tests/data/hello_world__label_size_62x29.data b/tests/data/hello_world__label_size_62x29.data new file mode 100644 index 0000000000000000000000000000000000000000..0bbbbd8f8ff5ded34fa4023bd8c92eccda107860 GIT binary patch literal 25427 zcmeI4J#O1T5QSGz!6E_JM@X2HM7cw{)ByrtAq{mjpCD)85tz<}VP<9pq>$ej^9&3S zS&xMQ4W&=ZkF$T=wOV@{$KmVY?%Uz+*Y9^|T1TAM53LnXY;g<9Ia65c)+)zCEd{6?<&3r-qEr_ZF@kBFh;OWStilcWzW$k%oPc&>xT_0N7`1?ia9_qPB&03h*oZnIEep2v> zyq^?&M_QraQO1RFA{9eMctUWfMp~o=8i2ukw)DQjT3zCii{NsefBL6vx!G)i7yfcE zpDizQ;90??1sZ@sWy{TK(Vz(4dTEiCe5bcz)jR7ekbMKG_5GQ(ypw3HWwz@C8zWU>?5P7K2mk z3M`zuqj~tgYoV4~@^D*zHZ4@TFz{9fx21W5SMB36_*w>kH26f-qP+9b;Z>Uoti7Gq zvQ1(S1~1zrRt|5}I&uDn+HR<675uUTkd{j${dKRQW!d7@zZ70o{k^lWw&et!;b6Xo z+CHwjR?#*S*R|(^4K3EH?aITpPHWXh>tTDE{#13)*SnAFiZ_YPHkhj#pWA+aI~H8g zaWr53`!JO1{Fw``>WyDdUY{AzbL@pt40;paB?Ewnz&!0E1=OqUkyI-RI_-o?pmO bwp<7~zmyiJ$ej^9&3S zS&xMQ4W&=ZkF$T=wOV@{$KmVY?%Uz+*Y9^|T1TAM53LnXY;g<9Ia65c)+)zCEd{6?<&3r-qEr_ZF@kBFh;OWStilcWzW$k%oPc&>xT_0N7`1?ia9_qPB&03h*oZnIEep2v> zyq^?&M_QraQO1RFA{9eMctUWfMp~o=8i2ukw)DQjT3zCii{NsefBL6vx!G)i7yfcE zpDizQ;90??1sZ@sWy{TK(Vz(4dTEiCe5bcz)jR7ekbMKG_5GQ(ypw3HWwz@C8zWU>?5P7K2mk z3M`zuqj~tgYoV4~@^D*zHZ4@TFz{9fx21W5SMB36_*w>kH26f-qP+9b;Z>Uoti7Gq zvQ1(S1~1zrRt|5}I&uDn+HR<675uUTkd{j${dKRQW!d7@zZ70o{k^lWw&et!;b6Xo z+CHwjR?#*S*R|(^4K3EH?aITpPHWXh>tTDE{#13)*SnAFiZ_YPHkhj#pWA+aI~H8g zaWr53`!JO1{Fw``>WyDdUY{AzbL@pt40;paB?Ewnz&!0E1=OqUkyI-RI_-o?pmO bwp<7~zmyiJ=Fn3_b8VU6k*razX=Sn59ha*fOE>NRcVAPhA_aZX= z*TGbFcNxJbtmz-WN`HR&GBTZRO;vp!$HTV|kKa8!{`BjY-+Wyk*r$ibAFArd>ihlr z=WsJykHup#6EH=u7LUbDz!be&JQgznQ}k-_Sj+@W(W}K{F%vLFuNIHROu!VqT09mr z0aNs9@mS0ROwp^wV=)sjMXwf*#Z15yy;?jLGXYcdYVlai1WeJZ#bYrOFh#ExkHt*D z6unwJ7Bc};^lI@~%mhr)tL48COX$T#JD6rxV!T$V^-7*jo)73}24{Cp5&cCH^YOA+ z4s-K$<}+MJL~k&+#<^T@jOY2@oBx>i&u|Ry4d-uz*RlIlEU$<2O2XN-`M6Uo`@+ZU z{4yJ7>CBVpW-N>5(sly1fH$awL);O5+ymYu=l?@Erhbb^)-&)<1KR8fuM_;VT08FK ze0O+&(G%B~>A0KouG$Sw$M=ED!rcxBOdK3CZxr6k$~cL6vCuW4aBXQ>676t|zwnnP z%7db-VkDgCBxZOWX`=vs!8#W)Py+vh@DKr{^Ceuw3~wWcxeWeSq*prs2>2mJd}n>f z_mguKGhA8}!k;3$N%)gsW19By{g7ihfp?K-Ug+ia(p6-$ULH1^B3u%1A?G9D^jzb6 z&x;O(a~Z&)Vsg%QeQ7LciwrZo!P%hj-vHMNQZd2V4au?8`FVo3GyL5IS24la4axC! z@R5(VLwq-8=Y)f&)1Pq3u@rupoCmoS@Z$omVuCkp!5oX=ml~FG<}ejvC-9#~CBU+X z6TEB7;oV8#7)90yOGM$P3{PT$whf(JoK7}{&d;~zI=k+whXOWvC{Nv)*3i}oumJ=NAcp1Oq^)w#g9J56iN);0v z9V>+6`Y=cUu)Kl8Z~Y%vr^cB zVtBK0j!XMysO}GkQ~K%~IGvoUn4Cu(Xi+r%k@?bjf)5Hu1dK(+1zanDCBO#hFsA<} z;J-89J>V@ybtiZ;v?%JG;paVKX+}E#pyPG#0d2;BwTW9W9QTITW5AOAufy4u`~Y}m zovZUFZf7^KP$+}5-DVPXvY=w;bE%pMuAMJuYRd@WhA(j*7S1Pl zhpe;n4P3SsrJ2w0yl=t2afWA6WBH=eeM=D>jZ!bM^k~gno6&2o|F&HKAaOPG& z_mZ8AvOmZD7S6M%@NliL9WHPV2O(av5rOMVguss}mi3zjM2_~&SQuvDPCK&;ps2JMW}z89d$THSh+u7>3$Uu_RHQr;{@H zpTKD^>71{yJ>lT;T}h54Dm None: + parameters = labels.LabelParameters( + configuration=self.example_configuration, + label_size="38", + ) + self.assertEqual(FormFactor.ENDLESS, parameters.kind) + parameters.label_size = "62x29" + self.assertEqual(FormFactor.DIE_CUT, parameters.kind) + + def test_scale_margin(self) -> None: + parameters = labels.LabelParameters( + configuration=self.example_configuration, + font_size=37, + margin_top=10, + margin_bottom=25, + margin_left=33, + margin_right=57, + ) + self.assertEqual(3, parameters.margin_top_scaled) # 3.7 + self.assertEqual(9, parameters.margin_bottom_scaled) # 9.25 + self.assertEqual(12, parameters.margin_left_scaled) # 12.21 + self.assertEqual(21, parameters.margin_right_scaled) # 21.09 + + def test_fill_color(self) -> None: + parameters = labels.LabelParameters( + configuration=self.example_configuration, + label_size="62", + ) + self.assertEqual((0, 0, 0), parameters.fill_color) + parameters.label_size = "62red" + self.assertEqual((255, 0, 0), parameters.fill_color) + + def test_font_path(self) -> None: + parameters = labels.LabelParameters( + configuration=self.example_configuration, + font_family=None, + font_style=None, + ) + parameters.configuration.label.default_font = Font( + family="DejaVu Serif", style="Book" + ) + + # 1) Fallback to default. + self.assertEqual( + "/usr/share/fonts/truetype/dejavu/DejaVuSerif.ttf", parameters.font_path + ) + + # 2) Retrieve existing. + parameters.font_family = "Roboto" + parameters.font_style = "Medium" + self.assertEqual( + "/usr/share/fonts/truetype/roboto/unhinted/RobotoTTF/Roboto-Medium.ttf", + parameters.font_path, + ) + + # 3) Retrieve missing. + parameters.font_family = "Custom family" + parameters.font_style = "Regular" + with self.assertRaisesRegex( + expected_exception=LookupError, + expected_regex=r"^Couldn't find the font & style$", + ): + parameters.font_path + + def test_width_height(self) -> None: + parameters = labels.LabelParameters( + configuration=self.example_configuration, + ) + + # 1) Unknown label size. + parameters.label_size = "1337" + with self.assertRaisesRegex( + expected_exception=LookupError, expected_regex=r"^Unknown label_size$" + ): + parameters.width_height + + # 2) Width > height. Handle standard and rotated. + parameters.label_size = "62x29" + self.assertEqual((696, 271), parameters.width_height) + self.assertEqual(696, parameters.width) + self.assertEqual(271, parameters.height) + + parameters.orientation = "rotated" + self.assertEqual((271, 696), parameters.width_height) + self.assertEqual(271, parameters.width) + self.assertEqual(696, parameters.height) + + # 3) Height > width. Handle standard and rotated. + parameters.label_size = "39x48" + parameters.orientation = "standard" + self.assertEqual((495, 425), parameters.width_height) + self.assertEqual(495, parameters.width) + self.assertEqual(425, parameters.height) + + parameters.orientation = "rotated" + self.assertEqual((425, 495), parameters.width_height) + self.assertEqual(425, parameters.width) + self.assertEqual(495, parameters.height) + + # 4) Endless labels. + parameters.label_size = "62" + parameters.orientation = "standard" + self.assertEqual((696, 0), parameters.width_height) + self.assertEqual(696, parameters.width) + self.assertEqual(0, parameters.height) + + parameters.orientation = "rotated" + self.assertEqual((0, 696), parameters.width_height) + self.assertEqual(0, parameters.width) + self.assertEqual(696, parameters.height) class DetermineImageDimensionsTestCase(TestCase): - pass + def test_determine_image_dimensions(self) -> None: + parameters = labels.LabelParameters( + configuration=self.example_configuration, + font_family="Roboto", + font_style="Medium", + ) + image_font = ImageFont.truetype(parameters.font_path, parameters.font_size) + text = "Test text" + + # 1) Fixed size labels. + parameters.label_size = "62x29" + parameters.orientation = "standard" + result = labels._determine_image_dimensions( + text=text, image_font=image_font, parameters=parameters + ) + self.assertEqual((696, 271, 391, 72), result) + + parameters.orientation = "rotated" + result = labels._determine_image_dimensions( + text=text, image_font=image_font, parameters=parameters + ) + self.assertEqual((271, 696, 391, 72), result) + + # 2) Endless labels. + parameters.label_size = "62" + parameters.orientation = "standard" + result = labels._determine_image_dimensions( + text=text, image_font=image_font, parameters=parameters + ) + self.assertEqual((696, 141, 391, 72), result) + + parameters.orientation = "rotated" + result = labels._determine_image_dimensions( + text=text, image_font=image_font, parameters=parameters + ) + self.assertEqual((461, 696, 391, 72), result) class DetermineTextOffsetsTestCase(TestCase): - pass + def test_determine_text_offsets(self) -> None: + parameters = labels.LabelParameters( + configuration=self.example_configuration, + font_family="Roboto", + font_style="Medium", + ) + + # 1) Die cut/fixed size label. + parameters.label_size = "62x29" + parameters.orientation = "standard" + result = labels._determine_text_offsets( + height=271, width=696, text_height=72, text_width=391, parameters=parameters + ) + self.assertEqual((152, 88), result) + + parameters.orientation = "rotated" + result = labels._determine_text_offsets( + width=271, height=696, text_height=72, text_width=391, parameters=parameters + ) + self.assertEqual((0, 301), result) + + # 2) Endless label. + parameters.label_size = "62" + parameters.orientation = "standard" + result = labels._determine_text_offsets( + height=141, width=696, text_height=72, text_width=391, parameters=parameters + ) + self.assertEqual((152, 24), result) + + parameters.orientation = "rotated" + result = labels._determine_text_offsets( + height=696, width=461, text_height=72, text_width=391, parameters=parameters + ) + self.assertEqual((35, 301), result) class CreateLabelImageTestCase(TestCase): - pass + def test_create_label_image(self) -> None: + parameters = labels.LabelParameters( + configuration=self.example_configuration, + font_family="Roboto", + font_style="Medium", + text="Hello World!", + label_size="62", + ) + image = labels.create_label_image(parameters) + self.addCleanup(image.close) + reference = files("tests") / "data" / "hello_world.png" + with as_file(reference) as path: + with Image.open(path) as target_image: + self.assertEqual(target_image.mode, image.mode) + self.assertEqual(target_image.size, image.size) + difference = ImageChops.difference(target_image, image) + for index, pixel in enumerate(difference.getdata()): + self.assertEqual((0, 0, 0), pixel, index) class ImageToPngBytesTestCase(TestCase): - pass + def test_image_to_png_bytes(self) -> None: + reference = files("tests") / "data" / "hello_world.png" + with as_file(reference) as path: + with Image.open(path) as image: + actual = labels.image_to_png_bytes(image) + expected = path.read_bytes() + self.assertEqual(expected, actual) class GenerateLabelTestCase(TestCase): - pass + @mock.patch("brother_ql.raster.logger.warning") + @mock.patch("brother_ql.conversion.logger.warning") + def test_generate_label(self, _: mock.Mock, __: mock.Mock) -> None: + parameters = labels.LabelParameters( + configuration=self.example_configuration, + font_family="Roboto", + font_style="Medium", + text="Hello World!", + ) + + # 1) Save image. + with NamedTemporaryFile(suffix=".png") as save_to: + result = labels.generate_label( + parameters=parameters, + configuration=parameters.configuration, + save_image_to=save_to.name, + ) + reference = files("tests") / "data" / "hello_world.png" + with as_file(reference) as path: + save_to.seek(0) + self.assertEqual(path.read_bytes(), save_to.read()) + self.assertTrue(result.data) + + # 2) Endless label with standard orientation. + parameters.label_size = "62" + parameters.orientation = "standard" + result = labels.generate_label( + parameters=parameters, configuration=parameters.configuration + ) + reference = ( + files("tests") / "data" / "hello_world__label_size_62__standard.data" + ) + with as_file(reference) as path: + self.assertEqual(path.read_bytes(), result.data) + + # 3) Endless label with rotated orientation. + parameters.label_size = "62" + parameters.orientation = "rotated" + result = labels.generate_label( + parameters=parameters, configuration=parameters.configuration + ) + reference = files("tests") / "data" / "hello_world__label_size_62__rotated.data" + with as_file(reference) as path: + self.assertEqual(path.read_bytes(), result.data) + + # 4) Die cut label. + for orientation in ["standard", "rotated"]: + with self.subTest(orientation=orientation): + parameters.label_size = "62x29" + parameters.orientation = orientation + result = labels.generate_label( + parameters=parameters, + configuration=parameters.configuration, + ) + reference = ( + files("tests") + / "data" + / f"hello_world__label_size_62x29__{orientation}.data" + ) + with as_file(reference) as path: + self.assertEqual(path.read_bytes(), result.data) + + # 5) Red mode. + parameters.label_size = "62red" + parameters.orientation = "standard" + parameters.configuration.printer.model = "QL-800" + result = labels.generate_label( + parameters=parameters, configuration=parameters.configuration + ) + reference = ( + files("tests") / "data" / "hello_world__label_size_62red__standard.data" + ) + with as_file(reference) as path: + self.assertEqual(path.read_bytes(), result.data) class PrintLabelTestCase(TestCase): - pass + def test_print_label(self) -> None: + class Backend(BrotherQLBackendGeneric): + def __init__(self, device_specifier: str) -> None: + pass + + parameters = labels.LabelParameters( + configuration=self.example_configuration, + ) + qlr = BrotherQLRaster() + qlr.data = b"My dummy data" + + # 1) One label. + parameters.label_count = 1 + with mock.patch.object(labels.logger, "info") as info_mock, mock.patch.object( + Backend, "write" + ) as write_mock: + labels.print_label( + parameters=parameters, + qlr=qlr, + configuration=parameters.configuration, + backend_class=Backend, + ) + info_mock.assert_called_once_with("Printing label %d of %d ...", 1, 1) + write_mock.assert_called_once_with(b"My dummy data") + + # 2) Multiple labels. + parameters.label_count = 5 + with mock.patch.object(labels.logger, "info") as info_mock, mock.patch.object( + Backend, "write" + ) as write_mock: + labels.print_label( + parameters=parameters, + qlr=qlr, + configuration=parameters.configuration, + backend_class=Backend, + ) + info_mock.assert_has_calls( + [mock.call("Printing label %d of %d ...", i, 5) for i in range(1, 6)], + any_order=False, + ) + self.assertEqual(5, info_mock.call_count, info_mock.call_args_list) + write_mock.assert_has_calls([mock.call(b"My dummy data")] * 5) + self.assertEqual(5, write_mock.call_count, write_mock.call_args_list) diff --git a/tests/test_web.py b/tests/test_web.py index c44c555..cd3a40c 100644 --- a/tests/test_web.py +++ b/tests/test_web.py @@ -2,32 +2,58 @@ class GetConfigTestCase(TestCase): - pass + def test_get_config(self) -> None: + pass class IndexTestCase(TestCase): - pass + def test_index(self) -> None: + # Should redirect. + pass class ServeStaticTestCase(TestCase): - pass + def test_serve_static(self) -> None: + # Should be correct content. + pass class LabeldesignerTestCase(TestCase): - pass + def test_labeldesigner(self) -> None: + pass class GetLabelParametersTestCase(TestCase): - pass + def test_all_set(self) -> None: + pass + + def test_mostly_default_values(self) -> None: + pass class GetPreviewImageTestCase(TestCase): - pass + def test_base64(self) -> None: + pass + + def test_plain_bytes(self) -> None: + pass class PrintTextTestCase(TestCase): - pass + def test_lookup_error(self) -> None: + # TODO: Where can this error be raised? + pass + + def test_no_text(self) -> None: + pass + + def test_debug_mode(self) -> None: + pass + + def test_regular_mode(self) -> None: + pass class MainTestCase(TestCase): - pass + def test_main(self) -> None: + pass