From 963340fe3e609ee140d5dd19a6af7a516b72be72 Mon Sep 17 00:00:00 2001 From: cord Date: Thu, 25 Sep 2025 14:01:55 -0600 Subject: [PATCH 1/7] adding test coverage for shapes\surfaces\nurbs, designer\design, and designer\geometry_commands --- tests/integration/files/boxes_w_mat.scdocx | Bin 0 -> 57932 bytes tests/integration/test_design.py | 112 ++++++++++++++++++++ tests/integration/test_geometry_commands.py | 84 +++++++++++++++ tests/test_primitives.py | 49 +++++++++ 4 files changed, 245 insertions(+) create mode 100644 tests/integration/files/boxes_w_mat.scdocx diff --git a/tests/integration/files/boxes_w_mat.scdocx b/tests/integration/files/boxes_w_mat.scdocx new file mode 100644 index 0000000000000000000000000000000000000000..d667c3912df28dc1a9414041e1f683a6619cf8a9 GIT binary patch literal 57932 zcmeFa2O!tq_dou8AtXB@va|P|k!-S8_7-JtMO0cU?Io4=&=Aoe6xu{3ZKX*mT4esu zeZHPgUZmc=-=E+5{y*>ge!o2Lz31F>&*R+ne4Ts9!G@lJ2g5LCEG$~ri`O|#>mZa^ zC>SP;O~agH0)j$JA_BrAm7RmaLLvj=m7!*Sz}yg}l=xuLef*eAK5G4Q+LCjceTfQ> zS@Ptey=_cqGGoO=SI0W>@ios)pBdy;n9ghHN4Hc@?^)i?h4zkX?-%m*=IgtEc9~xO z=!APM|L1(qGgVR_XW1!jE|+YNm*wL$eP_H^E&qhWt}V_BW-e8;DLQdYhhF?t^oGuc z)UvAr`}S_M=w9QWaH6Yzs=%3d?+$k^o0zsVfpPVhrb@ciKYF-CmK(DQHvR~0pMJD_ zch0udZ1wXC=^aLaH?rAs`W7Gw0q~pvJ~%qaAuc*5UO6BpMkysS;&*VDt+!u&S%tIq z)8$1gHufbQTPUw8zTiwzLr9lEYXjrwb<;fuzVCD^J0ZQ}Zh61(m(TCs9CA%E6FHzc zzv$Maq5zRey&We^L?o9hP^31Wjq%;2W$sRw;Il2+@BBBmTI9S&LK`$}0)jGJJf(v;IK2hxyrhS=p4?L;i`Mo_&jA ziBHEk!g3$nUm_oD@m|xN=glM5-t+pwu9_7b?^8Z>H%_(L@=bl3K#7a!Y|29sWEB>C zMA4MU;Nkr!PLE;eGYPEX7Z(x{udIZA{>~tu$|?5UQvnZe(cS6cQ1T037jQ;W6=|&?G8;hIm*)LX4iWay)g?DMiPGL;)o< zIxaFGAzmpuZZ0_wmDN;Kw3I=c5gFp6Ws16_#)J$@OioT#ibu0L2+eAxpy`Z1!68a9@sYtnF$BI)Rc&>xzz}uyKphQ@Agur#pYo`gZa8}L5&X1jt21n+d0807 zH+tu#9p2w9xelMUxR*K`7x6CZep{;OwAu8=r8`-Q4?}GGSZrSBZeO*^cTU#yoYXL@ z8y1z11|L{Fa(^&8lgV;sk*8M2v2b?__f<2+)hVyKC=3UN`t}T!41IpJa4nNSZ4`gn z!@C@3E;6zm+WV66i}J#P;L_-hfrHT;)onKp8;d(7>Cc>WVrfsOY*OV1#f`zK4Q1~QXdE_ z>k8S7aK1mt~;g@_F!)yEEsK=sL_RZ5hUb*%!&M-F*zZ*%}8=FG4b{=Jk^3}O`*iI{_ZBsh;?EP;;X6+KQvJCoMeqjDvr}^3e z?Nx?@FKdFHd^wtSnsTeF%10?I%cwC>>4V#PfCWlVz za|o#JlJdVI@%EC&m>ewWt;5?dA}^cZaX3fvCGrlWx9F#EzOtVm)}H{XB`zusrkl{`D~YO%=;eY0g)ljW9B9k*7*r++dFhS zWAF}tzPpyVo{7*2{eqC$j}uzNcRgHGX5-a2z##51|xKOTQXaN#W;x0z7!j}_Py_@d6+*c=~!m~9GGsEs5J$Bkvk56KvoXZNQ zT(*^bi{nkECG+k-oV_k7o^4^_eT8W}moMZhu-%Yr4V;oS`0iewL8j#74{Cc>JqFx}7f@ zQm1eqzJGGL|3KlqD&f>aTsG!2HrI%xNC~Xi{XTe=%n}1^mE87qo91S2Za%VEzhvi@ zxP@;P2oI%{OdqQcS zeOc_9CE3{#rgoQPtR=+t6APX;$}PR4aMt&Bom1@mj%z3O7o2mI=)M2s)mQAvvB45e zZRgs$M;pA{onzid=}%%dvVIbrPkC~z`1uuW9=^E~D)_A9JY+w8D|(ebq3BrrSM#C; zavn`n(*!*Z(S@8XYxu58IEpQ5gPYVUiWqjFp}?gi|d7R@Os zHsbYfn-|xAr$p#Wl>0XN%_k#wB^BIy#msOksoK!Thh4QQLi^p_$m^;M+dG!0T~Msu zy-G^*N=Lr+SxF0uPl4o@M6aT&OONO+@oHXwnttUmiBE}aQ}r^B=-u&cc1ZPA^f>j{ z?MH~B6+BWS6?IYR>wM?ko-P)zyWA8*8y#!u3#JsmJF?I06!r0GOXz7$gG*~?rOFrU z9WufUR12io@}Dz3a`?fV87QZ4^#L#Aob1_wA6V!W%ucE#Eu(A|7v%S<&SWXxE&fc9 zoAtrg9pd{0o%XeG=YQoMO$5>+T~820Nx8X4$rrG9cuHs3tAK(%w{@e`+C0VQCvS2m&SeF*2ND5^0%{O zMU^fznl@AQARl*cK!Ki!2$O^7qds~b=hIqY;g6zrJa)+++Ir~I*7LR#DwsmcjHR6y zKVSSXs^R*FWA#rgKZTwRIrQLT^Vg?I4!2GQ8u`s{;>pue+cQ#+-gXSPzseV=pe$ za6J=N+034OaOS(MJX4H>^XFWMxUrKF5;$5 zJ&!}Fpz?&Yvj;lM6_s`Gn>@@Z=b77Z;K*4ajnk~l!UdZ&FYm0$Exr8EPjKFS%Z))L zlDihC30lP+Sze?!T{g$V*h6t6&oh}_Zx;w!vG{ekq<^!8>L`yp@~_TrIMDees_Ax% z`9^V;dvWzQoTjxcL9N&mJWiz#lu>dteq7|LlH^(&zP|9u%64WxE4_>Lw?1%1?rFdH zebHmpx&hy^_aBn=itQ{amx^gyCT%$2e8IAaXZsBmo91JN%lNG7xwP|6gjFune}9ns z@!q>Cfls7TjOEItTx69#P7so`diCrC_l+CN2I97;H5oJBD_I$Ed~*Aj%At4RZyXmW zesG=JrMYO}fX9)p#W$)Jbgyt^y!~TH<;L^9DaJcO=jpc{ynJ&@2GgESm(+tbNxKBO zZ-s}>_1s^OD0t|ZiuJ%9ffOl&x4s(UI~K3Qbd64Y8ag3ZmVEN9)a~;&{dYKhc86D< z{FYK;YQOw>(MiqYYH_&=(C)1>h9BRzP3(264m%_Nbj6Uhq@GcL^5!%7 z2VCV;^AG5)xlm)Vt>+!LNPu3hcTnlMOY)ohd&LZ2n^b2XN~z1%+y8v4eM;r(6-@`7 z%4C-vsiQ0dmMo)-7+-{I|2tW>;z(l4lXm8i_)Bd5jF4hp90%Pc${*s`E-S7~N* z$la&G=cmoQXx~52ZHjYk^XxU@8_!)bIC;EKgHGnozDJAPi#v~1*mbW8soHPnbs*hh zTGDIXx_wV0x6OGj+?0@;b<=B`A^X#nlRgaz={YFgEE$+`&Pw4`bnWTI?dwk!PK>I* z(j~h?idjBpzE(z2?9%SVdL{xjndWzAd&!=e+An0VJh}hnjM+#^3E|Yekt3P ztr$I6)19ZRRP=Di!Ez0@JF|NIuihT?dB^rNWnzz_>jCf3O`^;{8gh7R-p}i5mG$rN zA50cl7Ry+AW7*NK6`$tL+RME4^y2E&Z{7LcX{B?y0`96GvY}h;^Uj#QSDd#s@WHaZ z=dOIZzOqkon)hj}Y950P)0_dO2xshZ;p3A|N7+O!%Lq^4d*v6==`U_0ndjeX_sPO| z)_$heZzc4$cbzXdO<;YUHeptk`XQyI6?*Lc2Nm|`9$|FwV9K?bLdo(CRT27<-}HWa z=&AjJ0t&A@8G|-AKc1LwUC*Bta=(78$ti1szwg6%X}uM5kVecX_rx_ohZ^vABPQ zVXuhk@q0OUW8LpRR59%-WxTJZo^a9h$V+7}EzYVGPG+y`;qxxOE$Vu)ciFb1A5yps zeM5uyW=xY>eR|SjeZQqA3(mT$?t0E@KWm-&x&GU^*LW@aW~}-6DNM!8q?&aJz3dqW zx25t$DN>IP`KfN|*IgU2Ng-z9y5o)k3okoA3iGbn=wvL*s=j}+gsQZn>$Yr_ILqF{ zcGm_1E#Gn-jQyB<^sL6+=`#(|=1&ZN@t9*XkNLKx#hYR!RrxQ{SKrgPtM)ke8Rf~5 z%8cCSHSG#780Qx;6r_mReu&;6wMN@!^8KwImmBKp?RUwW7QthT6d#1j$-=(VN?09I+ErI3(Y-cW)q|z_F_NaV=SIeV&ds%izZ?-%(HA`}< z>gwd_3kD~LZZ^2ww9U!aPUcgteW`EK89j6R{-8yn+irjOyu+uoPRU<(=_a9Ko1VUt z4{P5|J2N}!=4**NHk!LO->qA>b#D9P`raUqkh25FwXNhu3U_|{RJkj$GS%pPbK{Su zDGNRKOnha(d!|-o7+ccghTMuMlY&DbE7$YoHfc-NmTeNVtvX%XJ)_Nrr?$hdP15U; z+>l{#n$adZhAUgHUtXIhk+AT?rtDb}DR#T7UGFeCTg@8EtKaCf|IB^67V}+Ylo{Fk zI%7W!+UcGwo%3$1e67@z#T$fMVsG%OXfqVGR;@iGT<0-A#Wvq_!$vjT30|4qQ%}s1 z;Lb?iwRwuYoF(tW^?AkFUE#&hksm}+Hbnc+s-k-nN`U-cZKw{>RXCi5=%GD*jMA2HpTqor-1b{H(Fo1_NaIE zslAr5!k_!N1|~Jf8Z6MecVM?l%thse6KA&w8$HY3%dji)`T3iYiJkt@w~q8(&0PBN z^r`n&AIfCP4_~_SeWzs+<@T4Wij4Nyp=L4DyO&))bNShC-*4Eumg^z=QzlDa$DzWi zMOy?+L)L#75SyEBzOju?TJW+&a$?0TKMT5vFT+jZOFz!B5oPUkAYoEP3J?*Kqx8pZ>B`9?gBzVs7ty!zi@xl*k#I zjXcwNZBG^Zt$4>F6PPF*+{E*l-|xgm3vS)iId^#WdmY?x-urH*l;d&^XFC;!o{Av( zz#Sorv?M0vg-@YiNBoaU)xVKESaUkKnyYa~-#w8%tWx_6Zl>kjbNTUP-|Jm(=NiRZ zcsnaacHiZXnt zV3v?Mz^;8~8VB#SAR%6pAFp3bxFcaHN`Hwpr<%Eo<;pf5hW;0!Nky5S(%NE69P8Rd zY7O%>GTJW1O-i@14YA*GWzDAb6T2KvyNC&vschI(-1yvm*{W@CF9To?M?fg{g58-F&g{j*RYf%h>KNxoN_% zNHw$3;)z^USyf7}-maFl(@{4@v6%aMQG)N3Zf+C7 zDO&P-l%MBp%$m)o&}%2Y?SMRg$i)Y&Q*LEGjjF=#Eb}CWoMd|bRHm>>U+sN5{k-~5k}vWPxS#6U z?e;>~tK`K}Rngr{&+~KX)-JWv6Q0kU@_yn+t?A8s1*e-;wUsOky??=4RBKbrHs5(J zi*2{ClsYYQJJh7QVCyr@HM<{1d7UeC*|hb-PQ}a2WeCSe!g&(I+5ISz~;n18w<*J=Iarq)5&evk=&E7RUQPFmI za5K&L_F|#iuc~8ebFLqo-_f?DNBz>i6xF0D1Li*RnzJUix@J_*uYO$24EPih5 z3lw7^){@tX@|tExzcsdB|K`nHKi|t;29A{{_1A^IIpxRc>;2fxvEDm!@`ephVj?x~ zp1sFp_;p{=v3d7T9=Q0#&ef+R^Rw1!nD~2MX7#!kJ3lGcTUx^JyJ&T+m#@rOK8M)s z>zw-)yOw{wWIMSkdanN#INBdi4_#F>umACq^n*3I^Q1OJ=6~s2ZuEBR$;p-G&ua!6 zYhEqU=8FBX^I?Lsrq<`hg=NgU3Os~kmZsX#T@vrp>119cR1?~+P+4ro^U?HcEc?U5 z2E}}dS}_b#I)*CI=N8^Nwe{)Uw~M$YKCo5Cr27xIsI0sCE=EFHKR|iPM84Bb*Ccqb zY^w|-yK>p<2STv*wZ88*Wnz93BC3zwSYoPJZI1CgQGLL=pz!I6ZvMqAff@FVOX*ln z@g)m0ei2*6*E96klJ{_*&xIcwzDu5rVwB(7CH?VpdN9YN1B(}3DXXZRUHrk2byHSF z9Ruslm2V|9WRweAE?+O*vuvfol9_XwbTm?oKkU@?ko&r|$vKS!|KKAf|Oi z{SB{L$z|FO>4g^x+gAsfdhR?^w`zLGe3x%)HZmmY@MkTq?w)4tDfeD-LZ$Y=fM1K* z&DR1QTUkyFJ}TeyNk8Eke|gEgy6j|4SK)V84nMoWTcN$e=#j0MsLcMQtx=U~hAvT2 zU;O=xl)v?{vhCUXLS3W(@iNA?RmlbN1ZxhceFvvhAA?Y$?+y>hwC-HK0~ds_Wr}HLsIr-Mb)asZz_e zOwLUFCPg)$mus`5Q}F8THSVuJ_q|uY!&+f_wB~TK*ai`^){yD19<%4Q9Hqb4y}#pZ zdsB{mA=B$BMXm`Fm4)t)CiZK;kLydjBt6=S>OBRIE5U+i7~xW7w5OMPw?gah{mXln z+ATIwk5xFApAs*eznVvP^L0_{OrEfvk+~-)8AggNSR7o?8{zZS^5U$i5_Xa2j4!G@ zKd7Q!S;4_$QJFD#p<Od`PQoq1)D{xS?q5Z9NkjAdA-1j0oH`=9tKfT-MKoq zrBFI1vdytDr_(jcYI31bndzGu}Zt%bDFb;a-l?fsKodHPpS| zZtU#O9u!RDE3!S2U^sc3WJNpQ#7Ifi-FGfbVc_qXWD_H6-;i%1Fw4m{>zem&N@D9} zfo~i0@-O9R$RuN$cdzhMG|%$gpEE0Q3FEZzl#ci*hi#6@SaR^)=WLQqUMjMOF_XdT zORg%r?)wOVAGSL=&a2jHpIef9|HP^X(L1f5vX|{LSxoP~k-08&{TH9+=Zx=XZF7G< zw0$t?L0q@;l?oZkr+KSEJC8;x+N|Z?!Dp?R0H7>Ed&;uU*PX91ZJtjV$~CMaWb}Z zwzYB*HMg2=CK?nM5|9uQEESa;M25tNeWa&gR?IQc5vdX3Q6ZgB0uoB5 zRuiI=qe9|18K~TxfzgRk!2xlpeq+S24HJgtaSd0E5p2vE9u*vt;ujeZ;};zo8XuB? zfijd}ZBazvkg=oYLVcs=Q`ePAJai~(se>OZKSxo)Q38kN?ZR5L>gHUUv77(Im% zGE8v)J`rbUflF3a+{k2eRG?sv*bwX)AQ{PL!{~5kcKFGGnPZbotR_Z;gNg}o)rsqu zXvGp0oe&og6(1Q+HAw^-0yGM&p@1_aj%o=inBls>i0GjCU(uL(GN67j1`4$&)Hk~5 zM^8@pj}04Q#B%To#K48C!wo;xupuUFF;3vZCgauep)I_ZhTJw9E#x_A@nS(%B~X8p zIte=Y9A?cF#)gseu!bqSd22ec% zGaS{#0O}>dj8ed*j~PK}CTcPRgOeHx#!yYcX3;be0s%@mO&995#~O%c(#^uPqkt?5 zv>7w!X!x`N3F=E8xDX+o>0-a&jVy1BOHUq$zLrDWu;-U8~lfCKT#0lz#9fF+bb2QDC^YGWYif?cfeYDF%PM8T}VL>f?Sj7v4c95Xd$XAAuMI$GK zq-)}mXAeu)05$c9Z2(DE2S!zp%Ma2`2?zjH71j)r&X3u`PcC>OHg%Y2^02ffLCFqD zw*(S~*$+!M#T=kVM&KEquI!zL?>>r3sz8*m~NdQj&J zPsK5dbxao{+LN7dLQ^&<_zicV1vAMA*O%IbFHCjRg(%edkJrU$LygykD69z#3mEP~ z08n}1`ck{_hjod%m*kOJ8J z@zd=OyBI-3T~vYCHt2#4x7r-yn3iu{iSlvjg}RPp*yEE2l^%atDcQVqlfV~{5WgaX|J1VmB= zM8RZ0Q-TX;i5+G`Lac#}36rOeP!zCnK-ccTf({?Vzy(hV)QQ0hoIISi4p1`1;G`A9 zt3`m!3abH~R%)nP2Cue*X)giC8+zrFM%8kVF@Zzd6sqlTAs~(mxR7ia5GDvKM-)oJ zh+7&mlF-}$xXp;e9gbs3;6a*60U-23YlXk~qa&JXIBDq50gQ>zkSAjTwiD=Vgb+_S z4HJQf34eixZyXUJa|0s$@Na+d7bKB7soaggT+8?h~F^F7UA7 zU@5SFCtxYW3UXpFJ#*nbQ(*F@5k05j zeQ6LH#$g+AKJ+SwxWce>m?n|$i~kc7PT)wY!5CGy-!l$)ol)ZOQlj~W4mz* zdLgC2?D4~v5R^GsK2AYj1t?I@jx8m$Sd7coRiR2?$M)iU=>3`klIgK5f^R96kI*lR zTGFEGw*)WgXmh~}BHAOg;I%*rCJ5?H3X>NG5xO9j0xQV|UvEE+;OO1(=Z#hv8tUL8 zkY?zW^d}KOrAa@FpsMOjRaIj$EZzygk5)bfzI-vlPx#hrjWL*5{lXJtV&cgIEjWRb zn!x7)`9JxO+BXN@w}v`uF*-Co*5_tkB{znl&+pu2YX7>+2tVBaTz47nF#GRtm-U+N zp6;W*qmsJ1vnq*o^NR<$Uz5*aw#@O|Wn*QJ-a*K=Biq1F?y_GA_%Cvo4PL5>|MVhm zczj43j&+xf-)?GH%q$J<}@7-l%3^e>gA_U(oku#5UmyIzH4c};Y*;u}jff?;C z8{03*_piI`|3!D%*ij{y$N0~2-DP73eEg{mQ5iNBQ64*1f6HC=`;{{MvPE_^_DS?TuDk5_XogXYRewx* zTzA=6(W6(!7zr4Of_#q9|8LIva|(^4fIm4DYuh6ErlnU)&3olpTe$+XnK>x2r( zN2a9)?lV+CE;21OUFsPBuk(;0(a1xlrK$cq2N_~R4l*rGLO0|e)6&$X>W187TAC_< z?j0LDY@;{7pZC>qyklcUfPysXXAx9Qk#|f>L;L@*-;9zNfkXtnQ93~;( z*hIK0L#CmIfq`p$tnAVI2ibOH69C^B3pnkO40I1m!G0y+FMVT^hC|6v#2g=dsG(%6 zaAk+#AraK8H*`lX0ON}+gol!`!POD!Ul2ai@L(t^BOXeIDp4Sr2&gBD-z18oxUgwN zD47IQPlp>R@?HjU+ zOr#0bvv8^AC>+ZI4<+LmHjpuH!`XN%G*QuAoeij=4a%tE5n~!Cl+1<*B{N2s%)q9N zvuT2S6}U@7*KEQ_x)$8zVGzGSnqL#t)CU;Ubwv$SQv*4tOXTJ7FGY(8UENrz7lp z5PCh_QXcGNHGI`B3^J&pWLDsxLP1f(Th`do2MOaOs$+{9N@fjWkxHb9;Q=3~9ZeMy z;ST0RW|#>A=D<^t*!PAPJq}M|Q1$;!f zKqwwc#*Vi{K@0OBiisWQ63}?wumBY3pauen7%|ihAF#~@O=u&|LSQ?U0yZMN$Py2a zP=ju%p=2RIz@s{d#rLbx$ONH~hE0`;7k~PJd}Dk+g_2DI{1!eG;7`-&h3f(8$_$AQ%r*{5_gs6oiOhJ&Ka zv7$&6ChS`u18(?E5L&>6njRU%-hLYLiy>P)Hgo4&kSeOEw zwrFXXp_3N?u~?`Sg%+(?r-?Wq9o3^$p#Co9u@@8qP65&_Acpw=&Y?^3{10jYB1&ARw1p0cpMo!ZZryPhQ4?-7h*&1Fl`mW2Z9_{+A8XVZ!BeO6qz)1Aq93uzYHNlbO{51 zLi~haM08X}NY#y))FC*BHJ4{=R&}|tis1trWWdS)*3#C-hh@~CG`-7g@<(xF z8vpvn{`HN)^!p#?8~Ysga%D+Rf)TN7e(@l;X!1GCmias17%6-7{z0}K*#v&+8yhR& zztA@})&#%ujgfq$b${g>8_V}!;~P8o@y${8^E-wo`mcOrKl6?68zcG1$&CW~#`BGh z<@?t+_W!bPj2ta;8IAw^t#9nlMf}n?Hg=JY)?#Gi{11F%WEbT0{dE`r*f&OYFKCQ|YTwu|OqEF; zm0?p6<*{S+k9=d}cRBpBMRqmzN%Z|&-`Foi4Osky}#)j z`~B;}&#Q)5KbhpJ`V-%nHW@R8d}G>V%oOsCX_G-$|I|08twp%qkZ(*|i*UOk-jc-gx_y3k}Oj|?eXWtl8yyw9`i5t`W*EjaBZ|r}bZ;ZOOvxpa%(aUtC zL~haKbC~j5-xw)-^!`D%9oYna=^Gm>;J?r}Hr52c@{N&vq;-Gg8ym~_U*j7ifDeBu z_?2($XTI@$V}!M>fv? zz&A#AL49r>UKUiqv|apT-x%4&_%Pj>Pj_{PXCMjL9pF8;A^jO>Ec zcKqjm{1!eG+~D);IPG z(PP&8SQKRWx4tn_H1#=l3mFkX%?+a=2@nYKZ`{~_sc%e2lZZA#zA+t5ZR)o3d*7Ij zCgEQBy>CoMgYbbM-1YwI)!+NZ zbhHTFaNn3V;kQG+F&!=Szwa9(hi&xcH+(t_Z*sr!jgcaTdGXB8B1U{;I$A3Kw|rwd zs=7b>#&)y_rOJq482XI)*U>HF0%F3#gW{D#;h&a9{ho226zsh-DtqlECHYW@Vgk9l~9$5K2R=4btE0? zQ1vh!m1yYYs63XAYKZo@ELu8}kLXA*6v~IehaP@X)k7Ae!)s6-(vuPW0Xs+t6CLDH z3zX-DJffrgD~L0s%7X%=i3HZ%(O3yx5eJS3W$=_`AvgnUF)kfpCFv+nZ9#31%IGs1 zE8-ZTqtc&Z<)XpLL4$QN4OWDk7AqrxbvuET)D`s$dKgikBR>f`iDML<1}ix)hUp|$ zQa&ov%BPk|-Tr!9C(&S4q`}HYgB96;7Arl0b?a!X1Qs-ZalG&xHAly#BOY>&6S`-T z?V((b=%lU2qocY%9oIn=2MY`NvuhbC$S>jh>gS=PGFTGu#&nW zIiTn8zE3R=V}&t6X*3;SA=>})+#uysZ86fGv<+3azs4Gc7$G4X>mg5Kje$Ig71;o> zkyt|stWu+~5?HWI0uMZ?=f>zcJerPpNIIc=CfOd!_*@xni;?z-j@nRl`)jNLh!GOP zf#x%bbsppa%CHTn@(?HdiX?$`IxrxfpLHG92Y-(nGY2!F34BJzXY{xs8kPQQtRwWl zgB7hsln_=lZ%M4Q&+|O13GvY%j8}evfqm&4F(uQ%6 zC-;Q4kVoqQrG=13wnZrg@}wT?A&=G)N{bv_*$dhw$6XcQoQObfmxwZ}xdGdP* z!Ge`SJxbp2B?MtY`=nUXA=oc}-q%qbNyi(FITuL!#)LXzFaG)5KC39LAsie;odl}5GI z2-eYbRHEvJl=}TVyonegAsp8sPhzcuJc$+IMrcsTa2_PZ9~=Vud&u5Mo0+9Tga1GuR@;0ifn+`NUSFatZp<|N3dX- zFs?{ncv8=e(Q|k-oytSI21e+B1)tZXtq5!&mnt98Q5{vczs7nFF+xH(svu8dy##p% zq8`}*v5{Dh5m;SDu+pqo9AhS-4}NYStTb~FXv26QOC9&|=)cBFZU1+%qP2(;!hz;3 ziIsL-5pG(nhY74sBUowXC@v0ujGP;2Tt=@~#4~bkkhUOOQlBI5iil1#ZwR)(e{Rsu zVYGHhtZ1Ji#}$n|i4~n2Rj2@|9+(jyN{x_5>l&qU$dfia4|#G=xCeQ(9#Fard1PCZ zDj`qm(F}Psk5IY>d1P~xY9UX~!AFos_DAU^J0Ze^ zY?pYg4$g;PpBspdH~Pi7alH00`l~09#y>X@eLVT71ycP_&J8}|J1oLC8S)4Q%1aSA zQ2rYTqsoHFSi1?V&j=n;SJW@y9Nzb-Whz#haUDe`vC_hjtB&v|+wQHq2o?YW^z)T1ZDglvyKIP>t2(PM+`J50heqtEp5=p;X)jVB+`|IR#&Com#> zsgNhfW*+3pu?dAdIW|bX4uKUt39Ps-s9zvwQa{u^57iO60?*HM;3aMK6CL=6_ZNh9 zYNr}C3??ytv{b`B#<1LA4ov9)gA<(ZsU{Ukp;e77iLrDND?(XS4kT~W6VDZMh; zc&2IY`@QS#xxb6Z4RkJVKWHaSeLp0yuhqrxKgG+B0KW}m?kzdWcLCk!yqE<+2 z_FLwQ8sSG8BlJ?wm<1Lrbl1MrF3ra=fyJ%9qKRu?m|j;@p{4klQrVY+K_=Xj1wPNY zx;Lj;>YjP4?MA04C&T52tFOE%oO0~R=04_SDJx~SJ;;DSM&EfIqwXEZBT+g>%HeKYvY^UWVotL!eq!=`vIIjnstw=5NGMI8D|9SoE^WRK( z6bcd@4~J~2PVI5)NWSw$-#%{wb4>KjH1{c`VeO?isxLh3ZRb`GV@h3da#zirJzgEH zw~{6m7tt-M_0PT>d&_6*49yi$kCc6clS)tYrgO#UUj1=i-uq(571jy++k#)UEm-69 zB3?~yaE0U1o9c3Q_1BJ^d#5gUQu+3gi8CbjOBLNdvg*9S%OA{rF+4S|W+g}{=TuJT zPM)&6XW)UW_$ltxE!PT62bEV%6WWt|S9$bs`yY|5(uB8!oA5_5r;Z+OS1aY@@TlPE z5(fiJEwadUimUwp8FJ{)WRJSo_udgI&JYt z{)0rDh}G7`?DJLq!{P!y=Y84GKPdAsW1veqbuipD)qZx9clJ$+z;gO^t7gCPR#0XV z^yz7P{$q2wpDV}emN|#!mfsiNzOuK~xlWns;QjZjMIS_+t&Y^#Ja6iA71K+7We*MH zA7=M@-^yzBR989@trgS#mR`W~y>H4{Q+naEIFn@JDeTj1!m&Z=JlbVxzwe~o< znZ{}b7{#@6WR!>g|jF3meW|NV*88}fH9&*tsTIVQnNk*C)@eOzOv+RZIoryd)B_Thew9>Y7f?;Nf+ zxWvcg3f*0_eDTM3@0q0D?F&>de5h7DxTtt?-pqGZuAV-|r;Hr$e&S%Uu8v5}5x<8; zm>a2w6g20EVm^5a{5}K0^;e1)^ybJrAGE!8@08)K@7>murhB=)-lgfudDP~7diBcmTa5~GprK{t{Jax9)eXo43?0zjEa9Z$z zZ+YyL>Rr35_nypRSg3fu!6!g4*|Ft@Z@8e5M$JW@WS34l;kfkl*jbY$4=%FZQn86{ zckr=KTfXJqH+bAtxsO9c;NA(<^fym$HeFqJyIk;#@CRA9CvUbbP1w*XvwFv#I|n*n za#asz*|8XTn|c&sa*7)#8K@}JH|TY4{JKYE|7Q8`TZx!0!6&cQ#{a%_BXQh9&-Nn41 z>UummUc^X}}9bz2)&umU>XkPOf z{^m6LOo4qkI6BB7E;=S&IUy`DGB7G2JVGfZYVPlj+EosA7Hlj6=r3%uSy`GoQC~{n zZ`GrB5AV1mq3~dsYiw(bVW-zk>JLC)4JXD}dca@EWWS6)6kZwYOsJfiU^XYgG$cMK zE<7e7JUWWz6@X%ED`uApHx-J}R;I=-DZU-MCMNK_-SUa|gU%PbDwAnUYu0)MM$F7i zqIhmtzdkDq>(I9h3z^Iv$hTU>zmO7C#Tc}7?deNNfr90yCx6P>r6YDzN9=YE-^N?l z7p~L&B9$6kf9vKB{cl4TD(*BlHJyk$S{9zz(xTgKshC($X8mobrSIvdf@3Pn1Ni?3 z{r@T6`K#?z<^i#46)|Je2kS2#UD|ExV$t8Cx-95q&NY$PkAjUY541$*%`}_i{lIj< zgSDDLD7S}6imiNm(}u)>>l}Lyh%D+g;hMkOEB<1P^NW&&EFaISC0uFPL?6hg@UlHK zV97+qvXfAscz?(!B=nXQr;@oZC19YuZS7JpZv z!l^2=jVKQVTRRLI!(|hatG$J)SRI5`?xho?t7Z`93`Xc%ekKG?$F9j(opISEjkhmS2Se25KRM@lM=HuND2Uq#+ZdlrVdclxC zM}+niv4bUtd<1hfzq0Ja?y5gBj+40X%D2u}J4}#Hwb1XdmfgXC9o2&;J8rV|3J3CA ztWTvsXrolT?eO828c zr5DrY>ps=*^OXyi-}{EG?q0bgM;)`%`v(}m6=%YAv7X0=Ta;>|zb(xAAf%vo?%EM{ zf5uC0LjL;kZm%3nV;Ojr;i%9hzUbDP1OnmreEnm%{Ci51ZEW2H0Z z9HUQ5O6a{>Cv35H*V=pMo*CxepKqRTW*x~QIP-`^*{j7Wb z#^n$qlb6`MJkxyNdA-5~6_xaRLO$f3-t4(x!d=LAvZn1=!nO>i*6v`xYu(igpIQq|zI(%lDQ;b`yTkX-UA5)HJJ7@dluI$w|VCz?0 z+0xQPdB%4)ZBw?ClT*oS4zjkrE%|HjUcww&&-NwA)??J`^(UCur)IaN|HPqA8sag*+J zH|Zh@gMJTFclV}%17Up^*ivQ;=4i|+XwN^@n!xMUL}9I)On>=(W7|4~>@$45H#~DI z<0_cbqWRjte9fF%NMX>u)X=tKrs$)J>>}yOs;eib)BCwGr5M>4(Dz4qU(&JOx#zxO zsBAy4^*eL_slA`N^t3YlC0FVVa7Ox_-K(8()j9UN<}JqHlkA-XGm1a%&09Y0?d4Bm zZ%%BNo@HovJdmE*Ix4%OZPg3)6+=RGCkMkYPWmF{ead^lu*H?}t(%hD8fr!KYYHm+ zHaz{ZfctQ-cQnH@jtssGqXLQ5%ippeZalv~{Nuj!?5%wJKECsr?ji|FODuI_Om{lB zcl{x)*#~PvTjnZ9GqR@z&tG}J9VV&i^r0N}4M{?SlCEdd15E9H?2#$^VE^@=zKExx z$l}V?ofe6i>Vj9dtl57_cB$;4>E&Nj$pQ6t7CD;30w47T}T3fB0 zG0Wp%#=e6b{ac^)3`pL5>$U9EG5WkG30{vPzg|4^Dd0lRq0RQOJe6`O%s%Vdzt5{{ zh;VFjlbmHZW$%FSDVR)72Pk$CpW+ws!(?mYDtN(p3q?>9%e#z=1A zX3lh{l29zfdD^m5D}7il&htoiDRq0atV{nX=OH&Rs-#M0I^TC)eynwiy&qTCy%qM2 z5_3iNewTiHG{yO}O4bus?L&GqPton`D41w9`I37#w%xX@ZCw?m9yM&xi4==BFx~+15zt7FLDe||PD24^+^{Oh)X|}nE zB_)>cnX}7slZ|xQlnSM93JkxxUA%{8Ta5er4Z9jrEva|JN+3?JvJRxq7>C@g%0OtMd9s-Ygc#Ely&utzTDi z^WKb!r}Zl*M)#sn^x&7o|6T)_leuG1>0j)NMvNtv6n- z;awy%U{=jhSMgmSb}^#`BjFR?s+Kj%&;?kb3;)D-ZufA)HUw0?>aC5^4 z&0^V5-!+_vo7&DYC!7@F(ouS=w@Yk zSa-d=Wl)XHZnY?mp7+BgTQQqg(&$PrC(N7O9g_qiJbbekC3QsP&dAUTaSyrM^Q3E5 z|HY?#Z`w0IDLvs>&-h$)k+fuGS?gKu!N%^0){OS2hudd_>q?>*cNQ4lJQMQJ;AQz2FBkA>gZCbgLpGqy+XiDm-RZInG z`M$s%A{G>UyG2Ty>$GEO9c^w*zqDv|!2rMKZh}ONRZ;WY#5D`*$_OPSL}0!HOx5H? zP*C8={HGn5=5_7L?AsVNN_c5#cMahT8};qMv6eu!qR9@i2D9)Z0YNudnN*SRi+j?! ztcVCMKP&hA%+^?~${c1vg*7khH*5r2l{Xb@s}~(~bI)&jt<*gia3yETWY#_xh{oJo zea3L;399zW!jAdLv{y0nLYtRl3J(?k7ID)WIlJgGk?`7-Prh7r-&borxRcz5+UCeq zUgRcgCHt$G<>`Ptye|WFelfKDgWqQ#b_?VXYUBH&a~)u7+aPfNW4#$n5i=**y?B5yC)`)@#z9rLCUDcr`q*(`N6X! z&rZ*W7voNNoUhcJlFDu#%C3?Xey+d(u)zDnj6_Wy53ziRGkWl-pBc&aBj@m|1c>+> zqs(nLtz~ue@DERMGu#C8vDt9QE9^Bj$eXl3Efv;TU8L^)b_09;OVb3Hy`e?0w0Zno zjU~7C>IaJXGi`n0G`+NL?PZ)F=E#NwoK;4y;m{hsERRt&?{KL3g2mX(`|`K4mwfjS zZuV6cC=j`m6j-gQI{h6bc!`QVm`IB4iU(_@dKqENymXEwP8r?EZ>A9*5$@Z7E>J*! ztVt^m%k&k};w~S!o;Z?AzTG}iH6b%Yt8#?L>5Jn2<#wpYuy)5oOYa<_7{t1MVE5TOM9qKa53ma~3F6NvGy8 zcO!j>wxD8{YAr>0BlXL{^34PDcU&->ssYsQ@wzM3_vnNdy%phKzIX)QDn@b{1XVcO37Shfei`&J${K7!>D6 z4SE6+braMqBN5WXFSLvF~M8j=0#G4H;(A~OkBs@TgHD>bs7P~ zMWYPQNDA17AwsS+O+!DYA04gE(h;^u?LnGkfH|)cBGDU`CdN)_KRg zCjr5cg@r%$26_!pKSwjy9sxxL90^l+_B?VYAC;MPrQvU|hqMA{!Q&c?yG} zWt5tNlM>B&!2*zfqjG&!BlX~W9?BmKpE*}qsO=j`VO^kR8qmLFc*pb@W)wlaHdJc6 z`OdjA`+Z)-X8b8d^+ItSDOMG>lj7NM>m#%RUdy|OuOLtsJ(U;N)(7J0f}RXdxfj}W zhv3*Rupi%9zNZ(7O?|pq+DKV15-3nTOE}igiQ&=Sk+#EJx$>~z!%Z&gE$dsl1~z-% zHU*apwfp$9wy}2XZ?L1?!vL4>w+ACrEc1$%1Zj#JTqoAgAi8qVCYH3(e*6#%e=%e| zdXC=JR=}Qm*3(|VR!mtJewb47!zS-@w&Y)pKjN?yTdQPb1+dJfRcpRiN6gg-+$& z!DubNdoP~8Cdi*nI7eW(1PzNAKPGaj5xMQD8Y1qMkNd5)OkULtLAL$f(UHs9bPU{_MRa7R8 zM<2s9QW&vQ&Q{>saAhE=b1Jk=;Eqp6=BxY5`-hA{^+W%&FLJpNVZC#_XYDd%v*1BZ zJ#&c4H!rd5Y3(GH5i@s~!QQ-cY{U!-3sk{yDx z?iKL92(V3>*czZ0bmH|&Gw(4~F?NES2Ew8j!F?)JL{-EuXU==`cl+?rxRISDH&EqY z2Suy{o4^wpUyY{nM9!g`u+P{+1p*kO!%%yjT z&&W_F^!R4#eEPkOXHQg1_sL-u$O9pK2b*n&s4N#?mc`V-wiwm)0{0bN{{j!ebZ%$Z z?!JWVq^HD42NPQ^;$E7X$hQj8)DU%5$&Djvm3HgZz}%`XC{ra!)!E^S+j{?wO_mnx z+u66JYMK$BX>h>t8ZWVMzVaybuDWV(H%62!`-RP*UCdMx%^C!>LZrd zB?ogE=HJljz#fZl#_S&TJ$FmhXK=<-60RPhaluW!2nRGvM8{=`O|o#ED9TWds>J{X zv!vU7`Se%A(DXTuFVfkbk@95+GmqVVRZc2*b6l%nkKpA%9bD=gLl4u(BBd~|5oi?h{lmg?zD;-%Eq&>$i8_dEq_eF(1E}xi5nSJ6Xht(dN_eg3D zu|TDYyt%l^APWvYmj=447*Q$?IyTPu(95Grze(yCY+z*IB*o#J7G%=2_`_%45=F{p zB%iAIXl!1#5)|=EMuA>QmT}8r2+M zu70y?avtl&RXRI|3>C?_zcW?s$b!l9Qh53(nT~}kJ0l#Al$O&2 zNny$v1L{i(S1e|oFT$QocmdmtuqvX6$5ad%J}fT?KJZX0Y3QE0t#|(UfE%!kVd_Yr z`FyA?uwAL^#xzl$Kkmw*E42rHY$)@X#2eQlBXAeURV`YK+rehb- zGo(~(uum&igbt0=wJuirBz*93*PwkhIKR&P1{okkd%=BfDDOjimPKNFaJov`-8xJu zJ}Jd1rt4T}uYj!wiU`fXH8{Mxc8L0nbczdoCgc$HZl{0ZiU6>yh@lU7n3 zb!SFQ5BHlM=DFKlN`{I;AHR3aEC=#7OTD<1~idPUxH>Kfv z^iqaRZW+uulrn#Q6p=~XH2K~>)#RyCJ<8?Na91HvylO? zN3jIswa{hCM6{o0v8S~2yOS4Sc0LySD!hjEofTJ~iaVw~sW^Xvwc4u0z<=7MbKHZ& z4rn-;x&YPh%DA8Xh2SQEyAr?*s|Jd7l>>$ja2H8IKXwJyhRb@av* zix~j~tC@NE$I7_%2icTw_c0HtE)@g^cd@%4c+PK#Pjey!hdlDyCKD^Pnkh?{<`*MQ z8QQ*iDES8YO-G0e3H#)KiN!G9&k*80V1Nrep(@D$nT`p;Z*XxYEnE5OL(=SieZCERek*$71~~+`ze4sh@2hQ+AYuo5_!*m-2CXH>0HjX zB?nvZfrq%hPLPIqUj-v!oyXsn1QVY!&s}yyiccI$33A`XULq6n`eVR_fi|Vo&AMVT7CbNN8awxt=K1qPEwf|$X%2wa zY{XpcsAEfPB|+CmeJ^#*xtG#=&6xu){b6^^?y2{(Exg4U=E8@C1Bg!prXBKO^3~AM zY=y9TMzk3SF!A}Ewl`>UjyAp337VEdTeK$I$Ps` zi+a}Vf%feIl|2V2<9D8Xs)c;F`Ea6FZ6b=eQ<)d6q)LNF{(Yq+{!Z9RUVP6$6>pOK zPOb;?=_xADnukt7bqlp1(M+56uI@l;&e~m2N@u#(*!bns!Y)KoBz5>|<9GtcYIi_r z&S2Wx2^3G8WR1gmv;1IX)+ewMKX}k#SnPxpj6pyRniNnejV5lc*UsACoEzbEWQ124 zDyfi%ZDM;~S=n|Vs&tS;b=J4@Zm$NDc0p~S!-VET)Z?pC=#$>laH#=RF5(VRb?YW58b8ZVbk7!Pkz4zTRzb=5(^=kiN5o4J&VThz$ znwJ+4Nr(YXCJ9&f&v!kYT@l9fbHV&fV2BfubVneY`WPm-QD=WAHJ@H4*|FA4gJY9Exf;fI1GgR(r8$R>ind+i98f(6K+!Z zD^}Gl&q&UsapD+Iz&@2^t(olrah8OmlxlY>7FY;yY2sLHPDH`>p+_)j>Q}j#%%nSv zC|9|F*op`fx^k#F1Ni`U1@+q77YA z9Bi%z)PZ@;JPpBD~wy9@LUBJVeM>R0zcn@qP^?rIubnp_8oHzg zC!XhT4p3reE2D*X?wc0h%;X`O(wIgZsijJtwPJu@|2DPn9wJE(#;RPRDFe!$POw%n zi1QM8+U%M-VKd)CW|ftb)5W)3YyuMK6QAutW0-^1bJuHuu6Yqc(Cr_ZL1HMKtM2@^q9%{&osVIr!~1$nPqFzRrjol9Xa z7sihWzt<4tL}Usb0lTg+dL`4he1hIeB3B1`R*h#IF?75{wg8xXnK;ptOOO-JoenRA zxkXV~D-9@e4mOXM=-WiBypeZJley88ht8Ts+nR1@53Fi)q5Ugh^|8K;aGfVWg3^5S z!{c4;r-8}0yx zCoeyf0@38y5^3(C&@zk^asNJ%tYZyElq0$1$`9Ap#1-LH>`5+PS;}Pq#|$sH3Ckj> zV-G-r+C#b=&nV5~ZwHd^;6OtK%uI%c2`A=0?BpMiA}qBLoXyk)j>I!ZQZdI|9`RR&-ya-=|rH z#L1!@z&fIlWVCZ`rd`MaXwczjS-zPh!SZo&&F%6yCQGCC4lK!lMh{UaQtF#7D|yc{@7PgOsSwUnD$8R{{c^Y(1zh2* zoUnHp&G}NGj8SKR(%8?4jv*SuGH|(|MlVSPi8@DQB0f`-qkU987yU+D`!b5VvwGRR z?qgsPtjO)D3=+HEpwGUlv-hn-;cZpl^DiW*;>aXT=p^%Y$QMG`Mq$Ty(d{zl&i{l6 zbC81GBwNA5E@2>Zi6;&8!BJU26~T)poXBKG>}OHn#|RMiXNyi6cYZwV>>8{iL0p-h zE^=*7?I;-DfA|vNp|PCu>A?6v_Hv=fCwcJ>rJ%kIpx{s>@SK_`4HhM_x7hp-+aILK zL=YLPE(t&bhu5HmKCA*vXXk(^E1GflxO<^xkJnP`sqrd*c#-3vO7AlZdb87aQWtHWxg95@p4%boRs>)?H zF2+aHua|qwKA{)z31iN=e4KNkO&Z>E4r_cgUc311yD3_QWBdG9-Z!TIKJ@N2crOJY zI%i>A2_Am&LCJrk`>WXkf*5 z7vX;6v|rYPadpw748fz_9p})~Fa|ah3*5(u37U<93mL$$d$7YFB063b$19Y$bw8ys zO}jf^UbH|R>sxYw*Pq#inDePQq!7;~GPJ+xw|gVMwcdzH($sulDhq2upcH(UmXo8^ zsJ#zhSntO>1b=uVR>m_x+RN28Ac(EEc~u>mPA{pRY4{aQxaKT ztT`IImaAJH#k<4q^dU{Rgm#rP*Tk&@zbQA{Gjv9g%>O_O|%# zbdv`T~sg#ANU>@jtZn}Hru7G3K*S@Dr#PkvOhE*Xax+5Z9k9pj+T>FcHLqGh&gSu zo#WY_YfF^Ljj{LEd94xdOiSvnJ1UmHjvieNm;3HZ@bEF*9`pcXpAs!fj3GrICVvWh zx;HF)CRl(0o-fbM@CkdFK1mDSFfENlZ}3M`8*iRiKPMG}x%z40*23O(QXqYC+u*7) z4DuYrBg6!2*is=32juyTnBfJy1vX9%pT+5GkQtq;PfVbewqYU`UfMcjJVTktqNVyo zA67UPsvfnQ)}aKz^v zdO@borv&)h8z|;D5G7!yX}#nQd&NxP1v4t_hPym`=ZdPYE}Okuie}9OUZ(W~zL3$uk)4vmvY|`Ma?r2y?PF8Y#%4z2l+Kz8ou)rXSu1+?H5e>yx z(lnNSP=Cfhq?(Oi4^13AZg|9HY?NMMyuXyW-O$~2OpZ6!{tY0ny<#MAg9b{gXKKGg zfn)+}0|J{1-XoIaXmH?+%o*tejvH`z`bOXJbr(Ms zvcs^?3#T=82`18m(USJgEF~O+dF9d~KSa6tNKp3k$h21*TzR{*5Lgvn9XXJ#frZxo z_#RwSyxfRx107T1NOa?-WWF-%3u!RV6-`}~3$X>m1XSYAu)!E@wI?iPAy*A2%J0o9 z2w8y?md}<9SO?nIv<-$2+xfUXO!-)qu@SH8)F8fYnbEVd!rQ&rm>la^K1QNw+a7 z8eBuG7NiF7L{D2HQg^aEWS-j&L?Vcv{MQb{%Xnz8)0OEQprk(oSdPrz;s6Td9gA#x zBXy--{l?COjcNjx`&bcz=O7EHx)>}HI&Xvc9airR=Nam1AOv9$C8vTe%Wd(hdfFSX zQiI}l^^LD8#=wwTd_F0Za4!YY%<)Eo8{zf<4^i5`HdiCYRHi4=zlfYNE0mYY0|Fd# z0V^{HF@c;0W0*gJ!0Lf+PI3-CQHyFOHM4N#n9Nu8SKNzDMmf1WkL2fs9k>lj%V&D; zb$Kk6e+u+82O}C-T|>71c;8ZtWJ}n4p>z|LV#fKeu6ITfDatg^+K9%wHt@~jPv7>2 z7ok(~BIG8Xsr+?31r07~@7$F7#-z?>vOBLtskco$>&5^Ndb!t@C-T^PM`!|2@sLf6 zChAkqq!ngTzU}zNhuK0rA&1<>RMii;ZU;k{;QDboqK(SZC9lG`n0fjb?$3!gCO)r( zd{TuLZe_!VG)_4plb)xNYVm>(dbI50yo#N*_f1zm$Jjxy^{yl5AwpL;LWL-lUU-Wl zS*fYZ5$&EtE`*k2F#nFuWLA;{qHVlhgcG4%txbE541Ci;c2<8hENP=?ZrBeQBGEyW z0xO_p>ISKm9yh;gO_Q$x4Hpj>YB5hCEwh++$FPMYKT;rD2P76ii3B_#v4t(iNRPff zQmcGqcA_c`2F))K15G#?=U20lj~_kFV4jdJ?AQ0O-^l(nUNg*AGA(CK2HAiVkf3uy z6^lb;Fr)OK6+tZzU`P8(!fKnxN4XiSu0l1%p1*6Xst=#}UPr^26_KFA+#M9dkf=|e zi%hy^Vee!mn5IDN;Zb|m<)g~(S_fhB*Yc++gx#&VS;5p*ae)sSGQXF(O8+GysTrNY zyxE;G{qFliGH2aUhdf)H_2}t%8NJN-jJVOKtp%++{iAN0=OT&PV>qR{6osnpkNxnE zcHo`+yEy;f_H-V{+%h*nU_DN-3_QSj1zzN<_k<8oaBKP;X>hFTJ$F4_a8HWD*!k2w z&+9Zgzd5*sI#&-pcte*SLxHB# z%9>xJgl=0Q);*AKQ2+n`yN)*MCcq7vwT9q*doj@ZY;ZtyZ;?C;w%dA9CsrJrqm zxVC5VSX{wdTy=G~|BqXy!hcByOO^n-*PvvuMkq~e-*!xl3*OFEd>gXZ)}?=1qF(Vp z)1^<4^=4j*xqv@fsTSX}Q~ct;7gDxBaY-XUG1P8TROXw;?cKSA*z1|7a(1XOK^Cr zG|be6+?S_)Yt<#eXb~~FtJHtKne$7ddObB#zc=`8OqYBB_^~xpB|R?gjpyr^X1k0fQa4j&u^Umu`mg9%nj|#TMV=G@SC=bieb`@r#7=k;FBp2N-Zhky{e1j`3JNmx! zg|je{wd`6`l+QZT_C$lK()xx7NKdxD7oaAE()+IBtnuQmc$aH77I;^2d%PRY66b~! zw{Ud9i#kC`2zVDa8|a3-q>O~TgoT8Rtfhps#W5LqE4-|X@vBge6|g$<^M{ z!s(wBV79zcNp&k_@EYF56-q5o7M2i02@B#KEF3Lu9ITav-QBE2<%LyMl(s70N`UxL zw;)u;!BxT1LRt8Vo12q@xVV$Mi=CLGi?z6=g*e_0Z;y9ya}}2mlMomF*RyVT7kk%# zTj2Yhe?58K)#hJMd3bn;c}RT+mPDZ>#Es6M(}i^09w%z!;Od5Ru)zO;|F06R-*3B$ zL8LlBR9ZQ@*yEtRiML4mQ?wA0?B9x27~&P@hPQTf@e~x_;@iOu;zidD=jQJE(*-?G zC;Zk=ON;NsD_FSTp;DHD5b+9b&^=}0Kkpbysh!l*5LS^yNy><#j)_Xj=t&$?kdaqF z9TSs4$;rt`OB*XeV%vtZ1^ffk(d9=q3YLFmfc$aA#uB2;#>xi&{gJD9PY*{I%kM-& zh3#+-*6xrZZ9Qv;b9FlpwJ7wc<%#cX{aKy;A6NhDbRScYkQI}Ykd`+*NS{!6!1w%bRP(W+!Dl)Ah1WrOU) zMD0h5V76Mo)$Bi|LjKn^{5#$cW&Lj}(;r$Qy4CWokOrN^TjAX8+yvFHL(22Ru&%pW z3Jd;0`&L!T!Z;@(>8E!7cCq4<)ZTSpH%pqJJ33R=@F` zEY~YGPOeA(i8hS+Khyy22abcRNKp_{4#+3CDC^){aITJaHkQz}KRu3=teAwDq@>*6 zu@8a#$147=ER>=3OIaKHE#Lb6`oEX<51;uHgZ`J`v>{$yAY&DT_;=I7 z*+XqF{&N~P-VyTgE}oEoa&eRV>xjXBAmYC-+5Zj=QvVBRkp5pl!%xRO{*ShW_;*(W z`8gPkDEKSWpF`J2HVq0E8KD4=|9jZ@^Pis-=0^|c`e%P82Dz4Bu~ao9p1p^P;~^~8 zpJ4zQ`t`45Mo6)@9O#eITbYXB`?c8(cgD8$_Q?)-lB&p&KXl=36e{2pBXS}pJF z?MPjSqqqQQJDxwweE;7IN^ks$1&9Lotr+32+W(TnTk~kxGE}GwqJ29EKhHLhKU~Q7 zbogH>ks@V(s)PWFplnOwZIoE@ZUgzj&Cm4w#MxgW!F}j4Xxk0I)_31FJObY~yi-40 zv&3Io{Hu(e%^KtWI&<`A#9Y+h1ODV5egz!2)bIKCfDLMY5BQU<{|ea7p!PQuju`ws z;7^A8E8zBHR)1!h#`f<4f3m_~0k@w`@iQR5?{>id`=p8=Sbu5V_I);f#!86$_gLF^ z-S`!6`$i5wsNc30MwvT*%2K4KIcJ%$99tZte{r14}=js!>z`qMKbu{T9 TXR;NAvVnZao!#u)`t^SR`zuQo literal 0 HcmV?d00001 diff --git a/tests/integration/test_design.py b/tests/integration/test_design.py index dcf93e9674..446ad46cc3 100644 --- a/tests/integration/test_design.py +++ b/tests/integration/test_design.py @@ -34,6 +34,7 @@ from ansys.geometry.core.connection import BackendType import ansys.geometry.core.connection.defaults as pygeom_defaults from ansys.geometry.core.designer import ( + Component, CurveType, DesignFileFormat, MidSurfaceOffsetType, @@ -3880,3 +3881,114 @@ def test_write_body_facets_on_save( missing = expected_files - namelist assert not missing + + +def test_updating_design_from_tracker(modeler: Modeler): + # Adding coverage for handling the tracker response when updating the design + design = modeler.open_file( + Path(FILES_DIR, "boxes_w_mat.scdocx") + ) # ,read_existing_design=True)) + # Creating the tracker response that modifies, deletes and creates bodies + tracker_response = { + "modified_bodies": [ + {"id": "body1", "name": "ModifiedBody1", "is_surface": True}, + {"id": "7", "name": "Fake_Mat", "is_surface": False}, + {"id": "10", "name": "Steel", "is_surface": False}, + ], + "deleted_bodies": [ + {"id": "11:1", "name": "DeletedBody2"}, + {"id": "7:515/7:518", "name": "DeletedBody2"}, + {"id": "test", "name": "SubComponentBody"}, + ], + "created_bodies": [ + { + "id": "body100", + "name": "ExistingBody", + "is_surface": False, + "parent_id": "Component1", + }, + ], + } + # Adding needed bodies and components that are modified + design.bodies.append( + MasterBody("body100", "ExistingBody", design._grpc_client, is_surface=False) + ) + design.components[2].components.append( + Component("SubComponent", design.components[2], design._grpc_client, preexisting_id="sub1") + ) + design.components[2].components[0].components.append( + Component( + "SubComponent2", + design.components[2].components[0], + design._grpc_client, + preexisting_id="sub2", + ) + ) + design.components[2].components[0].bodies.append( + MasterBody("test", "SubComponentBody", design._grpc_client, is_surface=True) + ) + # Changing the ids of the bodies to match those in the tracker response + design.components[1].bodies[0]._id = "7" + design.bodies[0]._id = "10" + result = design._update_from_tracker(tracker_response) + assert result is None + # Then we create particular body_into statements to hit lines not hit when calling the _update_from_tracker method + body_info = { + "id": "body1", + "name": "UpdatedSubComponentBody", + "is_surface": False, + "parent_id": "sub1", + } + design._find_and_update_body(body_info, design.components[2]) + top_component = Component("TopComponent", design, design._grpc_client, preexisting_id="top1") + design.components.append(top_component) + body_info = { + "id": "body1", + "name": "NewBody", + "is_surface": True, + "parent_id": "top1", + } + result = design._find_and_add_body(body_info, design.components) + + +def test_legacy_export_download( + modeler: Modeler, tmp_path_factory: pytest.TempPathFactory, use_grpc_client_old_backend: Modeler +): + # Test is meant to add test coverage for using an old backend to export and download + # Creating the directory and file to export + working_directory = tmp_path_factory.mktemp("test_import_export_reimport") + original_file = Path(FILES_DIR, "reactorWNS.scdocx") + reexported_file = Path(working_directory, "reexported.scdocx") + design = modeler.create_design("Assembly") + design.insert_file(original_file) + # The following lines export the file to scdocx and parasolid + design.download(reexported_file, format=DesignFileFormat.SCDOCX) + reexported_file = Path(working_directory, "reexported.x_t") + design.download(reexported_file, format=DesignFileFormat.PARASOLID_TEXT) + # This is testing out exporting out to a non-supported format + reexported_file = Path(working_directory, "reexported.stride") + with pytest.raises( + TypeError, match="memoryview: a bytes-like object is required, not 'NoneType'" + ): + design.download(reexported_file, format=DesignFileFormat.STRIDE) + + +def test_failure_for_export(modeler: Modeler, tmp_path_factory: pytest.TempPathFactory): + # # Creating the directory and file to export + working_directory = tmp_path_factory.mktemp("test_import_export_reimport") + original_file = Path(FILES_DIR, "reactorWNS.scdocx") + reexported_file = Path(working_directory, "reexported.scdocx") + design = modeler.create_design("Assembly") + design.insert_file(original_file) + # Giving the download an incorrect file extension in the file path for the chosen format + reexported_file = Path(working_directory, "reexported.x_t") + with pytest.raises( + GeometryExitedError, + match="Geometry service connection terminated: The method or operation is not implemented.", + ): + design.download(file_location=reexported_file, format=DesignFileFormat.STEP) + # Exporting to the invalid type to get an error + with pytest.raises( + TypeError, match="memoryview: a bytes-like object is required, not 'NoneType'" + ): + design.download(file_location=reexported_file, format=DesignFileFormat.INVALID) diff --git a/tests/integration/test_geometry_commands.py b/tests/integration/test_geometry_commands.py index 7e0660fc72..6251c9d6b5 100644 --- a/tests/integration/test_geometry_commands.py +++ b/tests/integration/test_geometry_commands.py @@ -25,6 +25,7 @@ from pint import Quantity import pytest +from ansys.geometry.core.designer.geometry_commands import * from ansys.geometry.core.designer.geometry_commands import ( DraftSide, ExtrudeType, @@ -1405,3 +1406,86 @@ def test_thicken_surface_body(modeler: Modeler): assert design.bodies[0].volume.m == pytest.approx( Quantity(0.4, UNITS.m**3).m, rel=1e-6, abs=1e-8 ) + + +def test_failures_to_extrude(modeler: Modeler): + """Add test that covers code for failing to extrude in different ways.""" + # First need to create surface to extrude from + sketch = Sketch() + p1 = Point2D([0, 0]) + p2 = Point2D([10, 0]) + p3 = Point2D([10, 5]) + p4 = Point2D([0, 5]) + sketch.segment(p1, p2) + sketch.segment(p2, p3) + sketch.segment(p3, p4) + sketch.segment(p4, p1) + design = modeler.create_design("SimpleFaceDesign") + surface = design.create_surface("SimpleFace", sketch) + grpc_client = modeler.client + geometry_commands = GeometryCommands(grpc_client, _internal_use=True) + + # Failing to extrude single face + geometry_commands.extrude_faces( + faces=surface.faces[0], + distance=10, + direction=UnitVector3D([1, 0, 0]), + extrude_type=ExtrudeType.ADD, + pull_symmetric=False, + ) + # Then adding a check to ensure no new faces were made + assert len(design.bodies[0].faces) == 1 + # For the rest of the failures, we need a 2nd surface so here is creating the circle + circle_sketch = Sketch() + circle_sketch.circle(Point2D([20, 20]), 5.0) + circle_surface = design.create_surface("CircleSurface", circle_sketch) + # The square surface needs to be rotate to make some of the extrustion not valid + surface.rotate(Point3D([0, 0, 0]), UnitVector3D([0, 1, 0]), np.pi / 2) + # Failing to extrude edge + geometry_commands.extrude_edges( + edges=circle_surface.edges[0], + distance=10, + from_face=surface.faces[0], + ) + assert len(design.bodies[0].faces) == 1 + assert len(design.bodies[1].faces) == 1 + # Failing to extrude edge up to + geometry_commands.extrude_edges_up_to( + circle_surface.edges[0], + surface.faces[0], + Point3D([0, 0, 0]), + UnitVector3D([1, 0, 0]), + ) + assert len(design.bodies[0].faces) == 1 + assert len(design.bodies[1].faces) == 1 + # Failing to revolve face + geometry_commands.revolve_faces( + selection=circle_surface.faces[0], + axis=Line([0, 0, 1], [0, 0, 1]), + angle=-np.pi * 3 / 2, + ) + assert len(design.bodies[0].faces) == 1 + assert len(design.bodies[1].faces) == 1 + # Failing to revolve face up to + modeler.geometry_commands.revolve_faces_up_to( + circle_surface.faces[0], + surface.faces[0], + Line([0.5, 0.5, 0], [0, 0, 1]), + UnitVector3D([1, 0, 0]), + ExtrudeType.FORCE_ADD, + ) + assert len(design.bodies[0].faces) == 1 + assert len(design.bodies[1].faces) == 1 + # Failing to revolve face by helix + modeler.geometry_commands.revolve_faces_by_helix( + circle_surface.faces[0], + Line([0.5, 0.5, 0], [0, 0, 1]), + UnitVector3D([1, 0, 0]), + 5, + 1, + np.pi / 4, + True, + True, + ) + assert len(design.bodies[0].faces) == 1 + assert len(design.bodies[1].faces) == 1 diff --git a/tests/test_primitives.py b/tests/test_primitives.py index 764a65cf94..26c92bc74e 100644 --- a/tests/test_primitives.py +++ b/tests/test_primitives.py @@ -1803,3 +1803,52 @@ def test_nurbs_surface_simple_evaluation(): assert isinstance(evaluation.vv_derivative, Vector3D) assert isinstance(evaluation.normal, UnitVector3D) assert isinstance(evaluation.surface, NURBSSurface) + + +def test_nurbs_surface_not_implemented(): + """Code coverage for methods not implemented for NURBS surfaces""" + # Creating the NURBS surface and parameters + matrix = Matrix44([[1, 0, 0, 5], [0, 1, 0, 3], [0, 0, 0.8, 2], [0, 0, 0, 1]]) + param = ParamUV(0.5, 0.5) + point = Point3D([1.0, 1.0, 1.0]) + degree_u = 2 + degree_v = 2 + knots_u = [0, 0, 0, 1, 1, 1] + knots_v = [0, 0, 0, 1, 1, 1] + control_points = [ + Point3D([0, 0, 0]), + Point3D([0, 1, 1]), + Point3D([0, 2, 0]), + Point3D([1, 0, 1]), + Point3D([1, 1, 2]), + Point3D([1, 2, 1]), + Point3D([2, 0, 0]), + Point3D([2, 1, 1]), + Point3D([2, 2, 0]), + ] + nurbs_surface = NURBSSurface.from_control_points( + degree_u=degree_u, + degree_v=degree_v, + knots_u=knots_u, + knots_v=knots_v, + control_points=control_points, + ) + # Code for the not implemented methods under NURBSSurface + with pytest.raises(NotImplementedError): + nurbs_surface.transformed_copy(matrix) + with pytest.raises(NotImplementedError): + nurbs_surface.contains_param(param) + with pytest.raises(NotImplementedError): + nurbs_surface.contains_point(point) + with pytest.raises(NotImplementedError): + nurbs_surface.project_point(point) + # Code for the not implemented methods under NURBSSurfaceEvaluation + evaluation = NURBSSurfaceEvaluation(nurbs_surface, param) + with pytest.raises(NotImplementedError): + evaluation.min_curvature() + with pytest.raises(NotImplementedError): + evaluation.min_curvature_direction() + with pytest.raises(NotImplementedError): + evaluation.max_curvature() + with pytest.raises(NotImplementedError): + evaluation.max_curvature_direction() From 3a722c37b23d34a76417e3b2ebbe67165f74c03d Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Thu, 25 Sep 2025 20:09:15 +0000 Subject: [PATCH 2/7] chore: adding changelog file 2260.test.md [dependabot-skip] --- doc/changelog.d/2260.test.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/changelog.d/2260.test.md diff --git a/doc/changelog.d/2260.test.md b/doc/changelog.d/2260.test.md new file mode 100644 index 0000000000..aaa4ff8af2 --- /dev/null +++ b/doc/changelog.d/2260.test.md @@ -0,0 +1 @@ +Adding test coverage for nurbs, design, and geometry commands From 5ce07a8cee3e1c35b248e16bcdca5507ff31f8d2 Mon Sep 17 00:00:00 2001 From: cord Date: Thu, 25 Sep 2025 14:14:18 -0600 Subject: [PATCH 3/7] fixing pre-commit issues --- tests/integration/test_design.py | 3 ++- tests/integration/test_geometry_commands.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/integration/test_design.py b/tests/integration/test_design.py index 446ad46cc3..8ce78ad68f 100644 --- a/tests/integration/test_design.py +++ b/tests/integration/test_design.py @@ -3932,7 +3932,8 @@ def test_updating_design_from_tracker(modeler: Modeler): design.bodies[0]._id = "10" result = design._update_from_tracker(tracker_response) assert result is None - # Then we create particular body_into statements to hit lines not hit when calling the _update_from_tracker method + # Then we create particular body_into statements to hit lines not hit when calling + # the _update_from_tracker method body_info = { "id": "body1", "name": "UpdatedSubComponentBody", diff --git a/tests/integration/test_geometry_commands.py b/tests/integration/test_geometry_commands.py index 6251c9d6b5..95d3a0d470 100644 --- a/tests/integration/test_geometry_commands.py +++ b/tests/integration/test_geometry_commands.py @@ -25,11 +25,11 @@ from pint import Quantity import pytest -from ansys.geometry.core.designer.geometry_commands import * from ansys.geometry.core.designer.geometry_commands import ( DraftSide, ExtrudeType, FillPatternType, + GeometryCommands, OffsetMode, ) from ansys.geometry.core.math import Plane, Point2D, Point3D, UnitVector3D From 22ea83b436bd9d007daf17e4adcde004492e5994 Mon Sep 17 00:00:00 2001 From: cord Date: Mon, 29 Sep 2025 10:03:17 -0600 Subject: [PATCH 4/7] adding assertion for 252 only and adding tests to incompatible list --- tests/_incompatible_tests.yml | 17 +++++++++++++++++ tests/integration/test_geometry_commands.py | 6 +++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/_incompatible_tests.yml b/tests/_incompatible_tests.yml index 0fc2becb98..1406179a91 100644 --- a/tests/_incompatible_tests.yml +++ b/tests/_incompatible_tests.yml @@ -58,6 +58,9 @@ backends: - tests/integration/test_spaceclaim_tutorial_examples.py::test_combine_example - tests/integration/test_spaceclaim_tutorial_examples.py::test_pull_example - tests/integration/test_spaceclaim_tutorial_examples.py::test_intersect_example + - tests/integration/test_design.py::test_legacy_export_download + - tests/integration/test_design.py::test_updating_design_from_tracker + - tests/integration/test_design.py::test_failure_for_export # Opening large files through streaming is only available from 25.2 onwards - tests/integration/test_design.py::test_modeler_open_files # Named selections elements are only consistent from 25.2 onwards @@ -83,6 +86,8 @@ backends: - tests/integration/test_design_import.py::test_design_import_solid_edge2025 - tests/integration/test_design_import.py::test_design_import_nx2412 - tests/integration/test_design_import.py::test_design_import_inventor2026 + - tests/integration/test_design.py::test_legacy_export_download + - tests/integration/test_design.py::test_failure_for_export # Bug fix included from 25.2 onwards - tests/integration/test_issues.py::test_issue_1192_temp_body_on_empty_intersect # Enhancements on tool results from 25.2 onwards @@ -168,6 +173,9 @@ backends: - tests/integration/test_spaceclaim_tutorial_examples.py::test_combine_example - tests/integration/test_spaceclaim_tutorial_examples.py::test_pull_example - tests/integration/test_spaceclaim_tutorial_examples.py::test_intersect_example + - tests/integration/test_design.py::test_legacy_export_download + - tests/integration/test_design.py::test_updating_design_from_tracker + - tests/integration/test_design.py::test_failure_for_export # Opening large files through streaming is only available from 25.2 onwards - tests/integration/test_design.py::test_modeler_open_files # Named selections elements are only consistent from 25.2 onwards @@ -202,6 +210,8 @@ backends: - tests/integration/test_design_import.py::test_design_import_solid_edge2025 - tests/integration/test_design_import.py::test_design_import_nx2412 - tests/integration/test_design_import.py::test_design_import_inventor2026 + - tests/integration/test_design.py::test_legacy_export_download + - tests/integration/test_design.py::test_failure_for_export # Insert file naming convention changed in 26.1 - tests/integration/test_design_import.py::test_design_insert # Bug fix included from 25.2 onwards @@ -228,6 +238,9 @@ backends: - tests/integration/test_spaceclaim_tutorial_examples.py::test_combine_example - tests/integration/test_spaceclaim_tutorial_examples.py::test_pull_example - tests/integration/test_spaceclaim_tutorial_examples.py::test_intersect_example + - tests/integration/test_design.py::test_legacy_export_download + - tests/integration/test_design.py::test_updating_design_from_tracker + - tests/integration/test_design.py::test_failure_for_export # Opening large files through streaming is only available from 25.2 onwards - tests/integration/test_design.py::test_modeler_open_files # Named selections elements are only consistent from 25.2 onwards @@ -262,6 +275,8 @@ backends: - tests/integration/test_design_import.py::test_design_import_jt - tests/integration/test_design_import.py::test_design_import_solid_edge2025 - tests/integration/test_design_import.py::test_design_import_nx2412 + - tests/integration/test_design.py::test_legacy_export_download + - tests/integration/test_design.py::test_failure_for_export # Insert file naming convention changed in 26.1 - tests/integration/test_design_import.py::test_design_insert # Importing named selections from design was not available prior to 26.1 @@ -310,6 +325,8 @@ backends: - tests/integration/test_design_export.py::test_import_export_open_file_design[PARASOLID_TEXT-x_t-rci_std.x_t-2-1] - tests/integration/test_design_export.py::test_import_export_open_file_design[SCDOCX-scdocx-reactorWNS.scdocx-1-3] - tests/integration/test_design_import.py::test_design_insert_id_bug + - tests/integration/test_design.py::test_legacy_export_download + - tests/integration/test_design.py::test_failure_for_export # Insert file naming convention changed in 26.1 - tests/integration/test_design_import.py::test_design_insert # Importing named selections from design was not available prior to 26.1 diff --git a/tests/integration/test_geometry_commands.py b/tests/integration/test_geometry_commands.py index 95d3a0d470..28b1e90fc3 100644 --- a/tests/integration/test_geometry_commands.py +++ b/tests/integration/test_geometry_commands.py @@ -1488,4 +1488,8 @@ def test_failures_to_extrude(modeler: Modeler): True, ) assert len(design.bodies[0].faces) == 1 - assert len(design.bodies[1].faces) == 1 + # Only in 252 does the revolve not fail. This is reproducible in 252 SpaceClaim and latest + if modeler._grpc_client.backend_version == "25.2.0": + assert len(design.bodies[1].faces) == 4 + else: + assert len(design.bodies[1].faces) == 1 From aa671af375bc36493b7ecece243b0fee07f1d95b Mon Sep 17 00:00:00 2001 From: cord Date: Mon, 29 Sep 2025 12:04:34 -0600 Subject: [PATCH 5/7] removing unwanted characters --- tests/integration/test_geometry_commands.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/integration/test_geometry_commands.py b/tests/integration/test_geometry_commands.py index 68ef5b1bd9..27e4d5e292 100644 --- a/tests/integration/test_geometry_commands.py +++ b/tests/integration/test_geometry_commands.py @@ -1407,6 +1407,7 @@ def test_thicken_surface_body(modeler: Modeler): Quantity(0.4, UNITS.m**3).m, rel=1e-6, abs=1e-8 ) + def test_failures_to_extrude(modeler: Modeler): """Add test that covers code for failing to extrude in different ways.""" # First need to create surface to extrude from @@ -1492,7 +1493,8 @@ def test_failures_to_extrude(modeler: Modeler): assert len(design.bodies[1].faces) == 4 else: assert len(design.bodies[1].faces) == 1 -======= + + def test_offset_faces(modeler: Modeler): """Test offsetting faces.""" design = modeler.create_design("offset_faces") From cf7273958b7a10c1a7a87efc764cff08f27e5aff Mon Sep 17 00:00:00 2001 From: cord Date: Wed, 1 Oct 2025 12:55:51 -0600 Subject: [PATCH 6/7] adding assertions for the extrude and commenting out failing part of test --- tests/integration/test_geometry_commands.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tests/integration/test_geometry_commands.py b/tests/integration/test_geometry_commands.py index 27e4d5e292..6bfa49a9b3 100644 --- a/tests/integration/test_geometry_commands.py +++ b/tests/integration/test_geometry_commands.py @@ -1426,13 +1426,14 @@ def test_failures_to_extrude(modeler: Modeler): geometry_commands = GeometryCommands(grpc_client, _internal_use=True) # Failing to extrude single face - geometry_commands.extrude_faces( + results = geometry_commands.extrude_faces( faces=surface.faces[0], distance=10, direction=UnitVector3D([1, 0, 0]), extrude_type=ExtrudeType.ADD, pull_symmetric=False, ) + assert results == [] # Then adding a check to ensure no new faces were made assert len(design.bodies[0].faces) == 1 # For the rest of the failures, we need a 2nd surface so here is creating the circle @@ -1442,42 +1443,47 @@ def test_failures_to_extrude(modeler: Modeler): # The square surface needs to be rotate to make some of the extrustion not valid surface.rotate(Point3D([0, 0, 0]), UnitVector3D([0, 1, 0]), np.pi / 2) # Failing to extrude edge - geometry_commands.extrude_edges( + results = geometry_commands.extrude_edges( edges=circle_surface.edges[0], distance=10, from_face=surface.faces[0], ) + assert results == [] assert len(design.bodies[0].faces) == 1 assert len(design.bodies[1].faces) == 1 # Failing to extrude edge up to - geometry_commands.extrude_edges_up_to( + results = geometry_commands.extrude_edges_up_to( circle_surface.edges[0], surface.faces[0], Point3D([0, 0, 0]), UnitVector3D([1, 0, 0]), ) + assert results == [] assert len(design.bodies[0].faces) == 1 assert len(design.bodies[1].faces) == 1 # Failing to revolve face - geometry_commands.revolve_faces( + results = geometry_commands.revolve_faces( selection=circle_surface.faces[0], axis=Line([0, 0, 1], [0, 0, 1]), angle=-np.pi * 3 / 2, ) + assert results == [] assert len(design.bodies[0].faces) == 1 assert len(design.bodies[1].faces) == 1 # Failing to revolve face up to - modeler.geometry_commands.revolve_faces_up_to( + results = modeler.geometry_commands.revolve_faces_up_to( circle_surface.faces[0], surface.faces[0], Line([0.5, 0.5, 0], [0, 0, 1]), UnitVector3D([1, 0, 0]), ExtrudeType.FORCE_ADD, ) + assert results == [] assert len(design.bodies[0].faces) == 1 assert len(design.bodies[1].faces) == 1 # Failing to revolve face by helix - modeler.geometry_commands.revolve_faces_by_helix( + # Commenting out test due to it causing a segfault inside the container + """modeler.geometry_commands.revolve_faces_by_helix( circle_surface.faces[0], Line([0.5, 0.5, 0], [0, 0, 1]), UnitVector3D([1, 0, 0]), @@ -1492,7 +1498,7 @@ def test_failures_to_extrude(modeler: Modeler): if modeler._grpc_client.backend_version == "25.2.0": assert len(design.bodies[1].faces) == 4 else: - assert len(design.bodies[1].faces) == 1 + assert len(design.bodies[1].faces) == 1 """ def test_offset_faces(modeler: Modeler): From a3129954793f7e965cc2d07fd1338c8d5f02f5eb Mon Sep 17 00:00:00 2001 From: Roberto Pastor Muela <37798125+RobPasMue@users.noreply.github.com> Date: Wed, 8 Oct 2025 14:43:25 +0200 Subject: [PATCH 7/7] Update test_geometry_commands.py --- tests/integration/test_geometry_commands.py | 32 ++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/integration/test_geometry_commands.py b/tests/integration/test_geometry_commands.py index 6bfa49a9b3..d61b85d6c6 100644 --- a/tests/integration/test_geometry_commands.py +++ b/tests/integration/test_geometry_commands.py @@ -1483,22 +1483,22 @@ def test_failures_to_extrude(modeler: Modeler): assert len(design.bodies[1].faces) == 1 # Failing to revolve face by helix # Commenting out test due to it causing a segfault inside the container - """modeler.geometry_commands.revolve_faces_by_helix( - circle_surface.faces[0], - Line([0.5, 0.5, 0], [0, 0, 1]), - UnitVector3D([1, 0, 0]), - 5, - 1, - np.pi / 4, - True, - True, - ) - assert len(design.bodies[0].faces) == 1 - # Only in 252 does the revolve not fail. This is reproducible in 252 SpaceClaim and latest - if modeler._grpc_client.backend_version == "25.2.0": - assert len(design.bodies[1].faces) == 4 - else: - assert len(design.bodies[1].faces) == 1 """ + # modeler.geometry_commands.revolve_faces_by_helix( + # circle_surface.faces[0], + # Line([0.5, 0.5, 0], [0, 0, 1]), + # UnitVector3D([1, 0, 0]), + # 5, + # 1, + # np.pi / 4, + # True, + # True, + # ) + # assert len(design.bodies[0].faces) == 1 + # # Only in 252 does the revolve not fail. This is reproducible in 252 SpaceClaim and latest + # if modeler._grpc_client.backend_version == "25.2.0": + # assert len(design.bodies[1].faces) == 4 + # else: + # assert len(design.bodies[1].faces) == 1 def test_offset_faces(modeler: Modeler):