From c87bd44fd3082c412748ac742ee1e07b179f77de Mon Sep 17 00:00:00 2001 From: Hayden Date: Fri, 15 Jan 2021 08:46:18 -0900 Subject: [PATCH] mostly grabage --- .dockerignore | 1 - .vscode/settings.json | 6 +- frontend/package-lock.json | 160 ++++++++++++------------ mealie/data/db/mealie.sqlite | Bin 245760 -> 90112 bytes mealie/db/db_base.py | 19 ++- mealie/db/db_recipes.py | 12 +- mealie/db/sql/meal_models.py | 8 ++ mealie/db/sql/recipe_models.py | 112 +++++++++++------ mealie/services/migrations/chowdown.py | 2 +- mealie/services/migrations/nextcloud.py | 5 +- 10 files changed, 196 insertions(+), 129 deletions(-) diff --git a/.dockerignore b/.dockerignore index cc5da2130..b0f176b1d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,2 @@ */node_modules */dist -## \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index c98f474de..ac409863d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ { "python.formatting.provider": "black", - "python.pythonPath": ".venv/bin/python", + "python.pythonPath": ".venv/bin/python3.8", "python.linting.pylintEnabled": true, "python.linting.enabled": true, "python.autoComplete.extraPaths": ["mealie", "mealie/mealie"], @@ -10,7 +10,5 @@ "python.testing.nosetestsEnabled": false, "python.testing.pytestEnabled": true, "cSpell.enableFiletypes": ["!javascript", "!python"], - "python.testing.pytestArgs": [ - "mealie" - ] + "python.testing.pytestArgs": ["mealie"] } diff --git a/frontend/package-lock.json b/frontend/package-lock.json index d4d7573e2..bfe873610 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1738,16 +1738,6 @@ "integrity": "sha1-/q7SVZc9LndVW4PbwIhRpsY1IPo=", "dev": true }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "optional": true, - "requires": { - "color-convert": "^2.0.1" - } - }, "cacache": { "version": "13.0.1", "resolved": "https://registry.npm.taobao.org/cacache/download/cacache-13.0.1.tgz?cache=0&sync_timestamp=1594428402513&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcacache%2Fdownload%2Fcacache-13.0.1.tgz", @@ -1774,34 +1764,6 @@ "unique-filename": "^1.1.1" } }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "optional": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "optional": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "optional": true - }, "find-cache-dir": { "version": "3.3.1", "resolved": "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-3.3.1.tgz?cache=0&sync_timestamp=1583735626956&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffind-cache-dir%2Fdownload%2Ffind-cache-dir-3.3.1.tgz", @@ -1823,25 +1785,6 @@ "path-exists": "^4.0.0" } }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "optional": true - }, - "loader-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", - "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", - "dev": true, - "optional": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-5.0.0.tgz?cache=0&sync_timestamp=1597081764621&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flocate-path%2Fdownload%2Flocate-path-5.0.0.tgz", @@ -1906,16 +1849,6 @@ "minipass": "^3.1.1" } }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "optional": true, - "requires": { - "has-flag": "^4.0.0" - } - }, "terser-webpack-plugin": { "version": "2.3.8", "resolved": "https://registry.npm.taobao.org/terser-webpack-plugin/download/terser-webpack-plugin-2.3.8.tgz?cache=0&sync_timestamp=1603882075288&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fterser-webpack-plugin%2Fdownload%2Fterser-webpack-plugin-2.3.8.tgz", @@ -1932,18 +1865,6 @@ "terser": "^4.6.12", "webpack-sources": "^1.4.3" } - }, - "vue-loader-v16": { - "version": "npm:vue-loader@16.1.2", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.1.2.tgz", - "integrity": "sha512-8QTxh+Fd+HB6fiL52iEVLKqE9N1JSlMXLR92Ijm6g8PZrwIxckgpqjPDWRP5TWxdiPaHR+alUWsnu1ShQOwt+Q==", - "dev": true, - "optional": true, - "requires": { - "chalk": "^4.1.0", - "hash-sum": "^2.0.0", - "loader-utils": "^2.0.0" - } } } }, @@ -11207,6 +11128,87 @@ } } }, + "vue-loader-v16": { + "version": "npm:vue-loader@16.1.2", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.1.2.tgz", + "integrity": "sha512-8QTxh+Fd+HB6fiL52iEVLKqE9N1JSlMXLR92Ijm6g8PZrwIxckgpqjPDWRP5TWxdiPaHR+alUWsnu1ShQOwt+Q==", + "dev": true, + "optional": true, + "requires": { + "chalk": "^4.1.0", + "hash-sum": "^2.0.0", + "loader-utils": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "optional": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "optional": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "optional": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "optional": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "optional": true + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "optional": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "optional": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "vue-router": { "version": "3.4.9", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.4.9.tgz", diff --git a/mealie/data/db/mealie.sqlite b/mealie/data/db/mealie.sqlite index 77a38a3039a6480961d41c40a2c6a96cf6a7c265..9cc937f471ce62126ce00b293b1e5458de9a65e2 100644 GIT binary patch delta 514 zcmZo@;BPpi`3SEWCm%DrxU@85bMa(mKAp*5Im9RH^Oa0q!{^Nk4(rXj{FfCL aZ4g+bAb?D6+Q4G4nML4_JWLR%27~}sKbN!s literal 245760 zcmeFa3w&JHc^^0+-jBiP1w#}?;er%JjK~>q08k`E(KHA`6vc-~f)qtlGIM9<0=U9p z?(p6jf{-lB7bGorVobP<+JKy`8J$K43TgIH@E}3OxJa$j4 zr6u+e!-&OVr|{oX_%Ham7k{(`AMkHW&EL)bJQYjtdorH*v)I6vuf`Io#6OGwdH;Wp zf41)r<5u6fzAyD2@A)6QzuLXr^>baToj=?0we~-3`}Nk(p=tCJLEx=Jz<+k2b8y$L zmeosTGh48ht?Yv1EMBd+1+Vt+4^5w+nYu7zT$nm~YR0I2VvO{3+j--}nF}+=XU-dE zp1WY2xp?Z-UZbZQgBZ_Gou7VY>O4P|OxG%wuT~rL%d_WCoSr&=**H0K*%-0&Nq+bA zbLVGH96!VFM#4@>#ajcQ2TFETR&IF zr~~5Kr<(?(9^it#WYq!FDiSU8#?j}VJ2f+P=B=ZQtT>pwUNlFWer9I+q%jh_=foLf zWZzyRlLSP3`@YV>@$r_`6@iFrEvw~{N{PSI=d)%|sFY0zM^pee7EtlAAP zTQ};E>#ZSxnivj_SE$T$tyk|=Yqe_D>S3|-u9dfe&w8zOU)|SWt#u7HyVmOKYFGR= zt?(oFbPf&sBFOZFb&eyIgn|HtATRV{q3%%S(1KZ{4tOU?KC~ zRUTjdagScci8IG$UNCB(8qb|E*g|8yzqh}0aA2Ti^^gF9PxxP=4h*V&Q_|j$8geFY z|GvE#?- ziq`?A`u%2+S)Yb(7>bo1GphSuOglg?Ao^V;ln)L$bevpDqAWb+-*J^Z7ay&Rbs2wM!)SwL`x( zNN`c5f>|_1D&TZ_l6IHuoWETFQN5C@e|6UZrTRTVQ@gx6wySP(Y=u{icXtdPA8v`s zA@Z&jc>SA|vLm0bRtLVCss7#Lc61Kz-reHwtj;gEK&4gip>zE#gGZa5=wxTd;OX6W zoMr#8i;GS(Q%K@R#SKL+Nh5oxk&-CJ%6X!0@fN9mFvbHJ7ME&i!x}~*q zaND+)n^y!7`l0@(t#0vQ$NK#t#x+5ubttz(jd9tw3i&$Z+);MQW?>zNREzd?cpxY~ zmCsukCO~`FB)=SR>v9krcmCq}Q+02u!ywHdq}nQ{qH$}JzmsjaSNhgHnie^WPeo-!^`@3ua5qgy%# zr?)p-NHCSFnc%Nh2v=Pcu;To64}V2J5dsZ0uclv2t*KwAP_+y zg24L~0zF(%r(w>Mf>1c3+w5dsZ0uclv2t*JN2(;sOYvK?2 zcP8sZ0uclv2t*KwAn+cBKyn8rZ+r;9 zhI)Gv|28(#`>|N!w|c+W`&Z&lV!D4v{B!Za-j5|>iTe{DOT60u|MdO$zM;O`@$cws z>HBc+zmESx-}(N|ey{%@CVrs*2jdg*bBUjf|Ht^%zJJ{R9sU2Z?>FLq)PK0|hx&f# zJq(~|>JbDY2t*KwAP_+yff%Pl#_EvC$3K9zILY$|Kn z^F^!drIzjTLTbf)*-n|ZQ?Qe4nsrUvv+`(U7Cq_XnQq=LTDtk1RV-SCk)hVbOc#4K`7e%B+dQ!R7$bt~nS?3|S(Cgs|8_uED!K?Dy0V>XiaHwV%P${EL+Qids?rw1aI*$*SrF!29&@< z8asC3Lmz6*w7iTqC9CKFhHf$IT4sJg<^6EOSb3n|D}>GV3h4k+|#-%+(>89HTwzaqKz?9%h)3~HHTzdxdk8< zHakveVaFC+$5~3bwuilO`ZzdVQ%+sSv6(krj*iJ%UhhEbXiMH%E|&3MN+D?8>bb8q z*@9#kUJ0i{!J>P#H5Yuv9aZ37gPvBwa#z%Px(J|b1)#+@i}n)W5Wu2S&ySK_mIUn2O~8_mce2{C_RT&yW8{KM@2X2t*KwAP_+y zfsZ0uclv2t*KwAP_-7L!h&Dpqui)vj6`{Eb%81Xd(zi5QrcUK_G%a1c3+w5dvJ6$H9lwrtB=b4cn?R`&l${(oQXZ?u>Q0uclv2t*KwAP_+yfsZ0uclv2t*KwAP_+yfsZ0uclv2t*KwAP_;|{R#ob|407+@7LXp))he@fS)Hv!~o+^*rBmyysv~vge`h zzv%uq-CvCMA%Z{zfd~Q-1R@AT5QrcULE!EXFrI3Q9oUvNi}+tE>sn?$RkplxDl;~2 zWX(mpIKSf%S`0O8!S;)DrdNLC$+p<&kW;i$OLnnR#y^$0IlCA>k59J6VnfxB2kSo` zsQ>sx{m1?FA1CTRj@N%2tN)m(|G2OI<7nN-!Bksp&%nHES;drBGUpepa@jVnTk~7@ z;=$In4@y|K`QRQr8eH>;wXnS1kGI7R?{posvhsjz#q+F!hk;$EQua8kRW`E)%NtIj z;b60do}IV69V2bA{ljx+!JM-SsfEhYQpHP^3TD|datn5Dv1FOv_T6YR*su+EXvbsC zhEOwcZL>JIt1UJ(TrzW3s^qwfM$UC|i$=*Q-}fjU42BP6eGlwxi|rg_yA)PvE_%k2 zWtJbc907JkwiIeJ0%=-rg3=Y<(Hx%#$6?zx zJRMx$R|bCMA#DFnZ^`r)u*o^ob)CAseQ+z$W6g8b^TD>*VB_ZsrXRww9A2_LkN+=~Z0uP%C1_OLxJL%iXs}@;8D!f7ZLwV;k~)j7 zS%a7Z_v2xRn0zQR-+3SKbz9Lc6wK5z5YkP}xmGc^kSY_`HPP60FB%OsYZMZK2k*h2 z4FH=LT*p~Txwhw&%Z{A61b1`o6Pfh(ek^LhGYjR^b-QTIn=Y3Q$XRl%9*J|!4Ij(= zAL;|G8q7P(#WMa&Et#%eH1n3A??b%}pOs9vyz*dATP(RXhdGv3!mXAk1KoIXfBh3| z;f^lA03C3MxHVajM6&?wfmq^K6CaKr=>O;a zM-sh|_|GJM68eBo^nWt(BZ=?ozo-Al`@g6E%ZbIr3(yO6CLV=uU{~Ug68|yrZ2ZsT zzZd@+Gz0&8{HNkS691p#esZ0uclv2t*KwAP_+yfrhK5Zyl=p^km(q$+}Mm>pmT*`}9QJr~P%GCh9(o*L@nR`;@8sw6E^dXx*oD zSL;9vMfg-t>(&;Cxlohs?QR`x5xH|uqIIV{)!MJe`9$RMWPj^$OI4pW!UqObSG)P3 zs-=2NwF`7pyTYL#l^)bW?F_%$A#)J@(lEc2HyPD0hr%x(QD0Iav|aub?a#yE^KEM; z{!sX2Yp~!4`IVBc>*x5P@WH^EQ630KxxWSt?yCdny}|hRgu^6)ulmFOasDMTe;@x6 z?Lx0CME>mQY`vdA?5=**C4Y*Fp)(x0BOInZ{I0ELYOQrs+tSxM)E(k$6#xHCr6bYH zBM3wgh#(L_Ac8;yfd~Q-1R@AT5QrcUK_G&_y8?lByrnbo%Y4_N#9t=noEtuEtt zYV`$M4uvkpKS_c>sPt@!N^7Lj&+DiC;?mLgJq% z{&C{ViJwk<0oeh5H1XNQ-$;B<;;+J!e>L%O)s0=Fp9lgG1R@AT5QrcUK_G%a1c3+w z5dm~ep^df%k;Go0L;@2aG@N3&X{CbGp zw?2$t4-VkhU>}EQN&GsZ z0ucn>XAn5r(i7XJfAZEG>Qa<<&g?%pKDK}7zI_w>4@~WxJTSh0Vr=LBsiT>rM|Vz4 zPVPH8we#txC-xo8?3{Ue|M-59|6}*O&j1rGCxSo(fd~Q-1R@AT5QrcUK_G%a1c3+w z5d!OE)|6$T1VqE4g1 zu13(+Sh8=RsbydU!_4Om7e!0m>*%9~L#a&+mp0B8P&L(Xu3IijFy!sZlCgj~6w)i_ zIE#A?uWY+0G&yf9TZIB&m2=GUUZYYh+Xel8+cV69k++IvYp-EuQ6|<*qDyAEude~STGB7Y2$+9dEo@? zBI=-`ek-cTrXzSb09zFvtM~K*o&0P5wGE-u(Sil^P#EFuHLzo@UACPfwsQrgd9lw# z9~lb!?y#z|QLwL7>^wKiG*AY(mv_U_!F6 z5}X!+&zh6+=4Xwu;H(%Zs_Yr%1(P*abBiWkmbYCi#~tyEk@5mw&Z0Cp={SlgQ*C<- z;kIBuRD)tNZ5$(gP>uKMlh3)n`DG)As>O}=GyOqb_pOg~lK>CjLj7pK_U;5YUjc;@ zA_-!sXl4q9kmaPfiacY}4WJ13BcR9FR|mMVB>1C9V8OB$ap*jdxB{v#tFwlpzy&+k zi2gcrWfb4lBp_C|5-{q0b)hq+o$?tpHC*5x^!8 zgVfbtDduetOhT3$u1L6*pGPrjq6X@jFDrDzsc_3gI9~p&A{}5y%_V=_#uZ=en1+<0KV*2g=fGzO^F&%sOh;LI%}%)%okTg!nhhgK4ZaT7 ztd1{dB3D8>+T{;^?mqtPX7G=$~~hxjE#30}Ek$eDf#C-s0*B*f0awXd14) zgu6vo*TWrQSzyM3Bg50aY_8yBxlUz%AvnDAP614~I=Op|17H8-cTWaKByF4`Kjt`v z^tZwsAWtza`)&ML>_8GX&pT=^TAGvz0UOP^;G{_3$_}V0isUT<3QM4Ilu~j9Fne#I z%TzmFcH#u(7;NG^Bq;xXtAZNo9k~^2emx6 z=;phe*n*dxJ9pZKxZ*6ElnHsq6>)KhtVqO{TWtd^;J_cdc#(_eRRQ`8pxfYLJSCUp zoVhuR7t(xsBW>va-`(l+ z6d$vfN@$TMT~*k>f)h<)Yu<8kHs*n31#n}~&s(CQ{I+%rBIUB@b^F@tomc6Kr}CxKTj0t&(uz4wL#c0qj?A(=?Jp#6l7Op4*<1&+qdtC+O_gJkno`FFXYhFk|Rt#sGoxq;6iI> zQkKZNa`!2ew2MGmZ;5!At7M6Imz@f@45w1aLzVz(9;0YeB8o#};MHjd-ubtE=Arum zg3q*mruB{>I0X@ihcWBoG#bZh34x)G29D!iBQt(uaz}8L$~OQn;6m` zMYm*oNnj}0lV`x+AQIFZ3*8{6vH)h$a7rb|vq2t|u%&etYl$BeQhCqt6rl=R3S9(- zEZSOPEIXB)5JkQ@fDm8hI%R0b6zvNsDB(!-vdbV~fB}fK1A!E3LIWd1eyo8;-DZ)j zUB}tbv=nY8)q)Evn(eI zxJ{v%^x!nE5QSIWig9In!J3;bTP4rPEkODC(#S%&T=JeA9rec3=92je>^k7Gp-317 z{h!0zOWr7Ot8C{+!>*}Wy!UxrROc;dAFX1}N|*9;$>e)+&i;#WsJZ;Z{^1R&xsIs| zTG|Ezh6!sftYu>CScdg%xd0uEtF*8R)yvp6xmZ2OBrfb^^AJODJyNU^u`c~ijZ68z zv-N5$UV-fYSNnGL+}~m2WAqb2AcDX*4uMZ~KHM3byuEyTS=}uwsYQDUw@wQGK{;C# zQ;AqF8ymvbS-ma=vO^Jas@&WbR5LKjfH?=nmO<4OqqHV@T>S;BEJiG|xT19_5Fub| zhoQ%$-Vg#nP8sye(5%yN#Oqg?szM)_Mz$)^GgJMGYmLIeUSmHr?*{_SJ7^b#Z;FC< zw@?LB$6U01swxg~1?F|(SnwiVdO5dJ%q>9twK088R)Y{?hH}5)Qfn+#qCmo;l_N$3 zbZr)VH-Y}f?rk^;Zw$UM*!U#WD0N_-1T*M4D_Phmv|3wxXo;GRyc##XMD-+u;4x9u z0AV54i!;h0s(f(e3Nq1K1p+l~N;YJ1C{4tLtU5l2LURbO5W<16G7b<-Y@ae74Wpt$ zz<@w8aBcd{8F4D9zF3`{H7_^Jc^Fdbr=SmP=ou#K!8zrrgZ;Ol^e!-u1s2>88l0_6 zO0Q14A@OT*Nz!7rNu~~(-%`c>%8!e=VF{|PkrU;wfAaglS1jV7!(l=g$NFd*Z&hl7c1HQhvsYV@T!fGKg9#XBFTUWs zlC@hUH0U6qGK6*^5GqK@RIs6UhX899bI`y;Zs2>wXFUrlN^=?R7SK3awZL7GAcM6o z8*`O_DBF-=FNtMMIEcAHr?4aQg4S zLrvfN!7-z0fvlXV4BtGeV$58R#x)`^&Q7paabUiqpYaC|8aJOYfKWGg-rTtfgt`D{ zTOGId=FjXsTk&fNnd7U4gG`H)$YMBv39kh0jxIhI${jki61=J+R#6AW2HJTA)(E_1{S7Ex;H^2$A~cEe}y{`M|pO zO?vwqE8D4>wcnt>Bm}*+MvC(d!<|$V&a|_XMLaI723Y%ExCPO=0k11($ppQo8I&9s zfEWhh26hSFFhNw9v{++s5c~tPB%XMX5d&j`==^E9rr-*4!q>Ru!^+^OTqy`qA9q0xdS1VN3s`JhseON^l6nCkQ(;Fw^+Qp*T!P`j}Pd|DB#6}u#uWDhY2 zZ)+&Im7_XgsWrg?-a>8gGSvrsgb9QJ6q$V_q@hTij&}QlwA+;b`(uAA7WaF8zx$WF zezYsr`S;qt+V+QSEn9wK%QG!ETDtJ?TjJ-%eeJQ)*;&dza5^le0y-iA@=J`#;MpbP z3%5>VL|BqcYW#@>H@Sf(#Zin7UU=>3jG>@U#tQfo9yDQ#6~q0C4Wa}u9D365vPf>G zt$#WVw;q4SpV3!*4jeH;VK31gH$043&K$^%a&;t^OvM?9kY&QXmTFZ+VHTj)g9wNQ zAgOD-ri8>o9?pB|cXI4p3jR(ny;Q##QOB8(C)~UyQp$67VFh8o+Ql^M+)!$}4YXT5 zx0k+9Cst3?zej{O6GAiqk~PJ*R>HELkZ0-g^NEUXvtQaE%kvqlR;5!``QT>Y6 z(kOpGiPlHi0W{d}v=&R^O?M6`UX9;WAs zUC@LJTI!1|kOw^#m@n6%?B%lBOc+MRbc@Rkj=eP-0Y!+4ELEI<1esR+7)&~FeJ-3!UqhNP6noEO#@|GVtghV0q|m%*L=&! zvb7r;|9MAK6rh>t`j()|xKY-pjq|D+`)=R&D1dTn z>DFd|atYq^5;3jSs)tkpl+d~C&Ck~AV{3G-+9okA0hoeTqPGf%S)YC3Ib0h$5G`BD zQcI)tqtaXHQejg^hM{Ru!%A=wu`bm3Hpsk#gg(ecB_y@hU@SN;xIxDU5(^bgLYnM> zhpy4gt~iB7V+7-1TZ8FY1|6hUlE4np;Dw2Nz+^`7+6=sIeS9a8^3pB1SHMoSF%ubY zmZLPRlyoolT{^@dup`)fx1mJ98{Um69E#Jj)YUb^`c7A zbeqU46gUFX27nZg|C`uU>}#>a*AxFJ@i!CSpZIjbOq@@AII$-&l!*8LasRLN{~!H7 z7XQKcNBaJK-?hF&y-p-g}49b*i>6AcVH9eYRo80KB+oA`A0s2QIJhz!>99E$>fI{Fr%5{^G7hk z>?TIY=m=$<5-V50y+V(=BHdT#nf@<->BAT^kheF&4rPonZ7T_l1SME=X#A@ic=B*t zZ1QAdP4HRm-Zes3D0l$TDf>`0P-^BWbj>yHnt>#)T z4do{eVVJ4L!;B+tODo#f^qPFK`Mh~w;_Y%5Dw0&Yf@EeAT@N*W;e=*)Dn;@$7(_KY zbP!#hYup7^DdmyOm~_vP)RKV~R#dxB9YE)EjXMY2M5%z#Esi7^2x^tqXP-dtm1eye zv#vaxG1oINpg|DILQQ3bx_Oai8Fw7ugEzh(BOYlyB5+u#_QhLv8^f^HzRxF9vBs9wxLuFv3Ydu&^tdu;{Lb_n_-+v-eAS#sZT!E+atS zN-f!7qmILMU{QParXFvL9R?k4?1T!EDaIO*UG;{EB$^*?-kc^Ku-H$-K)MK(1k4`B zGYB6UL9a~nUgDrgJs*V}@Ft_X(SE#HdwPoo2uXJwuk6h{))qT{@s56<8*z$!Vi$%v zaJOOBXD>PUDEb|`W4|W(Ql@vJ=eaxf)JZn)ki6y04h%AX$3Zrg&g0lH#+$w4cz~vg zaBiNC;zn9!xQVsZa%&)dbv(_pAHqP-ZD?MQrByoWAYbWPI_kF#v?C;WYD1%Cg3*`Od=Jr|R)HrfJ{uiIwwzIGW2suNSZjA=vaZo_wj z8NPh56@PLq!DARBi)1{FEqE}K`MQ4#s|gCV2wrpy!W!{#nlt z_006_>i)IvFLdARzSO<1>sPxz-}Oe4#{x{kS?MK>s+rHlR#kRw(f7$xE*5j=$TmH@#bIXTXey-)?EghId^Pd-y zG&1H~DI)^~Gb03%M=8bStCL6P8q>|Egr<4QmptH-8z;C5&za{VL8Ie$ZhCyps)?`` zyh{WME&1!L{>mF6P?ai+nU_4_V{4rKn|`SlT;`SYEY8A`HGk5NVXVnbk0oayje9_Z zp8%^)y#AIZ7F_QLc!dhG2rIGap8UjHnpXhKdKblWuVJv6O)v86x4&D?Y|s%F2t*3N zx&cMXv5#ZOJ;9SrAXeRNfB996a&gn6G?%(?Luje#(kmGH+@^;fqkaZr3PZn;(jWYY z5)UEi>VZG9f`NB#df=M7ymEu5rgzgr92CJl<-lQ(a(fCgUmzu^1C7;>=+iO2~MLphTCMgfqs=@XJurJNB4$0(M_V>tvJGN@i4q zd#r+nN18O$a-UhD6CG7>$V(3KZ%-M0GI#D1%8Glvrt=<8O<?E>Ui7)-<^1 z5$6LqOFrHm1$5Zjtiy!d&<`!P#Zp@XHW9%_9^Ez-Haz$;o(-&hMvy*bXx(@06 zN=d1dqRY@N@64m&p0y31(ApfW+ZoBB(f+lK0)@5K73N`D&p)0;%gMDZCq%`rbu`9^ z5;u|~W}{IxCl=5K=oNB{k9`|jX4a0XmQPm&*LFn1d+};}Eak`7HQeXC0xRYk9$$FL ziU*$_kjHEVPQ}QPxgRZYFXm{b(nU$Uje6@m8fBVHd8V@I zBJ>t4^abk%)bY~`<`Se~_~roDFC%@bvz$fDee#jZ7-?wTNIa!-?q7HT&XfMV4I7YG z<_%;6hTwG>>WlYXfm>ph+EOTO7ppnO%%xX~>9R9AcBXReTIK0v^07;J^Jvq7p($3& z*z-KvO|EYz*Zv9UWf_MaI4TTXq`pO)W3)d@ou+!%1vG$CPb@yVfewWbPfDS?PHAX% z{WyUvAl&`Pc{G@;A14#wQk|RG(7E+PfnLHGrBBM9vuJRnekkZKaJR5(1!)sg-l%BG zhwHx?1v|QnF0F9H#5&NNQa)qD|T(-72pLVR+D}o&z(T$)0^mAC7OsefW=Lj zzF>Dk+$i_-$!9R&W@5x@7`{u#(RVXO$0xM)j0mbU9(4yT6u_Q&8UqLDy%Ed{)mmT? z;MG+PRC{vftuODyG4!3<1gziuQed7VZL5u!dS-gl3sP=Xif5>a#Cq{4Mw;Kmq%vxt zddZ0ty~Z3F5>Cqhy)FM|tbeiZPx~^xJG%d(^DjDI=vZivwSE*|M?dc&2;A&F)EP_N zY`NL8mg}j>%Y*<4Si3}2fLmLj@g{%6Q>3sj=ngN(<8Y@@oMce;M|e?1<-o|Q%&F8T ztK?axswP11BuJeIkUL3Ah|AYn0aqce#Y?=>gf1B@q^K}kJc1OFQmvFfT5b0A_t?yD z?tGHFvGwLUfn>U-AQW7!a9^khLk0{0BukJDuvSUg2j^!-H82XnLlgzo_t4to{+7a& zL7*EqNSI>=JmAU^{!Mlb^q$|T3omUvZ6d&Ip1Hw8Rb9#zr2AM9Z?5)-mly5 z3fo@Vcm@e@ap0CAEW)WC78f}(Wmaraew+edwR_}WjgcbL4MWX=EI2B=O}#swLY5$+ zBK;njroVI$aQ1V4t`VFCWMN^kszfSOLHV<*RC%oRhE0+Bs6gSoHD54c>k$++p-w`c zkuYEs!kj#idTfju6WmI+X)AEJP8pS?Sr!Vymv2Ch$X5$D(>bolY>s zQd#!x7~|$^Pmn%&H@!wXQYU;=^SqJJi;OS+q$V~1)ID%KC9A1}PNl?vuC6!&7bK^` z(lUDbsM5&=kWOj2S{X#JxpKBd%MwgVd3DOrJRb17hwLq&(*F1%B^y!E>9t}w%$Yb$ zh(?g4D?GQl6G2Kki&>$7RZ=kH1GePVUHeJ-wykapKwV4uh?8}C7Zei_VY+%aRb)Vo z;t4xJ(T4=F#9u^~np~JVJb6TG8_Q6eAVP$WH(^;(?20&_hyJ_Y0@GOSo9K)k@L%&^ zYp8RPAOtuDWAb#Agax<@UI6smCj%A$3|r36FEkCT(0A^Gfj^z@VBS3w$xSDjX!pGoV&z2=GGn zE%67S?hFV9w2-)gSxx{{ToKT{O87LcpR^A2l`q+DuTGIbwU%n7-WhI?dJfGG9cHlQ za<5dQ+}?XrkN1Bu*3Mq8WlKAEtl~PrgzP!AgF52@f zf+poUR3R7?>!9rdXJMWFB8i*FG>$tCQ+}BhU^kTe&@QtI3eJ-2Kvzuj2)u20ec^6{ zlP{Ts5|p4kTtdHaJyn?Zy#!HHA4uGdLe;d=0of8@R3Hy1`ACG@gDVSYpfG3wq2q{E zs|OF8wA4CfgrbA*XB+XTNjD@Z>6c6MXK>CNJ{;ROmPzf)q%vbSM|*llZ=XC69~cF= zkLeT;C|iaFn0ZS84Iz37p%)Gerqvw!q~$e%RzVgl69vc#y#*xKk_5tY=F2cR$(JS2 zCy5Q8UcTBd23P_J1wZltVLUPg{LEKI_NC5xiW5P4j|^6>ifkQ!L@6118!_9MuBw9aS~ z?Ap2q)g4>C-rbwLwU~(yB(Y=DVpuSyRZx4dT|td_h4&P_J#(2VsAqAdSjKa#a_0g} z7oKNS=tF$4~p*d^rckaU_-k56CP7(t{! zG*H)d!5Y>|#|@<;B}icBRKZRj$%zKeM$8l;DJcxyOoZ8L zsZ^AWZ8Rd)o%c4a@J`^OU;qH*Z;>nN{4%Ap8g#&^jtZNmdGXq-U zWJx=mBGesJ4D;HoVuUN>BWfYrxaDSm*m#81L`U!8RdXgja9HRCq*E|<#!;2WJb>7% zyF=Q6>x*iGz|{lSpH_e>_I*~axTB0`2MGmbrb-o;?SfDW&{1Rvz}MnOt`xeMm!h$f zxYc7iak0!%?qh*AoKaA7C?l|29`Ln*l=w%HoX^|+q_KOxf)nGZ`xZE}`?Y5ACe`Ds zR=74(dkD#~+Yhz(9e-o@bB70x54ZTe$8-hJS(Xw;mPcJm*f`5l!n1PqB7_$=v|N9< zDkLpA+_xk%iqw>lld2N#a>5eh&q=2b*GbCACk=IhdnDD>{d3B|rtK7vV!qSPls{SN)4Og5bH^m!)3M$Py z@Rd@*i8<1p`a#TKDY_|X(g@4Xhzg7f3w1H7_%U2Qc`zu@AQvjsdM$BFVFv-XgtLWJ zs#NYQ!Xv<&D*zQ)dq?I7`IiX-30$Ey%p;^D@+DSMcVZQfCyk3#C9JFTDpz|@=r!;M zhL?2uj*%+FpVNZ8a2F60GynxpLi&}E^4+m>6}ejPPVDYDl7F_XH@P~bulF+`OP49u zNxaK6l#C=j)HE@_G42Q!9A#9v)VKq_aGO!q&PEDCFdvBXT3{=*K*CYlxa3k4$_M2! zxM~;ISEhspfSol<>H2V-;N;bRTLsDLiPpYL ze(vhK_Av{A6JS)$$gT<+CuLh1UaY%qX#;5Cg7p zLh_!F`5-=Qs9Okx4cvhn8W7^#@4VMUy0K?(cV|PKiBnW`(L#E zM%$CEqg&?i_51s0b?!rbS61V>;ejhSltY?vQv9kqoSKm(mxQOd8lSTZa%!QvErLOy zMFDA8EE^IstRYT?SzAhh=Pgpk<<)Jc9J7SxX!WjQy~sMaIFG2dgsTBga*%jQZE(yX zw8FCme+chRz5^^5F1j=tlD|^{4m$KfWzokp>A;TQS*ixt^Q{}}7$V08&g%x};y*pm zoAJHL_&^5y*Rxnz$%1G4GycDVA(UdFco3;lLy1h6q!YphkZ)BM zCH5tU!V3VG0q+Fv94P2+T%bkDtR&)0n38^3Pa+k*FgP*mpM($@TkU$FZ)kO3cXD6| z7}H7i2$p&a#86nHEW}5rh-ChOK&O1Iv7d-)Hs|Ijx{=cWdq<8>_F3daQGwf5O2lw7 zhLBKc8>^0k8pk3+i_{Nq&79=E#X^HZ=4lz2li@2{9RTC>Jpa-Ad-wQLzGo(0eKpXLm;1u!WJqe))(X6 z;AUc;McjkXOyF7p*IQMuD^F=H(ehr0O;j|vaEMR%+iGqMx;4~)aE;T}4V(3JO7?sTp_vrg z^-j&h`&W20s+k2%ajvl#NW!vbtl9wHRTc~mQ@D`8dEQGSq)E>yWmV@CU}NK_)%CUA zeG?lGaclRzy_0Wj7r;P=Vpa+^Lf)X@!5-#vD3yl*#Y;g64M^uw{vB%;q{U|}r)*rA za*@dsQTi+OibtG4sIV+>)~F6o85b%;KzDQw>HbpUpFRqau?T@(Wpg#ANJ^9g z&m~$dZbXrMF{CMb4%j}2?*Twsf|Xi?dw^*{{sdoES;}GoXhac2G2}`)hLwSYSl1ni zZXKaB6F!4hKx&{t4w9FRp7?^};pIvM;C^SZ6f*5LvI{Cb5I7&cgYHv-gs4-iyW(dI z;OLjLKZnM$Pn0l&6p&z|nwMkhh`x0iqMD2rTgYqV2zO z0b#Fe&n~}`LtExwqlgI@E$547W^!^OGnqu0^zcAX%EZpdxzJhmdD9N{$iW$0Of zN$d>q8iXBx(Q!HyzU;vj= zwFm&Q*FmTXm?+*WI2h3Lg4e83SPM?T<$^v2LanRXIZ{4s0B`}%m<@=UzLEoF1pp2% zR)?pk1chjo!jer|6rg(&8;*`g3)WftU3Gb@$Kt(*Z=TdTw=>n)GG={ZXqq@Ti3kG$ z-hxSp+D0H89mQ4cRSMlFfWDvs)TKZI-ngeYQ#Vq?q zFuso9))8$AUxNr*AdWMagaNK`#9aWoX3wi&y!B#VZ|c)~_QwZOz>+{&fWlG|+ou1a zn4mAEGLAq%1@s*O^2n1Us6w3*0SXkbJ%UmQ1rmu+1Q`)^9(utB#}+iLt>ADAE@{Go zH=%MTQA8Vk@bOBmNu>&Gs=8mMu|?b@Ah?9OZf{hS=UVkSDi$vw)mld+@CdvLL(IH# zffF(^`!XP2dCRH3N@j`|1iJLKBViG0jwXy)igu`6Q$a&S!$6QD>IhE&3 zGNINAjBz0kIf3UgU{Gl5IYE08i(V)rq5(}8*i9=x9K1L10fvZaw~NXUt*w+D%`zjmw|~ zPQXEyRqO^FuO)LPnE83`k1n3285vkvprQnUg$|ciDsYohw~}t%s*bsJ12x#-sx8i| zSZ-! zI`9z`m`+VBxFm@Z@HH3;Ci4KBE6E(xiPsTqwfWVRh8j91$*-z$V95ck0Fj0e=^=ER zR13Gego4(WOBZ2dEh+{02F6=r3P5~d-3t&*VJI+6@#P^U!sWm^%DfA7QN$-uMdo1O z;ae@)ijraEH`O@u?g0IWt99Pa5kTK&fcoWUfZYBG9|5pRWZQ6hi?gmpIzz%E8ny8Q z```RY?4_Vku!Epj0f`V@9CuV_wFdj3h?a2F^uJ-jFd)8o_P(>Df9!aB?7+Em4Y_Y& z50zNLNx`j3t7Ah4%e%LD=4p(7=upG)r=dI$$wXI)rse{IPLr=!KQTi$RA&`}S%YL2 zC$#%Rji?050ACuB^T<8Oc?>hy3(p{0Lpb_?O(lU*2Uj=>rB@r#c|0ZZKt&ZG=|pkS z(*l<%88pCwC{KBnL_>c7lf+j`&I0}c4iHSYt{Q=|&F{Gh`!5~qjP3F-`Il;CnDYW! z70)KiRIzNbubF)*RVxef<(kkoYM^ie#OV}&BjQI{bIb6!!8Sm>D7+<(5L8;IdBXjB zhhMUKU>fUN&8%i>*C$TJ6e?xDp_oTp)s|xDuW(pL zhY#0+ZC2`5g6K&EWHmuvv+s{gVTePAYKOQ)xrrzxYt2J72YZB*Z}Ro>N7`eD=jWTr zh~jFmcmU`-Fe_jgcMW1HsIPbwz#$YQ0DkMqO*Qrxk95Wkvqny{cgv;Dw}Q^lLavCt zw8p_Wg=x?oQHLwaB?57UHwuMIV|+iN0l={Yr8l5Whf4`)PQVDMv=WLfeaGM8Cq4`~ zzy5l&wN7d7p8KX&sMs)uOVaray4Dpcr{p@+2Z$P%^jq%u>S0W1ak1Hij`C*aY^dgv z5T_tX4k~=A^g4=zl;j-gO*X%|_!Q&9%$w#~sWB`cMB$y}K>69LO9;~m+6yQI%gH^^ zLto1z-)VT_ftpq0=<&~z8Z#_@H+dmw!XY7kvg0S zL?^VT%PDj`Flf-POS14N0MQReM?Tl)eO4vAxPtfnN-6($#ZJWf{;228?*G>LtLj|wfGn5Y5+91K=!(5k^h`NqKR8W0}%(ZSEXh(i?Q z2~l{#dBAfLW!i(XKOO?E-s20nIe(5jbm``$8UWUqgM>+yW6Ol^a=5A|Q*nb}0E3(RFQd=Z1$42A& z!c%6KVPqWL%RxX$GS-C^O2|AE)U@xbJCT302(>C92BkgNE*DYjV9?+1i@e!=mc@=& zR#zJD^d)g+Arxw!D}5x6f>3EboQH%T97K`rs>ieJ0Jd}<6AxepA&7GYebva*VGz3e zV=(33f=ddvD$z#JRzw>vROu|EDElIw5H#w6T89R79c@=dqW9*kZ&jYdUfi;7F>I!R z5%vuH;0bez2f`|nRbI0-I4~+dr!Y>WU+VPe5DKUj;jhh;0=HKjF#0o!YyyD7Ar}SS zabmbNG@r401|e-4J8C9`3Bcg7gCrE^1CPbKUXEf*lcjFq2|Uaa36@?6W&S^mNcrPv-N5Tg%Bk0w@pW|f-A%ZVRdWx z4Ds&XTldy%a}Bkh6^ujjFCpecI=NkC^E9!CY7jLa#IdFJYuv^-rP5khUeNHmt2fZ7 zycN;_mktUOv``j+iJTVgye1q0K)>~!On#0eh9zW4KuEJhf&kvqm`99dtckL;D0eVs zLgWb%oDz@wYSiWj76Sg!(^L=+`h%NR5GplUpb3=Qf$kWg8clIwIwdpp22y2RTpDX? zB+^(*6*@H{vTYKjvbjNSrB7iIw_0ztZh8?lH;SGEgc@QB@Qzd#CYt&c?5&Yif(*sA z`gw(WRjw&0>4HP6#6#s&FWOQNaTrADgFw}&>4D`E)~P1qU-U18tQIH zAZXJ=9A^cT816ngoxe_UCr1|6LiE6^6z>&=|3Jc_H>=z;AGD=^s^=taK38vF-8908 zVq+0DePB9n%0jhLH(3}Fb{SOyxuyOvkWRu84B{|IRY7kWts!uP6~_}%ArM7)&As{A z*&2MPA_16Ym0?@OJFHR1W8~24NGhm=q8hspBUXS3qKzR^$qdjneiQ-vT>>=a|Ebttk0s9Zf1&?se=7bL@t=#o9=`xzfM4nR;lAsA2l`rjf3f!m zdkejXdV72RUeBeT1Tz0GcOUBd^{(q(W1WBA`T5S}&I_HH&i0O9?fAPLuXSARc%c11 zwEs-||J?4iA8WtA?a$hNrR}e`W!uKuI$M9E^^2|F+4|AeH0uBT;+BOi54QYli`Q}> z_U|zT^>fNc62>dfX@tC+lRIprQsao>R1Fi6Uht8K@ygW=4yQBg!zCPkoXpE2>0Zg* zu(DQR<;~CP7ft%e%6KKY!C}YLBugf8N-vrx{3-N3vBAFMT7(K~YJuS)d!)=b&-)+2 zSh)?373Ala%+o2wF6f-&JL&FKbkJ~MSSB;hqF*Pv92_b1T)aoD08Jz#5zpFu8oRlo`ZwD5GKojOainhDgjEmK=t+rhFI~z7p>K7OB zV%`CN2WlZ6ZycF1WlXSA>)I$2cLV_APssTEC>K!rH?n~KhhqX^mjHMB*f3~{17*>nwpbTvJqSlr9Glg@L)v6N+sdDj5uMHPfTEN z+276=bvJ%dFk9isl{1#%(IJ>gI9a>~J`vi<7cWt*gj`FbNgoyWCQmjVT9a9Aj#G8M za!~ZCveo&6KI-gEo@m^6T*qE3^B!Y^YlD$L>OaIK^)~LC2~K3A!`i$oX)v!De=FwI z1iRMki>gqoSeu%i5x8IRALJzCO(q#IA|pKUf@$75Dg;@3&B{aQ&H96wK^++6Cj5Rhood`P&@fB= z4yd0&reL{)?m0Q)$D6-Fv2}r2>5PwhaFdnBZ)j$q3X9Ltpd^WZ9z!@Qs%I2e@b2E` z?`BnzDnt3S--D)2Oap9+D!5Q)))-={FGdiAi!jkF*o%B})JJu?$peiSkug>faf*~9 zwdGm%`CaHS*`x=GMZiZD-aAT>AqhdeQNQy}FHyEwTJu6f$63FlE#^#bTG4_Kky;s| z);RA!=(o2+Yq|N7SkE9u0+bS}FjBo@FJL02;v}d(gaRaF2(I#28JfR&h52LFE}jv`K$>X64Q6R3JLFpn=eJu`tKF@3u%Z2K3FFUDUd5!@fuem zqVl82j2_$p4_%aO*}V8@naPVVE_^2WnPg)Mp!`JX zS|Pq56$UtneiulHzc2w;DKe>yI>b;0p$*{2v}@2Qs6~zOI(Ia!)&x72TVNO<7_)Fx ztx=;(veH7qO05_eVOe0vz|M(#qy*w}Qh1k&j(+pYWVS4D^=V@yNFasC3xs2;23bV+ zlcka45^S5?udyppH|WaO+;6ASGH zD<#8;9ytIemOc%QaG^%Ot=^1Tfcb+inZYQFnD%)%YlxZl%`ffXMk18nII9vK0LD}v zBC1+#!rIp=23F=S`JuJ5I(8qMO6fzTTNCF)+H}Cwajo1S910gHOahomns4oKrQ_I? z1{F3T91`pttVnghs&Ng0F9~tu5XDEVrK)x0?om&UoW#K*^@|8@Is90nawD=CV0hjt z@k$f5eO2jSjrCT&)6r>&PQ${wL-;{G4R7Qw;O=;1_Kn%bcgHm2e^qi19=j|~7<5o@ zA!4#5y0zmXWRQE_t}La*^~fusnk@okc^0d3VXdu>V*gs(Tu_=w$?S4(D)o`LKB$CV zB*;wi2G`mm-odvh=OQgJk}NcWOztTTaBvi zfsz{)!Ms{nmj1Fh)ymTWKj&5AbXh%BnYdf^Xt)Kc??WXCTz9a*A|rLNOu8D>NVwBN z0dJ%L6^m3rE>VC}-IJGV0(FO=9rh6R_Hjth6?n#SA0bp@ju}YkE9q#9 z-}hVm?Ym}i%D;W!+Xot-a@e0e`iDE% za&^e>t^y!pBaB&yhz`5FC=s1B(-xrnf#dJpiOpIPvPMC&Rw<$;7jSx_ij-+oodPy^ zINvfAYDjx<4$HJXjmd)4|%-&>X}hsB|h4w-2*0oX}tpW+Di? zJgftcgu+$lvO!QF!HICl!igjOQfOTl_J8FaC1Vi|M>zam$6@jRZz;s$-`VqXJ*n=m zbXPjF?f(E@L_cpk1U~)DOP#TyPtSaMCbVBE60-K95QeGN!lOBFGn~F}{9y-6+ zIwqFRJ`jc}xCgm#MTv!>;X5GC+2A~xctG7skn?dLU$^HS=!KA&p3GX^tw6&m?}WgB zdI;C{9lD&hZ*Y2RE`q>IN}1?zp$A4~Wy+-!Ka6*Vn2qIaHFjipGF4zHCzp--d5m$V ziwss-apz112pzMT6ohZ(HKbp~eCf!Yfpjx+H|eO?f`i2f!wv()4hZmh^nV&QTEr)S zkDeFTfHCzz<{_#yrA!H`y5dEcMP>&wFygIR@e$4Q?+#Jlv{pSRttD0%}hOMV3%&1lv_dU8pZcS^=m~nS&${ z8bS`4wsMAJkz$JeSSa0`Yw|jRy5s=u1yz?!iRuNJll-)F{{%I|JpmG40v=#9Rc;64 zM3E{Hu=e6;T9ZYa`>XOue9+f_>Z9$kJu@?Fd`M=Qkb);eN5P;diQM0ewz<=@h07St zG}nxFnxW=lQ4k1c!~@(#68%b%8#gBuN#4TB##{OizR(%l<0t&YnwP=yDarKo`(zaX zOQI}0+M9S}g+XEDO6Ux;WW#{F4AWZj8y?{H%q8d>ZtuU{#2$YM)(b)axQ@)g%or$? zF}%3xZBSOWl)4KVNGpmf7>~;E!{GLyM20GaAn_$+E0|4D`%4F>tb~02I9fvJXnoNJ zBWlg&okE_D;0^tu0|N>VTCHgUTv6S;G<#EPM?n@nRNpXYb*tvzArprbfJno-lI}SM zt_jae|(i@OzFEMN(7`Fxr%WFDp}$0iEKESlrCuH zlyIyOzDl$#>fWH8O+8n+@Fc27744>FQR6Z22tLn61X6?PXzH7$`f@-kkAh=0{SiP4 zr8TY@7zx!?CS12Nu~7)fGZu`2YW1c(mGqzrl?YBv;6(YqFZNih|9|QIg`VH+{;%Dq zx<1?0*O~3u)p|De%XlC^e%kJY_jcTmgBNG8*4_N_X>Zp}v70LF4poo9gkYC}S4^b> zp9KnEVmdg)9HqEDz`&ptii>}P{cl}gz=UsIymfJd6RzPniMoN)J?VE9ivoYaFq{k5 zAjC^}o=QZ}TJ{(!%rL21E(i7qWuGJ^y3(eq&}atG1U#3z{h=ET?+7KNP6RA6qHW3L zAvrf$uM%|tdK5J!o(P@#t(uXGG4nY6I{JXY3~Qnr)FMN^15TSLUsNBIMv0-8E018* z1V*>d&jaypXKrUUhIVgDY(RKB1ck_ zN>Xd`*$0>>#fua}qDVfpL2C_}qIL-nGetmgc#zze@|KVZ2__9R^=B7i@&Z=aafZw!wr{-^eijy?M^G-EUt%Q>|~73r6XokgyG+u$`RjP_@ysw|kaZcO)?d#_>1&gC9dmz#zJS4?Af5gOm3CeUK%a_0wzQBvg^xHR*pEseI@=YIpFS?FRRYE))d?m1jWmROv{hO2#5r&M! z{)qlZvEIM~1R8$it9|$0^Xh^G++cCOlH;gKlz=P7{38I@1)aXF0ABs*$AHwUmsT%@ z=U47cGLlk(`R&!*sfC;Ji?hqofD#U}7IB^^%>>(~IR`6E(TImA};|sp9`X zA4_~b@pS)}`oFEeBmUFzzZPGLpNNn2{c+z{`aaY5Lf@|5KkNNU?|1cH?%mn*$H)Qj zde6!3h3={Dhr52R>)X3db@g}t)6UmB&vZW0@gF+A*m1q%nT}ZdFSReU?`ZqowlBBM zw~e&^N$clY&mrdj%Uhn`GO^|UmOp6ug_gh5@*OROmYJ5}*q_9HDfamdn%jp~+uLIM zx6L7nd(JAPRCS~je7cc=3>FE9!$YfW&00YJ?G>z*QQI&z*`up1XtS$P8w5MDHn0r!$Z8DDwl->}mhp)Hdb0*)6SjJLyZ;F^7;H3x zgxwAKui<$^-~_69|Kn(}z0nBZGXTb7`4RusX0wnLdqe&!&EBHNwfq%iF!i_Rp!>0` z)PjkMcQ6K~vMeJ88E#yHy7kjANVG~saV;QKq`fBcoT>|zhe51PD8P2iztI*u{8F>m z=pan>IEcX{N3td?^Mt>QVdk3+qr$~T##A_}0D5f*p^me~b$G_VjrML(I$nWVG6ijTm_Z*Lf|QR}$Pq*7+77|sakNFllywtpd94kgSq;x4f@ZaFs z%eFuSCL5d!D?j7sG0Yuy5xz_t*~LSC4&yZ47vyA+YPF#wc0CR}Gpqlw{k~5)>1^{6d`CG#`luPyfRgEuA8dN)sv&6EU1M_ z9siiev8iml7ujI<3NB8Z!c=GJg7fw&00@mDN)4N)*ua*l(Z0qpF3r`<>EQca~ zhcgEbPCiC7FQbgr;ql3Rllu>ZpQmO|oH<+_<}o;{ElxXm3uBEvRyOAkvsz_pY@a+h zkw5&x>GLmKIyb)mxo6KzfAsm|Gs$Gef3YpL^IXjW*TX`Eu!6uMwglSTvfRp?5uX4@KNiPAeqKdb zB!!&vi&X<_HM@RHEj(PA?q;*EHP_1orMimz1x|^j#-X662QD2;;Ijy+b-k8y7DaPu zkP@yp$hVG!+SQB|;`)VpUr>6B+ZUJ=7W!clTjeSMWrs4WK@AVHe1#boux2>VD4jWd z3osd6=gU&`VH}Fms&=7$!G>=i=Ks$>UDNv_?DtPGCs+X0s_z?7u50IYgpynTj{g#al9A0%s_18 zf#Qp$j2^SeA6!68I{t-zX+)ta!VrY1^x%lRiN>W@@g`K6slG|MK~r=S*@vh6Y>luO z*bdeDFw{|g zLR{G9d%OZ|?#|`qnztfBbwLqFuq((d=-P1HlvMrWVj-3+urT_ns_yEnC*M-1S8l9* zH+=&MSWKr3rdo_KB(-48m~=q6G{m(r8VqK1GQZ}c_m(=9mhtYTrP_5@vaot$sQ|Hh z6WD)cDDA7&;^3w6=EG=RoTc)pn{sfdu(E1_U=uN zRoWrIHJ9LOs$K>;)f#;Di84l6T52kw(b6hvG)DHZe$!r~UjA0GhM^q4+4e7bc>l@f zazDot0fFcNX#ujnx=xg;KDY-yBzGwr@{E<>;?1(?$4>WzDDgz?)Hwf4eK@>z; zTa56BNasNv)#|c1O~8q+TIWn7CC>%w-oNq+R9mv=lFUlS5LZ2k zYrXbs?3cp+!kM^L(kPZ-!k;d~u* zxW$3PuJ&{Ry3|+lP|%SvDJiJ?N|Gp|jvUVVEwRC=eQNaK$@`yQi4 z5a_Mk-kvs*GWh~nDky{@f-#r?G6@s$l^DK-fHo!Pkcm=8Dgn1j!3eiCzDBN3Fh}!H zf?!mgL{TBYbq5j}t_@MaGJ_!KImZ&Qih=NRm9!oPvrX|cV!q1@sjQxD3f4-_Hihw0 zbDVAZ<b$+VtIwTi93|>amouo=Ojq0eN5%# z6>HUZe6d(1mgM@6urXc{wTJH|Qh9j&_7=7pb+{JAJr-7~aUa;V5TR?uH zqp%1lHYS8xZn13I1!5?ydp3gTfR*YyK#=$(b7s(^2UmGntwu5Ayg_CHDU@Y<#jk(z z`&ic%JrJG=QJX!MX%0tgIA9`k1DxfLpnzUkO-5Nuh;$*G)N8AN$`C?#YhDG`-C=dN zv2H#*)O+~Wt26O|!^2%M@&CsOUwf{n0uN?fT{M9(EHV!>**t^?{9;XH;Dx3Iyxj`O zutqm53mLb^r{35%K03KotD4 z^1TC+vNz4?IoW2LbCOdhakj_VWRtXR+SA>$+1P0}J;}D&)9fEPO}DMnrfJ%<-t3;H z?dc!w=lgq}=gu8qW-yc~Tap1=5-@Y`bD#UX{GQ*-_xJr3olljWZ zPH_D2=Xy>@H=o<1>4~tW5nnUYXO94ab%6L%vlaA|+ejye__3#h*yzALPfdfz4EHyEG!Y|rU9_go(5$3a~VOfXKi z;^$-AXM*o$Y*ZWJ zEK7mgR$qOz=k)CXx5wh4%K#0o;CUHM>EN&6GC-D40QIKd;B19OurcP)Ft6=}JZg&( zL3_i%L0~uvEQ0SBAY9N?*W&!lNv_RL;%~K73_C?i1I6Rm;apc%=ZYV!7K3O<6d317U;7wc?=pCiO+)(_~Bi)a$ zKCr)c_v6SX=T-zva<#rT40c1Tq--o0u!+)p7@6Kmy^ZH zHPHy;=+>UjxxIEZ9ht+GSypl|eK5L+g=NfL40<+zcuypSP54oQHu1j(3733OozLjZ z!`=JhT?c!2@6+H3q%&rYLHm{Ns4gzceyAS;{G}G2zV@2u>>b1#|7)%<-hE`df_<_6S1cIQ@*~W|5c1o^$p^uAL>3+ z89v{;`wVYz)+1(2A4RrUwR9YTi|OS+znom*#WNHg72d5j*W5gB_PamqO|$q^*g zHr*6{d1Tg%cp96T=9DKA&H(QDYG=Q zB36J~JVfeRpRP5ENKFDbrCAO6{B(aq?^PJEh8LuU@6!)<=PHj5_wLRyeCOr+kw``} zV;$TIixSHag@_LsEBSEH#qh(Sk|LUjN|g#ZOM_w&EE0`+$F@@X-S^`SpGMe+h#K#4 zvnaZed4qxph6U$Q0ll z3YHF#d2@wz@RTqxf7|Ig=JSH_}kS`H(Xkw(h_0~MWFQ}I4at~gG) zB<(>FbIjUSS>@88l=Wzn7gVZ1W)W(`z9;hN*xQ@jO&{uJ6R>08U@DKj>PhLLb zL;GgYr=qP)YlNNM$eJKcdPFe6r?O*$E}QQQAAo5gF4P_fyGGr{rDj`pcpXU^xFR3@~Dhy(z~l|{VF)~U;vRcR!1ViF8MsYa)rfRD!G#dKC+(dj=f={mvU zp!%aS>qZ}}%&B$VXD+k(iIqC_>o><}?HIkc=UrCXd%ND-)o7*Zh}YIN(cw^tIn{}i z06t~rb~RbYg@>I}&Mh0;%UX@BvOsjDIZ_Ir9QJNLP1q;?Cg;SLBgmryy<0B9_F;}W zzACrgS&&sJvC#tud@D#3-$-iphx{Q02;5r?DFcD<6!tk@*q3l?X_0w1osm154r3j` z*jp0(k-flxaeqm`ajo4d^m7>^)P(&soM9f@snzMwB9630$D0|Oz=>*EyhNqpup8bc*&JfrO>re{E`Xo&1t9ysD|0=wW4QB=+wQh)-S+C% z-`Vp2Zt3TvpX?`kIqL1q3`e8UXuW^~O8#8d$5;T*QM^=n4hovto=fMH*sh<#(dgt! zTGPb$WLpprKsL$7{{WkgE=E0isZ-IZdM`B!7c%G{;~4O=%9$`ui&;x8V3(BD_kcT* z)ua48xx|fe24R(-{D7K`Mxt)L%uqB`?`6=?^7!s&p-@7J5Ql+^mrDTR2ou6d-q^qy z;NDiy2avQPcO-I(!n*Xs@A+A?x_Tc#lhFgw4!y*-Xj{FPKp9~$8}^bV=VNlbmc1lc z22L}*=}&NL)E9NBQ*eIO>lBHP)h^j`AD959Z#5`+xQ5Sz?=;$mL&A@b^RGBZET8D9 z8{qrY4A#f?_RR3|a=otN@nk(0vOWr`W8|C*jQYxyH3U{J%JF{gxl@Qb(N*q@-5G0S z;0Cr~bQu?N)o`Fp(!Hr=MI#a#!r2AO!M78ZL8?*)_Gf*OCk2BnxhhNaY>HOgpeJ;s zRhGphzNyi+EooKLgkw)vtF-mcCp2|`*=Rx%ih+?1WrvQCL@|^)`4fV~+U}V4!T>mb zfTqoOnSAipZ1FT5bcpH(^HOgzNwGGC7lVCy4}{R0Q}m&oqScY8L+0n<)x(W8+F6BU z-5$E%tJ%1fkZESyBG3?KTALR1(?M?MU$G1#MbS1-2VG~?AGj)1j|Gs$6ao?!be5f( zz|K4rfuJTYLdDt!TZCsNeCc3iwLiSzkf$m;P~Bvk1F~j7e))XV&LaBd;a_gZA>(`z z_gsR+%jd>L_<-Y*cuPE1E<%S`w;x$&@W$E@zZ4@`O+6fwg7Tn4Lw6NnDX z!&nL7Fgx48Ic8k@VYDLHt{9Vh%p42|KCL>R9o}18RutkH^B46Kmu7?jSjj`^3Q)O_ zM9RbH2XJbETC8qV6{K)}4Zo`o7@Ts!p)AF$Y0R?3b&E@cV*wmHntF3rKspbY&gx*< zLrfu*&k6t9=9-?DyLNL;b3h?3W+XWb#`}?6)3X12w|*hB>-5e)=>1a9!`uJe?cE)v z_TO#$KiVGKwz~D-@YUwe<_I(xf#`7b2#P=iJ#!=Mv8B715M5Xlx)D$hnx03qK)5tn zSX43$${#12N*>|uoCO%9^JG7kC;WlRF6g^o?NGhwVVKz7eYa7E)4o*cpcav|dP#{! z>T2Se)~bUZ&N$V?c;7chyQ7CRiuf=ZcFIy)-MOl6;64YsmN9nO=kLSJTG8N;r~s%bIyY;Cw%rG zu_{pbR?j_OV^4oDtwz_P&**iYi=J!rI@bhCm+mC^6+Q*$7pQqZpX_6JuJL72?UPj? zWSCuxRXmqiI3^wID9uNlO6{YL<~j-YBM< zVrC5^mX6Z4c*ouL=##9DJLNm&M%^IBtch~5Wy~b!i4F*+z{!YwbcU4c>tdc<3oRVo zdVrZF7cCw26t3OEo`KS&CaMYTvnsYZE6p_}%x~bjs$WTQT&Zb>h~lw45dee^3s*=E zyTd|!ZYfrM4X&`SYX6FbQmGBLxQr~#hbmc;{ynrG*2D;1xUo+0p0HJmTi!-}xsy zqn*$1+|v7xd;fgzWbfhL_MRW~-00ce{l9nrhuurv$GbB-{=FSHc6_eu$6fz%*Cf1v z|1-4$$G0Eo{NFnNM(0dtU&n8Dyw~x?jwjmxr2X%=|8o16+k4u64@|+UZ4Yhx<86Oy z+xcysTfe_`Y|Fph^0&53Z`sX5Tl|@i&$MTX(YAZbbRQTrlKGG;i^tTG^w}Q{)OrZf zLTptoMXwlgNTbTL6E4SJXv-AO-`n%ZFsrJEHR=$F#?Qs4X>sV@T1-lLnw!*i_p|ZS zv@>w8?KpPzDbb4?Jnu{KDVkASv*RF4yWT2 zG`a8IntXxk$vTm+Wef3f?gu@8F9Ygg7Aka*1L0ay`kApu$aX|cvm{w1S=}sEK$`KkCQ*IllAU8rF|njL0UpQC(rh&~6MI2;dg^U1n5yO&mp4a=G*_$RQ%XgtUr z`TBPp$-4Cmah!%4ARR${p;p&cBz`&`pp~(@tpwJ42DChbW$)>9T_nNzAuh#7xP7_q z?eC||!lC#u?F}_(&%F~dN@?TlqWn__I92}!Uos-xfc+v*!IAi2%ePROkz3|+@sr##T=yxpa?M?GB<^eY2ygtX zT{Ac11MQjP(c!w!@b?Vt1urqU7rqu4U=-{E?q_Nh+Lgga9M`WUlhgiUVX8zRIcrA! zfkin)N{->T@9B7dTjtW~jrcEKOuQwq;<1l)Vl%;gBk||C{rpC^Bc%pSN=XNlK)6(R zM?CW=h=tNq@e{Oha>F)QD-v}6I=Lt3Cl;QLf1#EB2O%%n;k|Qjp_{H8kN0u=&_>Vp zkIqkv7LYu90RE@qz1(?f!#jW5I&It2<_6ad4waF34|i`kZpc2pvb#Gqk=DksI7@AS zkw!j02^DcY%N1#)lQMyqzmimsy57EWb zjh+;?!`fx}RQw>fU2J@t$z5OHg7v7Sk+=(w#Gm2j;YK$@9F@j>NmU`QA0?JD)q6^KUku2@D#|R^?aU3y$3p|>O6?U9~kBQ>(zg^%Oh<*`qCL z9bH>H24$HgIyoPAX^k9i+<~eaL_o1wvQ4}X71@elTOdw@QMa&+0~d!83i)h)1=^)> za<45jvl0V$B?#2$frE0X!cvhhdPj@|@qo{N;;SEg=Nu{|Y*FT>VV|W70c49)EKLwZ z6dPgdtu+I`6nE;`osFJ7V9%~`27%9UAsTy**1c0m);B&FcTkpXq^>8T=7>|rgU>_u z|Mo3?nch=9`?~&FS9@o-$IO z+DC1jqXF9q-W1f|Dvf3T=J5Yahd=sylx25BbJ1Mg-7!|A$Zk?xXi>>ToZ+*;OQpjn z?h;O3JJqxx(_S1G9?b{M(zXRBxZLlAicmQaTNo_2^6y9mBKz{E{k+P~=yBdZem8!% z?)zWyME(XmqSHgeaJ>`qG8~V)gTvqZS@_L6X^{6+56NDrbRi z#*dwXTanE!M~6t*sP_i!LdDiXusbB~(t7Oyu|Dav|0CP+=t}fCt;mt6zW41}OmY?J zGnU*0@R6!sh}3au2x2%uV$~(ia5)A_z;#j@@yB`jLAAVkE_#f2TIGLrSJ|j%SFwYn z9>##}Mac|hUf@91u));O&T}=W_(uJe^df8)|;Qrvu}??k9KA*-QItD|3=Quu&&m6CY=}B zc{-7>@|rp^Za!Bh#S<=RpyoGG$EKWP*kracMQyL>E5AKb3X+gG!*YNh!Ab>DGzqd# zX(GWhT)h=a0DlGhPm~}K)bShy85Z|!c3QzBO_h+4306>eH-}eZO68z-Xge-bAMILq zqf%I*t|rN3VHtaf%84fSQlk-)Y7E+BH=UBd0BV>ScRHE#%utBQCQaRLZr;to^wEoZ z8BELn-?BZ^b8^R2*W(@kdHeUa{;RFsTk?GLbM^CDbg(^h@bYEHlvrNOLvu^!@U+ zD$#-Ul`A0a&_KQn^ZjZkx*qj)g0le4a&K{Lk1TevYjsi)^+3>@LK>qbP2?51O`-(> zl!0C9=vC025HA5|d>>o9eL6b8%iZ36d-uJ)oT19_xp5SkPsY2G*TCN3rFRI=I@-1w z^RP2PYo`_@E1i*xv(Veha^^wlqH&Yrt-L%)uI0h;sv-z-A7Iz`I{vg0iLxw;wQBh& znvqY4UnVMIU_9MqPhfmK(VqgM_ulx`sy~P+wpCk`Ved{OV=%xG;QgTen`2l7G1g!g z?_mt%-e|veXCb;rWX(BTjD~lR$Hde-gSeYl-K`E{mN13OQR%&Y(DN54-sbcYyT<7a z0i@>kxGH|gsVf9=!OQ}RpV3-lbx~}tCOI+s>L=-o(Wjnm%2fY^;{ERL0Kk@ zazYX-UdIXnvP5#!6ycQc!MvA~c~DFeDGsU4QK>g7@o4k}i!6RLe)QfJnadRp-Wms) zQzR-N@Z4!`!9J(vJ7^K3KdBlfSg13%2GIV;f8Ch{|q4<>L zpLsVbm!n@`7%TfL`|o)eNjY(PKux*{einOwfXmZMGq<3Sv{!fJNrTu7lUP!q;6z81 zC!>kL*%khf%h~p}x&F9?ooR-Ri>k?cJtyG6+=3m!JX#fWDSSI6c2&Mz)OJHuA`p!M zuHa{nEl5W#^5{NsLc!7Jxq@sy8|Gv3GIvL#eN5@yNAKR_&RFXur0zl0z3B(1nonTB ztu;vn&V9*@CJxM+{G2pFSkRABk&n7=p(c(AflgILgQ(uX-b9G6V+g<(jed)tbxmho zC@1khIVac}rC&Y{D^{6Y<_cEgW4nnLOyXV41~rQ@2zcK+bB8$qj3^cv8BS*7(l=Tw zXi?Y?gK`E89jQivocpn=W>Yc53lV#ZDZuKuUQQuWoWQaCQe5YyxpmIo&1odx?4vi0 zvj0zHZfAD=wO!BddVJ@<*!i0~|Lo4|JNNefxc8gAXM6tJp6~R`_6&9Zxchgyzt(+Z z$G_R}>pNc9@rkbA?fT1IrLK{#UEBZJ_P@S;W&6d>|EKdeJEuF3bo~8}3+?~5{qMBD z-2SPy-*5X`+cRyQ+rGc`kGB4et(UicX3OtwxwB;;^ZPt7{c|zC)s~?ERjOc08Ax<# z3IJhlk#d#!po*Qt{-B%?mD13K48rZvJPBm&MobCa(WtXYV?!uOQiO~~O|c+vP9J~- zJv$Wsa*-5i#MMmT$vu6q#LM)x+@$%z?BIz2j-sdr6|yE4pjUY*zep#&0WTl6-~kJB z`K5(I`Pq1hMz1w#bU2F)5OkTy53aryGGy_2hY&<*d5$w_@?2b|nb(^&bA)y_9>imD ziH1%!X=q?rEl~%fnpJR(Dl6va zmB(cgMjfs{6ED)MOHJBFwoNnC@;Ok^th6G$Q1)gOrXQV+sWUqozucq^_hvTMm`$MR zHBlCRRGn+Ifh4V)uk;p|OVe;zPY`$(8eWkWp3=5SuVW2P|mT*2*Q{6 z4W}`Gy_GNLRL_g*C6vjdDAiF`E@L~HFQ15Kx$%kCZ*+Q*QVho8o80<(tG5n&&rAJn z56sc((oUX<-=fu_R$D!0xM3GR=A9==$Fcv27UZuP;Q z-aNp92?!clq!|SsL98?|EaX}l46REycp#c$GHu3>uvXrtp4v@7`~-XFig^}YyqdHwU(Lm}fE+;Fhr z0|wD;Q_$(5_{&^=vff zYO@O9g15j#9f>b<`B>x2M-dRS_Ueg4QYrrKnUHWJBaX!{(Z=b*NIiRzdj=Zc^P}5;&e9$=2U0>OW@h6T+A|~3{>Jx^Wpx-7t}wdT z^T8}^bE@=$wC0tJFVQoft-@)xsKYT}Mgj;|x}h33Oa215c_ zc3_^P@p*1J+3fw&w}f&dgYmhx%)zkFLOgY#|ESFt^aSvr*g7NDK=DNB6B7$h#?Nun zDZe?Bn-0612tR=NAmfB{kzA%H;%B)y$m(!0mpTYsV%MFFN4YM@jd0yGc9|GNeg2Xt zTtbld08o1lIm#pU?TycJZ#Z(Q5&qbyk}nm9!tF5*S#NQAo-~&1HGzt+=ie%3M~XPUuBuEi z_+qRX$?vJ`+2^y*7U0Kn*-hu6@Xya=&lf1Fi}amXRt~J{oLS1N(qG3_F4qNbbk^gF zE}`88NRIL2uSj?0~ zVqx|wFmN48;VWT?6l{Pe-H}0HJ#s53$|bTv_oxQ9nZ9T_ke)an6GzTC5j21(`pg)@ z(3_Q$Y#$gnkKg3>Tcjwjb&FA@TQ*MN*=~HNtXmpetg_Uwwsv1KtOFa5YHKZ4KC!?1 zxyq>*Ms|dwNo`sRc#UFlesklT5-7C)7oV_Avv#ngcC%y^vEP05fQlN$#Wq^he zZ3V^-bU-UmeG33GQ9o8TCE4T>R7qeKpD;m7q$Cnyq_rP?^Dlaz_K&{#moN!=(jl>& z;>;#iGg-iyOOyunQuULyO$Z*A2sBHcebfl@7v9G##l_A0_`|;=_v1Mhs>I2XT;W`UqK=Ix zj4E!}z?cAt3fdGrd(4tAX0I%48Z+p*21=1K+^P~8-sM@|?{>hHxz}G2XWu2hXB&N0 zs65^4V!W&g(?St8R^~>EoAcngEtJwmpRa=RbW@$!@xX(j8lgFtxK8xMa-_Q-PUT!tK^j?OyVI#M9 z{X);kovw=qcaQAZ5+6^Qb61>yL6)AZ(u-98R`4rdmSd1{KwxMKFyJ|5pO~vb;(`?_ zw0$V`o>+?77b?$m0qg^Uf-RzhT1%8+oFRTKx&%8z*&@uEyB;qSd(Adl;i1bx6sodFR3sm$eNC8I=(%;w$ z)`F4tfDAp#aUwx1x!L%JWZASLHXApyk8@|DIC=Wbw1jrUn{#>cIsH|dcynkXKRG;6 zIGH;>bTpqkdTi=MZhZL2Q11ANiJ_s%!NT#u<0s!_&q0_`8q5tuJOT6pqF31}@w+bQzlv8GXW77(+g?9Dt&^GCTj(&T{YX_3rEb!yW%l*Z;l!X6K3a<+ktg#Rv5B-ht?NXXea%yWiXG z`?fv=uofvabi^e>rULS+R@=;7>x3IJ1dGGurq%nh5o9nKXOl2K1m}}WCGbLh^eKtZ zR@}-agB`!4`H4NcfRyKIDG>z>=5MlsErkaYiJjw;xk0M|rj;CiKRjdhIxd9b8nNS* zbHNjY)JQOgDD?4w`Y`}Q{Ms%dB#r80EwS=a=wTOi@GmV;6nxBLzOpLuY&)Td!dtSr zB+mOi`2aQwn-0Bv18`Pw`Xm^8wjD=&5v7_0ueHgrn`?lu>G~+i$9WAzm!e~x zc=Rbl(D)p*v)3*E1lx_8pj5%eK5|LY5RS=~OGR)SGh~h@ksIjTRh8U!=6!6nawZz) zg(?Rt2OGbTXDL9C;3-EJav=bB_)%Vo{fW)uxH&k^1P|w;ph8L8LX*SV;&cMz%I=hR zzzz_>6pdfsy%td+TRfOI#_)iGR%gJRcwuMu19G!`OdX;IN6{&%fppO!H(1rp?0XbQ z7d|ep6CaL_GKB($H=e?3DvmpBG-PtHh#4l#6bFz#o)K@hPyb>dnO#JvMs{Ih0->t9 zDb8F4 ziZ!@CnJTp(T!LO0U{_a_h8Po@fV?L>s6IpksXPj4ayqK~+2=6fq?G~@(Ny4XQ83wI z!Th|bHy_15Q#W^zz~j5`HlB)$RTMT(lD9FLt#pCJh$^5P9?eHWWoxo{89vA=`rr4B z@ug@$E97L{M9@3TvcOS(K3rH#$vEJZ>51kwOn!A{Qy(SPqf>zg;%*raY>TOVO|X3UH@SN_zi|O)p3ouq@?vBFs@-TEart>v9CJSY^`7(Tq$d3DwyQ3)Jr8+FLlo7H(no z2aBX;5WIkNnGSkDvX!*0rvQ@%ZkGi@wy)UE=fRG)s(*6&!y6g`cn z@y^3{!lAg{(>Nx|Gd6@Hp>VmgP80|^%916dfkWS-v!1PJ%t#L0ImHoR-Y;g#QgwB5 ztk0pxO%@!0rc70Bzr@337))va~3`fvvB)rbc+3Q zd*t>=L(jZh{Och4(k*QRRF7XfhRn$!{<2rI<`uqdYm1}LxQ8%xSXm5e>n*6s(==<1c|ByY2Ndi8X}x49ztih;bO zxlU!*C$IQLyRevSMuLeXKlNv?OYfaoSmq@yi`+*rJ*HSYRaj+9gpr1t9xeYwTm3F0 z-P%mFd}Af8O}j}c+x9dLL|J_Y{PCKK4FyQFv$3lCvG0`03w9?mCTu`Ec)SUx?l>Nd z{>^bwq;dVYR2HKXtf|V4%8iC=iqac`RVjZNBZx7@Nd~M#MwF!Yn&c(IsLF|z#j_?0 z%E>^GSdMHKv1%}`q~`Le>Q3S!w`A-fP=0OMWo~=K9fZ-~>?X*>VA05>lzf2DWhuD3 zCzb)ug|P0rch^Bu^PHcT_mus=ZR=y19sfh;GyG@sXLAIqBk=9Vqi5vr`Np@t(W<`( zXA2=!0Z`d_=0RSPOU)#))F6BwruZo858*UPHwUKkQmW*902hE6R+l`P7P#BIk_NKD zhFjUw*Pnf9;Z^|A8ipW0X|OndA+SQ9@=SLYRri?Ck#K_o`XsiScQpi&ln$Fp!dajr zl#ywInDC6_p6)OBgF*)aCpUe-UQ39A!n2(yU7)y09r{0KG^wHlkatEaxSvuL%+D+T ztNJX^rSkZy)if~V{h&*9yw8Jx#X4k4WyTR6^B$(O+bMXNRMJso9hlu!flwJ#=5)vXmkbeGpv{aK5JDC#J8Cnv=^+@4wygcNlXt&Ra(L%!hy_tH*nQ1moiD}B+bj}We_!}t;W z+74$hvw#c2J$`)Q9il9(XHpv;qMj~$Bia=gStJg&Y;>PsTxtR*ecpsl zvVD;XC`1TCWwI|PM8Pm5B~KyK02&Nt4fgY zQ&@1K%<~;AhftjwVNOz%sbJ=Y! zJ1ml!pYpPk{ok1>WqNwM{%+@R`yaLa`E6h3&kykD_EdDfGc$Vo<=f3z*evWzWLX5$ zXbiQb!koqvI6H;l;)D+2JJ8X^cO+txvSEj4!6cn*%r&x3=_czMN1mj_QNqG*ogoq^ zM?F!CF`zt{lJ#n!A*?KIR$e85YK9o37lH0wQEo#&mPH%#Gu4D&5x_xZqwdO%HH_V@Bh$t z3_9~?QHQl6TUCdz;y{;z!uT0T!e>1P3o}Sv1TMN&l^4=e^=WZBIE5Q|)eb6j2--t#T#?{wXTV}6RJWUF@SDxkZESxg!*AkUgGE@4o z+-tT5MUd&CYgL>`V8LzRgiMKs`Hkz5j0%X#j5(uM&tv`5g#;iM5NGfl5z-`i8waGD zJmNWSI<322lFX2b=!_0!gK6IsCa3);mf*`RW;#|A6V@f7^luJRVyQJ7rq!|NtQO$F z>OiaeSoTHOv_98Rs!4u=8U)L;24gjo1wu5f3l>7aCYmSNO|nNu;cHsL$3rHo)Sv)r z@Q?wM>+yDi=t6S^A!$5+|+vzs=vx9DP0AQf6?`c&!6&@%HjjNQ~S^%hvNuw(( z2F=%I7wUQk0#%hiWf>-LBnub&4)SVq1=!j*M+BSQ!0BN`?k+?lEUUYh?p|tnS@|jm zYkZ08=ARE-JxO1URO`XT5*o!j5Qys|9{4U@2DQWAq~f^uBh0Z;Xe0O@&Am+jHgYg) zg@wS8)84ADEvJL&ZuMd)?&2A2lfv83h8xN}h|kmzTty9Wm)iPwU_3iMyx&!i!*Mig zTt58AQD6vnPBu>oKr+ekMsO9e+VaR&TpN-)yH6dW&aOlzLweb zk9Hl|`A>G<-g&(DPkaAL@0WXb_59a8-|Bg~r=$D7?>@HU4|e>89hY}(?fOr7${Otu+*|wiEdk5mb3t z>n~Og(8Nk>O(cH8dU)O6cEr}}@w#8A?B@}~tv$j6c>Qs>xNwWm@5##NY2aXM4R{2V zF2+opeYWxh_l~r7uig)*w>-UTETnUlU!a*5rz~iz=^%_@hv7(hp|X#LF1Og9BSvD5 zl=>?AgzgDU*n`&3zLCmaT07NRYk?PYd0qw~QXD-7_t9`=4{hvgt&JC|B?Zn^viE05 z&Q~6%q4TYEU?9M^jJswHr|iYb=V^Tio;h(O#!<4ZKl#kOr3TsRQ+-lIQPVFO|+z zKEnf!-_rwXMdz8y?$%ofGQl&GI6&s5%BN{zthGLP!Itb^oVPhEg~v{I3$OfQ7|9sEw0oOup&jbDfRrFV`*vaSjY=o?w!HHk+Z%eo?6~twqG`YkkH?ep zL3ki!MY)f>3u7|cSLsk4p-(mOPLEK~zVJ5j>Vjhxg=v-yW;`Mw)eXIaF5~Gr1y`Z? zl#3o)rB{5qv1+^3yE)D@m$!BGp_H z_1Vf+8XIfU7?R(gjb7<7;aIblzfjpiBQG>*B$(qy^a_!#s11zo9pB{Jg}&!2nGIg4 zY2hk&aQJdneWUTaH1=wf-V9KNRk5CNi3r!FXDup~>e5T`FVV`)Canx+NAnc9EWv2+ zQuDk;pU=LPCtW=mXrHw)5`TjRn+0D}hgdb3;*V^X2KYk!b=qjg3hSnxve`z`ns^@F z%5k3N0bdxUd?EfCt<^9Xt_hL_y`jG6J5}u9M*LMaX4CR-1J0T#B2OoaXp3n7>^#_b z;nJLil2=RHbo6#wQW6be0hq=stWrNu(j;x z>{$XRKl~2NUcMixYe%WOm7mY|ZP2yB_#H-Zs7c2VxK?#3RZ>azf5(gJV=8oha%ueQ4IDGVd@Q~{? zkZW(Y|NY;&`cU*DJzL$jx~<7lfszEtm?T{vP}ozTc?WAUhasKqQ^*vQCM9D8PM1f< z6hQK9AY-oHp3qZO&!+4F2V|3@(c@7GE8xGkAXF_#>wr*V>$B0E^^b#7C^d2c6n3RQ z?vOYn{nSONWam5fLB#}!7I27xk*H!JI6_J91n4GcU7&OFr5VwVe|}#5_EPi$YvcBt zx0?y$>e_RMRqd*!R+4lkw`{KgPO;OC#o&Rv>%c2szf#3{H%n+hw=|Iubf6du{(z`f zSjp4Jz66E+Q%3FTT|zDte`{fWKX^kCj@UEMq~{dk8ebj<;Q*pnh4iFfn;T!hXze*~ zgSB8x7<1|-o-ZgbxY`oS#1pHXCzahTa!Xv%L&&8sOyosU;(g}D$>KtJ1-KE~l0y-@ zW$sZGh;W{XqHj!M+~dBjeGg$A-$u(%ZSu{5{y+!%?k`2pv+nN}?-rZL#AmI-qz8VO zm~z^iILl$^BVK=v2&5nnN_a%hkcDFv0}w8AE^_WK4MNWL#32_al@5rZy#V2_YXY%K z)YY%OrR520*+OEr8p&qjD6oftSP5|((Rl|We+C4h~EyP^YYJKU#+v(((h6s98r)E|54<3baak=Dd zJMi7S`_U7%$H3-n|2)lhyf?at1c-a%-X;>jc#Wk7xy5OiCs8H2l$5aE0p(4xFRE+W zEnSu(Wh+>~+5T zx)lUw|pjZf#E!cP9A2o)mC_AYEPL!WGx# zEOpNtFD#*g%xmYvE`^{W@yRDg7-Q}%Ccmeznxyo$%Tg#66WmRer9FGVwdgfZOFJ-y zKstr$yHH1gv`aT{yrI7iwZS|S1rN~G0K5eU{p<=lYC@6an&!pw?rI0a67*0OyN0i! z!sH$(j7y371=5soDB)Kz@9Wf34wXhZ9WcrsAYGJ(ko&Y~Wibp*6Ou)!5)Hc4hNJKf zCZ-(Vv<4ghvN;_Mt~KN&W&h@^ejI02_J8}fe~{Vv-R>86EVX}*UpId?M__XVK0+f9 zzZShB-DM;mX>uw%cD1zM+s!#-4rqmFQ(g_S>hweY(lW zDs6d97{-RlF-RS%9s=RE(LYO)Zz77 zYgrSY(y*3_z=h~3D*(UWB))HXTv$TZA!v;5YG(1uT5nuSxe7pQoM(& zxyN|(4yIJ83yaGPjuKUA(xP(d9pE66_IjvwBU5^A=#V0ZPDgd~;nX>HfYe`0Ew`cb zwg8!6dI{Ta$$Ks;EI}NC{wQ^g5JjH)lzZ_H-~kBJWEs?GT=#B-&~iQ>+-|5 zE~Bf_6{Ko(CTf=5_2k8$(3uzktDS)B{{b|7=W2AB_qucDPP6xV)>F176wB(gZGLA0hV%%%V)<6FG;4_%yj9ra#B=eN zL3jhiPIjWRodfMqO`3;0!;vo7(2jCQtv1BnhbIJldli504R1Vk5><4@Va<`B-bPGd z`D4UZbYPg@ZVl(T9&XtrNjO-6t$QICTH8ZAQ#A-SS_v8LnqC>OqCX_v+8IQ6fGMa=IcK#<7eyOPwPpW&-plv!0Nu}T4(0EVHa8|KYj@)I_OsU+JgzQCN^i>P|%;_ z9<{_|4`p=+m=u0Y8<}k?r)K$D)e4e6pHVU9w<%XIM>X=P01s(G#xf!PynTByo$(7Il4FBUH++ z;=u#_stRytPo=k#bGoETN;p`3vTNi$X_6c3*Ra#Mlp~}i7wS-m>dysZ^?eNsDVs|% zF*;MjLMrA^l)9gz7p|O+u4+jo%ttDXT|F4>+43DutTpgH zF7NT)g=h?W=)Ix$nt^?<;vrqcqE&e&oWMRYCyhqdfYum2-uvu!FizG9b3!uE=oLf( zd?ig}exiH?Lq5=hsL7YIH`TZDbnRv9E+EG6{p$pDsUgxR^>7N90%M*Qd!DD%{bW;sTsyeTFNHL#bMMq zB|OK1%fPT$%c8waO>u6IL&^H=1L>@8V|`VGV3OW2=xi#ubFy^ep`{+Ba9&ivKPSj!e;e$AEbFRl4t^Uuu@*c<^yASy@K(Y>OvXsk8e z%cD@;#o0XiE+AY$VkkZef!fiLoW@SxqXL62w*w;N<#Om&3)#CA=e+2+brSaf6dn;D zkG{xj#}CF2w)WcRief{rqx7Y$3ipOafUXFxvJmVHc27`@*wOlOc$a4jD-4)2z1>|d zNa4&@8^bDJj8r{&g8;)A!Vn{pBjGxm( zE;NL^8yHQG+Hf=tn5+r8WMD^NtZJeJH4eG^)n?_*=*zrV)&J&?o5YnBC*@Y@9clv_d0EDVAY>ZGx@c_$)Qm6$ngy09zj+_QFxv-F(%0ubk z$uA|47fTCD9ke4i@ZF#V3T&wY-R4hm;$5gT_N}AXA*aCcorROi?E)OTViqG;cAf;b zC!Gh1mjqzP3^D!>h#8^$ z3cRJudeF0l%>gS(EQ?GAvO+h9_5&MQ+5h9){%mH~4|l!2YtPP`I}hya>iw6!|G4*e zdVjsQ(mUBZ(!0O+(cX@pKkWH?J%6z$?s>Z>-*d9(k?#KsUcle){;lp`>0a)BrTawp zq3#EF{CLMd+3`1b{J9->ca(NKzvJMJ?OlJ=^`oxe>-uY5ce*CJE_R*nI?$Eb{y%O1 z?d{*){_k(EY=3?G)7u~J{Qo-twDS);|8D26b}n^(sq>}IlbsKA{7J`u)A65le6QnI zI%YdAbv)VeiH^4RAGiN*`>(c7w4Z2ywC(?F`>nR`w7uK*X4|>8{cT&e{de1bo0r)9 z*&Kn7^a$iud)hKjoF9knV?LiVLw(@zQDXvwQ4fl!TfWlGB3bA2<-SK&ySaW(`g)fq zCk18SD#T7t45hy`in&_TW#1}{O>3??JSd)!a2=dn`OmJx#`MG!>9#!kf*D4iS?%QO zhiktUrTAm39elAr{lx&StE5tSnKS5ft1uKj(O2(#cZxl{3Nz6YkEbsSkTY-Tlb6S_w@8m7MZl#lNbKSa5F7sjNEunmZl#lNaoxI37WpuAa)#gQcXFC*NFExSy-AX6l;JS64yupW|lV9fd z`kj28Z#L-Um$;-!C$IB$E1moz*RAX1H9icTe2w4hck)%f*`SkGxui)a$N0LHPQJo* z>pJ-|ABIj|;rIHTyv#Qnbn+!GY0}9{eBDYXU*x)VoqT~0Lnoi-_xhc@$Tu5w@&cDM z>EwC7Zl#mwxNco1pX0;O$!Gb!ekVuyW`j9Vq z*Ps344pi|@AW%*oNqShmK0Y}`N(JH+bHXhGTS2Fjd$2Hz`$8^C5)Y?Q3aJFb!{+%L&<406 z^VZ!ezzGE@Z5A-&vOJF~=z(+PAAR%JXeC@Y16bdeth8E^CHL_DS1LJP{6=eieyuQF zSTe>6`7IBqmka{#RA@QPGwG;qp_x2HqnBE1)Rh5-l7TX$KD5I7i6GZiynd>3kj8SY zH8xxRH3Cs4 z`la^F@p3usDxiL1c_}wAICNI5fX;z!$&H7Rq!OU`(N!>5(o|7!G4_es2TbYw`?%$` z=o@t5;>EgMkTYI>eZpN(sheNjd?)-4^-l9|qlcoecV>=9T~SxvwmtKu_ltyh{46;I zNuXL@oWsH0UyWAFt@M-K&A@-H$-oO;Z6`I}Am1?s11VrHRI0x5(P%mT&3|$B-fy`S zO|)k+ufD1`QSgux7kqgUY6~MF5JM?YQ9^Ue(^i~uqiZfkZs;x6X^|^?x5?rnuEXj6 zd%gbd<>*b~WOonWZLvs5$aIm0#D37O6X^WE( z^l?}}LA|scWof-?IR##@%xFDoX!ytv{&wI_5Gsa%Zqo?MA$tmvEt z{|E^txnQP2`qUXc&Kh;)?HCER67fE@Xi3ij8=cIvk|Jtg%@$V!vVpis5_1|uFOqf` zHdJdMRNSYrQr=T-f_MMsgnrB>lq3Ag{XE7Wh~Q+;Jp8Z@fy6N`)u%m z=$-0k$#u7?pC#A5UHvS%Zn^qda@|t(v*fyR^|R!G#ex_MvQ>y6%`z1_Pn%+1Z|pG#5kzP5icnxVb>b;?fP T=e|wd$G#QrbKfTKTi^bFlb9nW diff --git a/mealie/db/db_base.py b/mealie/db/db_base.py index 3bf60c7cc..c9ccb8601 100644 --- a/mealie/db/db_base.py +++ b/mealie/db/db_base.py @@ -71,12 +71,21 @@ class BaseDocument: if limit == 1: return list[0] - session.close() return list def _query_one( self, match_value: str, match_key: str = None ) -> Union[Session, SqlAlchemyBase]: + """Query the sql database for one item an return the sql alchemy model + object. If no match key is provided the primary_key attribute will be used. + + Args: + match_value (str): The value to use in the query + match_key (str, optional): the key/property to match against. Defaults to None. + + Returns: + Union[Session, SqlAlchemyBase]: Will return both the session and found model + """ session = self.create_session() if match_key == None: @@ -136,7 +145,13 @@ class BaseDocument: new_document.save() return BaseDocument._unpack_mongo(new_document) elif USE_SQL: - return self.save_new_sql(document) + session = self.create_session() + new_document = self.sql_model(**document) + session.add(new_document) + return_data = new_document.dict() + session.commit() + + return return_data def delete(self, primary_key_value) -> dict: if USE_MONGO: diff --git a/mealie/db/db_recipes.py b/mealie/db/db_recipes.py index 801134756..a2a35b2d2 100644 --- a/mealie/db/db_recipes.py +++ b/mealie/db/db_recipes.py @@ -49,14 +49,16 @@ class _Recipes(BaseDocument): return new_data.get("slug") elif USE_SQL: - session, recipe = self._query_one(match_value=slug) - recipe.update(**new_data) - recipe_dict = recipe.dict() - session.commit() + # data = self.save_new(new_data) + # session, recipe = self._query_one(match_value=slug) + session = self.create_session() + session.merge((self.sql_model(**new_data))) + # recipe_dict = recipe.dict() + # session.commit() session.close() - return recipe_dict + return "string" def update_image(self, slug: str, extension: str) -> None: if USE_MONGO: diff --git a/mealie/db/sql/meal_models.py b/mealie/db/sql/meal_models.py index d696c37a9..e08bc57c0 100644 --- a/mealie/db/sql/meal_models.py +++ b/mealie/db/sql/meal_models.py @@ -39,6 +39,14 @@ class MealPlanModel(SqlAlchemyBase): endDate = sa.Column(sa.Date) meals: List[Meal] = orm.relation(Meal) + def __init__(self, startDate, endDate, meals) -> None: + self.startDate = startDate + self.endDate = endDate + self.meals = [Meal(meal) for meal in meals] + + def update(self, startDate, endDate, meals) -> None: + self.__init__(startDate, endDate, meals) + def dict(self) -> dict: data = { "uid": self.uid, diff --git a/mealie/db/sql/recipe_models.py b/mealie/db/sql/recipe_models.py index 47edd6da0..f14959198 100644 --- a/mealie/db/sql/recipe_models.py +++ b/mealie/db/sql/recipe_models.py @@ -10,18 +10,22 @@ from db.sql.model_base import SqlAlchemyBase class ApiExtras(SqlAlchemyBase): __tablename__ = "api_extras" id = sa.Column(sa.Integer, primary_key=True) - parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.slug")) - key: sa.Column(sa.String, primary_key=True) - value: sa.Column(sa.String) + parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.id")) + key_name = sa.Column(sa.String, unique=True) + value = sa.Column(sa.String) + + def __init__(self, key, value) -> None: + self.key_name = key + self.value = value def dict(self): - return {self.key: self.value} + return {self.key_name: self.value} class Category(SqlAlchemyBase): __tablename__ = "categories" id = sa.Column(sa.Integer, primary_key=True) - parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.slug")) + parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.id")) name = sa.Column(sa.String, index=True) def to_str(self): @@ -31,7 +35,7 @@ class Category(SqlAlchemyBase): class Tag(SqlAlchemyBase): __tablename__ = "tags" id = sa.Column(sa.Integer, primary_key=True) - parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.slug")) + parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.id")) name = sa.Column(sa.String, index=True) def to_str(self): @@ -41,7 +45,7 @@ class Tag(SqlAlchemyBase): class Note(SqlAlchemyBase): __tablename__ = "notes" id = sa.Column(sa.Integer, primary_key=True) - parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.slug")) + parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.id")) title = sa.Column(sa.String) text = sa.Column(sa.String) @@ -52,9 +56,12 @@ class Note(SqlAlchemyBase): class RecipeIngredient(SqlAlchemyBase): __tablename__ = "recipes_ingredients" id = sa.Column(sa.Integer, primary_key=True) - parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.slug")) + parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.id")) ingredient = sa.Column(sa.String) + def update(self, ingredient): + self.ingredient = ingredient + def to_str(self): return self.ingredient @@ -62,7 +69,7 @@ class RecipeIngredient(SqlAlchemyBase): class RecipeInstruction(SqlAlchemyBase): __tablename__ = "recipe_instructions" id = sa.Column(sa.Integer, primary_key=True) - parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.slug")) + parent_id = sa.Column(sa.String, sa.ForeignKey("recipes.id")) type = sa.Column(sa.String, default="") text = sa.Column(sa.String) @@ -74,24 +81,33 @@ class RecipeInstruction(SqlAlchemyBase): class RecipeModel(SqlAlchemyBase): __tablename__ = "recipes" + id = sa.Column(sa.Integer, primary_key=True) name = sa.Column(sa.String) description = sa.Column(sa.String) image = sa.Column(sa.String) recipeYield = sa.Column(sa.String) recipeIngredient: List[RecipeIngredient] = orm.relationship( - "RecipeIngredient", cascade="all, delete" + "RecipeIngredient", cascade="all, delete", order_by="RecipeIngredient.position" ) recipeInstructions: List[RecipeInstruction] = orm.relationship( - "RecipeInstruction", cascade="all, delete" + "RecipeInstruction", + cascade="all, delete", + order_by="RecipeInstruction.position", ) totalTime = sa.Column(sa.String) # Mealie Specific - slug = sa.Column(sa.String, primary_key=True, index=True, unique=True) - categories: List[Category] = orm.relationship("Category", cascade="all, delete") - tags: List[Tag] = orm.relationship("Tag", cascade="all, delete") + slug = sa.Column(sa.String, index=True, unique=True) + categories: List[Category] = orm.relationship( + "Category", cascade="all, delete", order_by="Category.position" + ) + tags: List[Tag] = orm.relationship( + "Tag", cascade="all, delete", order_by="Tag.position" + ) dateAdded = sa.Column(sa.Date, default=date.today) - notes: List[Note] = orm.relationship("Note", cascade="all, delete") + notes: List[Note] = orm.relationship( + "Note", cascade="all, delete", order_by="Note.position" + ) rating = sa.Column(sa.Integer) orgURL = sa.Column(sa.String) extras: List[ApiExtras] = orm.relationship("ApiExtras", cascade="all, delete") @@ -118,7 +134,6 @@ class RecipeModel(SqlAlchemyBase): self.description = description self.image = image self.recipeYield = recipeYield - print(recipeIngredient) self.recipeIngredient = [ RecipeIngredient(ingredient=ingr) for ingr in recipeIngredient ] @@ -130,13 +145,28 @@ class RecipeModel(SqlAlchemyBase): # Mealie Specific self.slug = slug - self.categories = [Category(cat) for cat in categories] + self.categories = [Category(name=cat) for cat in categories] self.tags = [Tag(name=tag) for tag in tags] self.dateAdded = dateAdded self.notes = [Note(note) for note in notes] self.rating = rating self.orgURL = orgURL - self.extras = [ApiExtras(extra) for extra in extras] + self.extras = [ApiExtras(key=key, value=value) for key, value in extras.items()] + + @staticmethod + def _update_list_str(new_list, existing, cls_model): + current_index = 0 + + new_list = [] + for item in new_list: + try: + existing.update(new_list[current_index]) + current_index += 1 + except: + existing.append(cls_model(item)) + + for item in new_list[current_index:]: + existing.append(cls_model(item)) def update( self, @@ -156,29 +186,41 @@ class RecipeModel(SqlAlchemyBase): orgURL: str = None, extras: dict = None, ): - self.__init__( - name, - description, - image, - recipeYield, - recipeIngredient, - recipeInstructions, - totalTime, - slug, - categories, - tags, - dateAdded, - notes, - rating, - orgURL, - extras, + self.name = name + self.description = description + self.image = image + self.recipeYield = recipeYield + + for ingr in recipeIngredient: + self.recipeIngredient + self.recipeIngredient = RecipeModel._update_list_str( + recipeIngredient, self.recipeIngredient, RecipeIngredient ) + # self.recipeInstructions = recipeInstructions + + # self.totalTime = totalTime + # self.slug = slug + # self.categories = categories + + # for category in categories: + # if category in self.categories: + # pass + # else: + # self.categories.append(Category(name=category)) + + # self.tags = tags + # self.dateAdded = dateAdded + # self.notes = notes + # self.rating = rating + # self.orgURL = orgURL + # self.extras = extras @staticmethod def _flatten_dict(list_of_dict: List[dict]): finalMap = {} for d in list_of_dict: - finalMap.update(d) + + finalMap.update(d.dict()) return finalMap diff --git a/mealie/services/migrations/chowdown.py b/mealie/services/migrations/chowdown.py index 01b23be2f..061a2ac8c 100644 --- a/mealie/services/migrations/chowdown.py +++ b/mealie/services/migrations/chowdown.py @@ -3,8 +3,8 @@ from pathlib import Path import git import yaml -from services.image_services import IMG_DIR from services.recipe_services import Recipe +from settings import IMG_DIR try: from yaml import CLoader as Loader diff --git a/mealie/services/migrations/nextcloud.py b/mealie/services/migrations/nextcloud.py index a8698cf06..3cac03ef7 100644 --- a/mealie/services/migrations/nextcloud.py +++ b/mealie/services/migrations/nextcloud.py @@ -4,9 +4,10 @@ import shutil import zipfile from pathlib import Path -from services.recipe_services import IMG_DIR, Recipe +from services.recipe_services import Recipe from services.scrape_services import normalize_data, process_recipe_data -from settings import TEMP_DIR +from settings import IMG_DIR, TEMP_DIR + CWD = Path(__file__).parent MIGRTAION_DIR = CWD.parent.parent.joinpath("data", "migration")