From 9544661dcf0fdba1bb97564a09cda8a5d36192ac Mon Sep 17 00:00:00 2001 From: Nas <94843416+Nasirhus@users.noreply.github.com> Date: Wed, 8 Nov 2023 10:35:13 +0000 Subject: [PATCH 01/13] Shows to do items code --- README.md | 3 +++ todo_app/app.py | 7 +++++-- todo_app/templates/index.html | 5 +++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e153c3396..280201222 100644 --- a/README.md +++ b/README.md @@ -52,3 +52,6 @@ You should see output similar to the following: * Debugger PIN: 226-556-590 ``` Now visit [`http://localhost:5000/`](http://localhost:5000/) in your web browser to view the app. + +```git remote -v ``` +tells us / lists our remotes diff --git a/todo_app/app.py b/todo_app/app.py index d71780a32..2afa17fe4 100644 --- a/todo_app/app.py +++ b/todo_app/app.py @@ -1,11 +1,14 @@ -from flask import Flask +from flask import Flask, render_template from todo_app.flask_config import Config +from todo_app.data.session_items import get_items + app = Flask(__name__) app.config.from_object(Config()) @app.route('/') def index(): - return 'Hello World!' + items = get_items() + return render_template('index.html', html_items = items) diff --git a/todo_app/templates/index.html b/todo_app/templates/index.html index d6f8d9c85..a9e9d5384 100644 --- a/todo_app/templates/index.html +++ b/todo_app/templates/index.html @@ -12,6 +12,11 @@
Z9JTcmqT|3LT(KE*2xqIyTfcY!ZtiR;p&}JB& zl&%@^_23gqJVnVYrIQd^YD>(kzsSt5bt3&lcJ@zfED5{;?d8pKM>D@ZgLug*Z=Id3#2XUyCL5XIXyQ*;UC zp{2Y8o4$fsfsPsg_OOrIo|$LAc*B#v8D}}lI~jAm+$tlb9)~c+T^$pRnR?G%7N2|4 zc~Fa)F6%4NELEMqqu|8pi$Pzi lrikW|ktX($8lmqUR)Kffd9#n!s&gN>cA%12%cN&wIT=)y4OEgSo&F zzR#5fd%ho1k)QGWvlIVNCw@zVj!;r-{gKCGUt8{xrA0~Ir(YIt({8OUJ-P*O63qjo zP&pbV;7M@=TKkM7M6m#0j7LlmrO|cL^>&c6mzJg}IOf_!qBGBpLk9 5F=_N|d< zbG$h?`6}inaL+w8+Oo9VZ--@6O!h3Cf!2*lPehwLK)27?o4_B7dG_TYAKZF$0-Qt% zz&PFUO)R`9VI?@N%fv+K7C#>J^2Ac5zdH&MrGtQ8%q14E50&ODxt;>h H9ZX>m0iprs$^l9ayyj zz_?lI*Dr(3Rwsk&Du9zXr%sq+!9wVEE+C-xhzli&=r2yCLaGLHD!KzUZBF9qaVtP@ zGi3{;0sWvI1qK0k5ddy#RgBew_iwUr(GIxw9c{?bY67VK!ro^a*zAwS;5rpJp{o3+ z3fdGc==R<@1!D9ZxUv7to5NdKIv64=usEx?ura50DMg+}HhRJei>Gw;wsS1w3e-5( zC!ZE8m*|%?28+{avPmP+zFocEjz8^`ykz8$VLGsCgNf+6oKo_B4Mu2~#3rr#Db;CN zYe(Bg_jLo3Z%^$~FS}8ZjlS%ucVf8uWTb1NYj<%Znl4r`c2{>`NNa7)+Nf`m3x4iN z?`<#6L*N~mH%j0vqY~Psv#;#hwmHa!`G*w`$k8O$7!JrcH?V4RwqI5HI<)QA(riZd zKx1hRI+8W+mM}89@YLQ@=9jlP?;NZd;xz7tYiIN{xE>)VyVAe;kKanpOFCUnt}6a9H55-So&r9JG}{UL*|t&H`HK;%tNGahSYCQppAdIm}+La7j~ z+!FFaMuwr%U8yD) 3R>;exi+8SHkx-vy2iMk}zdDMfkv;1r-_p;O zHa}xJ1xA+U+&*ll7ZDw#tioUD2HB$(lB~fD#FzPwD18O7sIAFn`4jDB{28`_8G7!! zj=zEa_ytsmMWQbpKj#OR@6|Wq+jy~qu6wAOoPy(Sub+(kU-QpUa5kxI*lDe1&h^Ue zp>35zJoD~%VIJY!aP-*YlX7{uI)%UQj^a{ I#<^_HS4CZLB=RxK?bw0b z$keuNQ4HRS5En|BO wsf7YCQ1S8a=%Z?el2qwcGhgy@cRTtyxoE=h$# zs-9n##=-_b2u13+Qtmlmd`MDFZf=V1GmZYADnLx2@8ow+l@5)%GaCwJYV- j&$Y)jw_AZJi9R#QM+-lymN7I$Ca9rq4<&JQHHER!BcVik$vTeqM?>} zV`*wP2+l~IxwT?+*cO}E1)>vQKXkbH=46a(@e_4e_KlXa%$p-!ini-H)inp`L;E;2 z4%su+#tF}y;QHe8Mz;W0m@rQd4R5@gL}ut2SnVGlVmZuMXx^I=wP@Fva|p|*QGwPJ zwP$_n#p5*TqRg aBVPr!OFjVXyu;k+5rs4e$ zm+8RVoz+12!@Rd5+3-cot~zvR7dd%%BsRaw7tA9SC8@kHY`7{}5}WA%nDorQRw50= zS3P%Rwsg#H9ZWcytDKz9GzPdvC>iUIVfnyyuGjaSJyar9zOb80_oXYnV36{LI{Y0j z^^G$0tgbm{0k`_2^Imuo^~GWOpz}T|+i0MHoW6$&qB>fwOR$gs718p-*3@{KL3a_E z`s$>EeV#Qvncn?1G0$@?YnII>bvgF=;I132uAog>o`m?}$Bp{;&s0^T;fz>trbg&Y zdX&S2_{6S 6b*?C6XFlv {cS#3m3!*EFr~ zxiyQffK9m4>$&cMMv$amq6gFQc45%xD$ig_6uZNbQPkx??!_{GdVek&&p{t#MY= zb$5pDAYkMeZ-b$i$B#D}o=R%cV;#DFUl#D2+ pCK zE?>NVv`u-)r6Nc(HKFEOpW77&_)+y=+T}B!2Ry-?4&9@p5mvr9P@!38L3i;$V_Scd zPRY=Jn2&c8ojdVvg=~g ra8CKA!Rb~HkxECtSp z>6r)|dD8a)(e-m_6Nv2S>Caq66R^pl0UR2BOuKc^reUy1BDAdHT66sOqzBKXn?!vI zv }fb9eY(}_B9w^zN2`MPx|akqKrX^<;Gww)?K!t%_^<$p!o z89c=#$T!19nEkEE<9%s0mg$_ixYB!eZ)8eW70o}C7uKxdW)hhj8Ql#9l;ru1o!3cq zGZF%x;?i|yGR>3&RhR?WCF8@4yXrJFRZcEIlx;4{oT=C7-`!t?FFLN&{atC-ve5`% z9p~5O2A4R>VM=Qrl=QRA7Y|qVG);^LvJgyTSST}6UNY8rd@u=}KmLGZ7%Q#GjG@aq zI9(~gEZjSvQB|CzkX3RxI#8!HNMR&$!X8UH9H^-s$xN+f5P-QFK $R5x2 zux7=}`HaCbN>!&H+A-L(|CuY?vsy pq9I_v!G!LG?Ue6${hnb(d%i7A0YcHg;GYjfGLj%8Te{)Ga z6zAWr9<~zWRBm@+tn63a+<>!>JD`jL!o+a|@+mvMkF00k1``j|D|E@zwsnA&C2wav z>NVgDK3%sPU_*8GGFWqG6=HLK&e4N}JS>ep^nh^SdySg&sh8xVPat4K$*|t|rVhhR zPuHC&y{HqavK%}uSjP8zbbgcL4NK9*F7qm)rP|IghX>jAZI<%R*Lr81u0}L;pJ9ff z;Y})K&jtqjgX%7q)mJowr(fS!G)Iw<@+?V#w&mBOft~SPKb}Zxy5V0Pb_Q_83xvyP zII%mjp2i&7mj6nD;2YWP7n#fslx;>Pa-KD(=KK;z2&j4#eHT2Nc%0_kG #Ujmw80C7y|tQoMV!J *m9#V ?>xQM6P_GPMmLY}J4sjX^(-9pv z>>h7`(rZ WtMgrUZ3)Cq`8XV>C&CVk!?%LIsv~)!zf^ ^?e6cxdy#DNe4vH zKnVmP!D=A>Y*bJKfe^DLp16o%G}4iAsidb=oW8@sSqs!dWayXElFruXTw;Ur!S%fX z!0l$V3_d_sC_U^PVkK83kqu3*6@s!%bnKP-h3Bye-g}k%-+*F`0d1SD9tM-siv5lg z;adUd`7Dn0 S-rULqNYR<=a=4F5N{7kGU;7a}0RyP5az`zPCyh zw&}<~yUb&9m5q)>U}F#qs)BXYHZ;j>l#{02+rF?xtV525W(6?xSQ(O9jVVV0Pw)vP z13`NLf;htj5HgwP$8`rRIfCZgRS)wWWJ*Pg|F9hVbH@tMy8!!j8$g*VJ%C+@P4F%2 zd45nzlBpYOH2iwCl38*+q0mRSJ>x13WDN+i=i>uTHap)-z2zcx)}~#eU8=nB)v4X~ za-as*A|FuWi`8v>l@#*ko>fPFvm|O^lzW7HZ^3^ExAPVi#D~xaZzDzx#|N7Yw4ss{ z39$Xlu*J%BU3TC@1Vb-_1;Q#Pz5Q>FCpX;iMl@Oy{lqrxA8lUjprsHiTh{39a5gw= zFNg>A=Ps9Vl%lg4t6T=R=(k?n@j5cP5sGG>W)^_}IQ &bjsrnuE z+0=N{gB5+zrb?`RW1QOVh+t9r9$&hIPDYF7B36t}W8GydSmiTDv|~40GPGoO*YU z$p(PJ9a$H9cUJC$)1q4jXD(Jh&wT6-JJ554R75^(@Lm4>dP=)i<5$HmzFT9T=Rv=c z9NPb62em^^jIG_o4OKE5q$M3(Lpgipkzpu?$vy2TjkBc=YC_N8;wmhcuF`Z;s!M@Q`y={xKZ+*aMAXCCDL`FKX zVRd4KcTw6IQF_u(dRKEZ=GG2pt#LU-1mP|d6uyQTJ`dTJhHG&lrj2VdN*PNVX2uw^ zPqq1iVEayIIrTx#)p=<6x9YUc)aLBDL#YU*?jMpsOtn<)P5k4+MKtCFhz8komhr?; z&DC;_)U7-H% nurWNGXGrtY%GfwcI5q{{|$-{(>F z#j6aM9E6gwdvrxdKz$}HtlglH)4Qk2r-`Z z)L0duQ@12!rTb{>e@M5F8l(@dDlaz5ET~Vj9sv31U(>MkkiZdC>)@$Z!(g1Tgd(xG zD_}!Llc%$5vrF>wXOwtU*gn()_tC`rq>k(`PCA{qf24lN&3QYUT4~thh3k!vCTlLL zAm$}9b?>mo#1Mt5fS{=ExbGA_yMI{aURa(&`K+hM7O)q4t;pLbb)xDvcrB)~wX*n@ zX(T%Q=QU5dT3@)Hdy=)k;(|CmDc#!#;uhb7H#&~Tp+LPs !r{mU+*-5_d7XzFNNk>1}Y18F3yJ@*|$~&7Mzup%bn{7P<(cKbO?In zK7g+49crIKbE#N^JiZ3b0^&340o;FH{%7fbHlEK%_cQW*2F}lJ>;DU{d&?HyU$l|S i4ra_8nKx=ooj5J#KCiYB{J&pBtSxOVvds2;`~Lu?ztRi< literal 0 HcmV?d00001 diff --git a/Architecturediagrams/Contextdiagram.drawio.png b/Architecturediagrams/Contextdiagram.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..0c00f7e319d678ff025322ac4c6400e4e2b2aee6 GIT binary patch literal 20732 zcmeHP3piBi8=q`#A?beEC@QPAOw70@ T? zWTd{3LZMJH=Icy0gWm=eYFy}~&%u!eXKfMq8OPjgW`sIlB=;1B(oSNnwP$&AJxCM+ zN(pN$I#R-@deWFIC9H`O27{y1(RdP$$iR6s(NqEpG=b~hG(5?JM8J#sU{o>cDyr%# zY8YEJH6^Se=z=v=(?n}yR2@bAaYO 2wNV3&G8T1fIiG1FMC`YJ%pa7VB&`SSn$R!7+tI zCV(F^f;*W8-D2#?pm~E9Q#A}04TcuZX@m2?F-T%VKx-nfa7591d})rJ+L|6)$Ql+_ zRAVi?y9dozv<^0b!6ebB@Uqp>7&KONf#pXhh+6RkHpv}K2n|UG>t>3Y;eJea90l&E zChFrxW8eu4Q70e|AiA|ms)pcZ=r7h7mOVJ3;=nqDI@t(@Re^6O!8&lXvM_P=)bL&p z9^QlOX6<0 z3pLn~{E?*y9~^Y^CE<|;!yQ>P8ihro!%~17-Dy-R!5uaTxDCf(Kvp1JAl&3Zqrj_! z8z6bU)&pv=86{Gvbqfj4@)Y&e#%PIF0ky9qkcghh%xaoCqAT7wq%*t{rY8; >J5wRMuKwv}0 zLY<*$Im2dw!NP5x;wFJK;$TxG4vh`n{#Vom`oP-$ afaT3s6JOk(rn@UxqsYzU!|!=UYxWgc`_{EF6PKV7 -AEd+-@>-pC(1di)sR%qz%PGCZ$iv kcnwl_gfGrS-iSOC|5o4oycrX#Z{pWE9S 0!=?NmkwV{uZey3~Z`PKE$b6%Za4 z4iFy(NFkxnBF3{`kH#MW*Hu$}Jy5D6BuFfrt0S>nJf35<;TsXe`B%B_m uo?^9z8cd+f8X|AP%O;Q%ht4(<7$lH@LnKhxD0-ehPf-B*6cTE18@T1o zfG|4Ti-NxRzfd+UM&rbM3~@toA4A&SGnGT?8#=EeG!{u+5f}gGQyC1hLfG7gh%++f z$B@d5X%TS6PR#t*u~>8fMGS(EFM$d2ijfifL(gBvT&B>=-@)) 9+i)=;AmPQ-TTNP&rToMaHQmD=e9gAR82%_L@7(=0xAqWL0?~b4% z==d`P{R>Dd4D#<_a32)XVn-mYhS~^<`_Cio$U4;!{YD()qeWUoc4F?amP>H=WkDNk zV-mlQ5^04X@D7GQjI?TM8gSzBpTgRIsWi0N3+rahcCh18jIngQr CIuaJWSEX}=SA?|*u~lTG5Vxt92iL vUk(8BK>ac$YF+3}1JaFM}|; zH1{D^fv`w54p9q|`-$ q5afb=YpBZo zA*+>3$E&OOt~K`}vyC}sII@ DK2Dd6pDdZOFkwgmTPFn$MqET#mc7$qKd zkhb?snPHZ$jzmM)R1g$K;Pw6Ig+qY=net=E3&%9p(Nt;kQ0Yw-yv9cYW;_~YMudqE zJyjfY<$rTW2rA0K)%*8s^@xpq;6=GHg*=-4{WUCP0*7L~#fwx!+a79YRm{*nhXb^S zfz}*4AFkO!yClO!JLv46soISRx^SEqVT7o uq+CsBzYeG*Z2RTlInFL)=PzyOpG9C8TYZ5!e1>Z5(_ z1AqJL%^30yoCRhJ;41+P7JkbbCJYEg`vlz3UhSAdADx?wHm0$5Q{EZ4K|EDe10PI? zZ&_;&L;2f4H?nb~iWY5oBYQXSKF;t^;yX8@<^2_sExt=LCXT~i``^HO%!s^g=xu!j zeE)g8A9|H{i2si$dVREb4}YN}mO2W*&`^c9!vU;&fG?oH4_;WUQN>a5!zT;^sH9Or zO#pOf(rHvC2nM4{2cx aDDsudzdqePh#?V)a zqK~Ea 4z7w-+_;%zxa$>+bIGk1g-eYp~C%Js1}kr&zDF_(IUDz<$9|>!zy9%&x|S ztozQKYC?E;cvokswUdR#0gC+i)7INQXLzme11;XAKW*rGa_W#HlbNj7b FOq{CKn`u)n!!b9YaB{n5e6v`#aWj&u`i+qP>9 z0()@%kD^?E;xW3bIh9*ncMv)r-#+=A*c&V>k?*kWP@M~Q^`uq)ollP0l$~`rsyFvx z4YS}$)pjtz+2=3HUDFI+4U}fr#`pO*r<6B!RnpShI4*aW1oI|zMertMpSu=!IQiO< z%V$-lQYTCa=S?_%>$5nCI=ctI 0v%~|RFGucwrdfxhj_afz2)8G zBjrsM;(xXsyuq2~X{MIH41M$!-g0tAM15p(&U24jCvXD|7nNp5a@85f?WZ!1Ps*C| z!{OwdBaz7_J-$=Jc}mCk@RYI>c6$nV9_BGIF=ZtsYPU~WzN}Yd_IEYgyi$n$c|KU5 z+t*ESw-t#?1S_Tm%9|`EhAAl$!`d1ZzR&gwGnWz8J%>UYuUp*~cnRT%(h`}1@@d*$dHe2sFArZ2bBljILxQTi_4|aDor`6uC zNG4jqSEk>uxPUW0?*HUB#llxt_MDy?tvXIHGpeH{z16X2d6rX%b0;v?;=zX#cCJI| z>}@c*R6Kdn=V~3@(e*F4UQ+*II?! hV2gm@KhuiRA=pbLe8 zr&Y#Q4apNCa^m)a4hr{D?!BaXl&g5kO>vSKCs={ @ky}HQ6sO`3|$T$plqtw;q !ZpBG~2iDl-)cF!ul9w>; z^C>pQV1&gd_Q#ydkGX6*SKCqs_>9c9uUaL)anM-9SNzEkr4v7H<@SpQt1S~PtY=6s zOc*y#!22>MB4UbDqTAlipovSXg1*!C$u`nlnKeGLl$K^`*8m>7NE+W8D5(%%ON~BT z1jdY+lmGnX^fgvl)fk5upp#WABOmoE1@i*a2}!GzgL%F#3WePkC>`>><{Jm*oJ&c$ z>+kPRxxQ-x->l`?v!vdR1}7$yDO0L_j02vSA96T3L{;aQB2mVA*UkKSHOc-jymW&G zGgKTe=10iuYGxFM$fssz>N#zq(P*iqE?I%qnzR~9*2^xZt{N<{$lk`rMrO x$^ntF*OG zNOGSG%$=@o_e*sz`c`9kr9A(YD{(NzJ#Pw`OrD=uSw_Ds_mvN{yj{DvDk>@!K?Sp7 z%OX;i=jPKL0tETf8e3XYRh&{MyS6-znrX0b lTr&zhPpHdm${xU;W) z4N7ONO3?{5en?1&2`PuG5X}2w_F aPbZm`1NcGNojY#w^78CQ z1+%0Z!JlMcVA v|;Eh znx$8K8 um{fxr{W1_7(d^+ofNIL-Gp2EOy_cudHP)#aSu z(OF_PFB$kYK2Lh`@s+On8AS^NdlcR0lyL<4hYw!Ac5Mwi1)^xW+_nd*#bMf^71pu( z-ce}h0uO1wjGxRDBz5@a?SQ{|C~vxF$Z4sHcGl0$=C^{u(YiacZ_Z?ww{_>{=GM*7 z E8j^B%Cci9iF?VQF4;k8w??RRyoD{r?@o+KBzz`>WpsXVUYgwf#_*U!0q z=d?xgi=6JvwruIH$0unX(?c$2M_Ketmuj5E>&RM|r7n@My10bLZ?KITEY)pptS>!X zI8SOy?Qe$1=?U|!axU!7btViB^e(=-cei@`Nxh&~QMDS2`z|n5Tr#wEpBBd&7-W!5 zmt~(<_b->TE=m*>9QcA$-!owvHoK1>p 2RFFI#qWj{Pa7va2Yu_R96xF+_uSUYjGkWz8P3>Zoq<(Nyfdq@Kg+(P zW)$3cbj#Hx_jK-2MIPSfFtanD<5ZqS9oJz_PLb=?T#Mg+$)C5 OvRZzx(SJv#Ra}nsoM*`ByjQKICN;nAh!Gz_2>HCNOQEwUU|ZS2t+&bcgx)9St#@ zrW #uMuizt`L59fexKXT7r zNagmfDj|4R&Eki})*e=7I?U%3wWG=WDc$XP3yJBE_s?3M6oYBHQoFrl1N+Q;G);D) zJ_T^ad6nE)Ic`K=bPV%bql10iGrA4o=uP!$%t3~R{w>Ma15v;97T!r*FzFE|Pc>k* z>0sO)`>0f(yh%|%w(r~+DKKS()HfuIe@NxI8V_DCHj&-)<#OU++@_4s2*%^JMFvx) zwoEzfeyKQ|92Qk^iWuGWnIf7@R`xu@D5D bunC&Z*#vlp7ibVcEi~Mo5 zzN=|Dr>DiB#tAIHAAcORGjWna{F96aS?i~LiY=eQ>nDcs|0Y?pZ6AN97jQN+v-(PU zI+Xv {%o7&%98-$&<`@*aK+E-`K zox5Gbtq+$ts&jE7pw8P480H4FT+SN=)q%QWmDKdxfrGt7_HBvF0Xpi8*;V*^di<9S zAX|4&t72HNV{e{!P-Q8Hnt{yhR_k|7-%jAO*<8WQnP0T(T`r$_jXiTGZx@E&(p$wW zuIO*gD$e{VI4x@5JP%C)VeaGLU}cGDp0RPy(=)anXM!Z^TpbOI`dSZ5%7IKL^fcxO zC>}gLW%d&tB#-jP3)blav^umPI$Lp^fMx&H;$A?R_5JZup&)O d0&;N&%d7Lmx9E zaW$|$iT>-?4arn$(GrrE*SB}1sCGqAHpvjIJDvjin(vrqNy24ZehiHH@j7Mw2lfn? z3~q^Cf{S-Uaco+NE@>+H<`Jb-&yqy}55tt3fSnh!i`t~p>*9< _YvK{1Z9D2C7sm%*;!z7UY9&=`d7N?}9 zI$B#72So(UnADTMWRgO|5{0{cDyJSzPWLb~3vI5=GDxqQ{7P=^q|JK@OSp&Tajvwq zP%D!N2PVYvPy1xVZ@t2L8pKX(i@x9 #60=k;^O r7n+qYkr zu-fHV&_&*+!C*<96lH0KmmiT-5QEK<&MT}QuzFd|sSUrUQ$J_zrOw-}JgxiD7HjOo z)(KX`Jw8*#bV+A>_uOo`UB!%e!P1Idm@6xL@*)4nl5Sr6pk`G+qxg)TL!?b%z^xeU z03BmZ=J#hGt!T}9r62J93>Phb$ADASXnmGriq|)p0OKkWBNpg+LCHh=677M@o&(7h z^YvuV<4*Oj6R=#{!zaq^D4tg ;SW)hT_pIO_|6W!ii@JE%_3 zJ|nmt((F? PMl2IK( zWRw5vgHzpC*Zuw8_x-)^@9(<)->b)UmGe38&wIYc^Ywha-ma;hl;1{1M@B$Euub8( zj5+}UN*4ZSCD{T`C^`+r;U7XLb$Ka*{O5Z<5fF$JI?HN1+qjupSYrv;Fw*NkvGMbo z+c`P2VPx3&`Hk%DxlJsL%p8quoVabV&hQAnx3M#^Ftxy%theFk $yRJl4_4!p?SM*#g}B+?e$*oZaoQ>rYLv=Pit3K%}`ntlMe*@kTo* zV (;R!G7?wVPx5OkHO2xe;DbFy@wCBMzD^xGf{ fgkwl{pAHg58cM)u~)b|zSB=-9+ z2n)dWA`3Bd#E-KvEb>6Z!UMmQwTVMB7Yh^of;SpE+u2z=Ti9>x!p1{mJ6l_<@rFQb zJTr21M5JJCfg6uZ?W{LexA6ek&%bGbJka=MOOdBq7ADT->up8&h1XYsJU@=LFf+%G z%qMhs{Tmx2eB+IkIGG!PP_DoK%c-pIBYrm>?d+hxpAPNkuknp++@!JA$Y$gBabp~i z!GHeU@4MmnU90{l-PvmEVuYPfYbr|{bBTy(N~>6y9K(y(c_V9=jV;%-GqHmOfDW$j znUk|SUX&f}Tx?C&tO26BuI3ibSPgq4&;pE%D@YnVGk3PJhEHG}K(jYA$r+0mJpA$e zSkKxL|LaZtv9 C#%cf8^GD3>Z-nA^PXfkW+pr%eamon{#@fT5&HyBK%>=pFSRXTXwgZbI z1=h;h0<=TP=p5Es)y~PndEIuMvvYQ~v-zpPF>4Dm#Hcyj{pPIfT%4^fY_Zbc^%Xha zjrl<5|G5Jcz@Nj$0Sf(ke)twYA0NKiALsNo?EX)B^vlU%ZB33L#t#m_*xJa+$-)>m z`6q?>TkTqZ9c%K7CH$W&&riyM*Pov^7yrx=Yi;CgasF>D@$c>Ue=Yy(`ujtRRqZSQ zBYan30fCJp-;e-4{Ac_~PIfMi#@LOw{xRkJCx`rQHSj|^8#$U`o&SX)F#t`#DttFo z|Mkvnv|cj~|6R*}%!X|E^`E5hn6WX|2~Z8MGXNwPGjsUq9O8g~$Fd-@wq`>9RxFJ+ zjD|5dAq2pDH#c}|Vq;-qf_MliN34^Dhtat;Z-E#Pd*r0o?5m&@o1hFl`MV}%11W60 z49zx#!rthIxc{!zT+_S%dh>pW-uH9)E`40Q-26g98@ORZ0`WfaKP>-vVY4$eb;9HA z|K9K57xV9yvo%@#I}isi)jz=G&l|q>Egru9?HBl`Kj4s|2v*iw*WK31T*|^l=CG2Q zuJXBcq4*8#UGs)N_l95iU!WHJ2W%PNU!WG*hSO?h0&0h)PdGU{7^~Tf2=iIlp62@1 z8UGAwc{yb4jI9s@$P0kS*$9A-BZQEMYxxOh{jE3t17KY~-oJH}0(cPglRFo{`|h9p zIYwmTMZCrNU&Xq=dqBVXDLFtyR&4x2Mm7jEwLRyA{PWA9{5Qv7 Y=OPNgZ;tNT;5~S`1wl8~KI*J}#0Y eY1HYlxes_~a)@9`< zS^8CY{wZ<>>t^AMSW<-NM1Ed3qiaSKKK-zv$cOJH6h8dx7IfWo{C5`gAF#A*PX1pI zxIdJo#r($73iAC1;{N+B?QeOi@9-P17=Kzzi{HDS)I-({YwY5TB-nlz`28s@?V1tz z7X<%@rRC!j+z4F$Pubf4C2C0B5_3-Fyv}JiYiW$ViMg<)vxVlmnf?tm^miz~HDvgM zqWUY}3EKOAI^TKT!u7nHl8LIBj`T@;1tWPu1xq)sHC_=C{6Dg6-(y_q--~hocr*|K zeGsk+kNAIwZV<$C3qQv~7~$Xe$p2Lu=ywm}SDp^C&fNA$f|tX|+0n(=*~Jn2D>e5= zWPvbvHV%I*_}K3!-1K{=f`5ib5&!QG g4!cz(l={t*v>?>DgUJM;OcJA_}U zxb@Pf-}0kE)=-loWnyt2s8ciKM@_7aJ)~`+I_DQIb-gVlj(%$Xr#MzYyye=^t?w-N zANg3_>`er?Tx1n2t j;n# zessk`war?&`meh72e1D6`!?iXz$_bR0d5KKV>YU+Hvj`3qWxvKkzDQXZu+mW$*;on zd)btK*>HnD<>iA56F;Y{g?^awf5vp<6F0ov>nU%1?q(y8^P{VuGdJtY`$s_b&smz^ zwc{IF`+vjU^ZzDp`(CY&H@^RVd;h(Z_dEXo4e9l#wf7r0bbbmQ*KTO=ZluG(tee6O zDEP-@jjiD|vNief!4V5gnk{ew(A>%1&ejQ>!7tRouUP&cVhsM22>)Nrg8q~Y5*FD= zE8{)KM!fWY%5(f%b3+?-#>g$j^~+ML#Trrs1WW`9GRHLC3_ialkD`8j^XV6LJ*qk_ zq9V0+rVEsHCbBw0Z3Iv3Pw$mWJw|l>%BWP`WD}+2&IiU!bvt=Erbsy0Np@|yAvjMG zuCGe$X)S6m87B2U?(QyowFWt63d1X6s}Cx_3d}u!Q}Nd2e(vIh)<(XTH~IOCn$N!4 z<>1aIJC41+XB ed6%(Xf^;`Q6`HLcO*QSl8 zzI6_Srh&Ui@gJcb-}iRB8jp4%Z?ARXh&q(aw~IouE?!brHXvTqy|848a~FJhRl`>m zoym^f=PS9*PvhiaS%-rHTQ;Le%9$lO9Mdzi_M^6wQ3UQ86UYgcyu2CaHSQT7>T5$N zb=}6ONuIz@1fDrqs?(rI?s`5!#xsKl&(AYZ%QLN@TF~jWVOjf7B#9JEXg)e*c!HD$ zI W9zhRiO@I*1A-g&{|IbAlwFAVV?|z*ZzctAxs^ z5CW6~IYr=mnsiYjiUw%6Yby!Uy9nquy)QMNM1&ps$a|Q@joMAigvNRjyznHlh6PyT z)P+zakGLc`0?$NEQAqj@W1hfXif}^n!rm+alr0Ib#*mzZnj#T}2)881IaVfLUqP6n zpe~sl0U 2PV{#KDQ#Bgb_TjwA6S`+;k|39#CVZo76mzdRVPuxGlM z-j5%?ZSrm5q>yA1B9v0IjzV7|Kp7EA?KDOa66sMgp)1 Ct<3a+HDM?kcfun-8PzZgu+CzoQ`S9S!^hh zJ+M)Hlz-=JTEF4mcbje941*qrK~>GvP7&!*oy}+{*_&2FVsge;HR|)X%o!4GY9_SK zaJoGRlnw|KhU4)*-#SuQX&T{QEB)(C5$RpCZa)-m{quK? dZH(f2%5nU%CDz@AADyB+^xF2n z3jsrr2Zo?KKkYpU2Ube$X()r!fN@v8zU5HEb<4gg_Zc#B2al0lt;At@&LCB^Y?$%R zNf6;7*VUItS~pJx?3gb3wz8Bv`?>cZsY3OIxzoL6c3S$C&T0p>@->y?1=P-zTB|V} zaaOhIDOS6A)b+Gkl6wXn#xyv|oqwNVUy gr^?7Y18l!Mwe z3yZl0H93njqcIoyaUHoGw-q9t?S>K_leM~S+s!YN>@?bW$MW0q!eV)W=kP(?Ti5 P;{fxLcL>8iB)Dyxl(y!+0aa;#EOFJqX1fiEPu>lO3TaJ=rcCGeoSka zn48&tbY7g)=q2|;WxLJblaPv4o_bY-`qG%fv60#1DYGO@s=)*p*~c7T_7bTdP&HR+ z3#2~i{E_te`&jk{>+5j}d_{5#4}$mDJqWuL; m` z3pq9g8h5$s3$b<)?FDLSa)PG!{8NtOik&~HpHfpxVZ99!qR<-A*xYh8PUisWrAw(% z+s$(VBp-kYy>!&~6$^zdlc)x|Pla_=s7RpD#MFQit@Jv)fR-xIWHz%@`I-9VLvf8S zW8!qk#$6&PjHCNab~j&&K5I|PW2f-$06V(z(95C5$c}BoZ*IjbWvC=4k*lfK9D005 zr-)rxQH~>!A16XX=mW;~+bkDXv#(^$aM9U!J5i*}h5d5h4%VmV $lzrX?7Lzs#&7jwupR&p*@=w<1v=ZaT}|D9&7D za@v|BqFVW7X=akg39rvqhOb< SCVJkkn+xThdsVmzV zUe+rZJZ?cNaPVV~)B7)7ZMkemDot5FwB+*4BR$0~dlQNz%FtI;)7$C!RY@FC%aqQ` zIiV8_TdAc8{FK1|@^`!ypz&KqeE1en@>}SXt7_jdhWdJN6mse9J z(t~)fqQ|M7-fs;2U}4vX;$41)5cf7UJ!=G??hig1wf73MujE_sxs@Sq#3+*6(%{TP zy>HQwxE++_m@2ih*oEqYm#aqA=`KlDLTvj9x5M%x0V)76Rq%Fjy9dDSHYpB(&rgH? z eeqP+0=MBd`h=$}bShAHN3kV`DfbNHGax3|Y0l !+ZNDyK29k60~?JbJO9;Zrs;bDq2f(6Iwp2b3O&) ziyv8L>WLY%E)ws^!L*7}@qv6Wxxj|CyO2^#)p-%d?Tp8mg)R<7syGuw+;Z-*$js(5 zev%c3F{|vC)CJ)&fGw{YJ53iLS%{+ae|~gAbY|cR ?T{VO;7 sCV142pwTEv=yIWw`sghKs#gpHq=l+B2=z!KM*x4)e2|$IqPJ_bjt>5 zpM|CEoJ1HJ4ZD}oN@VtGVV$4<>h}NCCY)VLt-&_a2wK19J*A_Qty^mS>E=BfiHSOM z3e;Y(8lvNR@zL7|6KH2ZRdX66_gggx+4N-9crAHcv3%8f^bp-8-wzN$v>uHeS>QQ4 zomykn#a#lCugmD2vYZR!74pxLB@7W&R?wysw2ZRsExn^#ZlBUq<8@#6-noG7%8o5j zoEq)IHD9*P3^J~2U&;0?QVQsE{qmT0v=Fqupr_2P;HZ61u| R_jWhjZ{jSc>gXj7fS5LV^+I9%TUB+JXmEC4f$(9YG z$ c8n%9HMJ$sC>7H^b;ZMGY57q=*Z!t^ zcKPThExC#@+#VyDz$v%`*TE4%U=rP9NiG}Ew_nk`Fh&8@4Ft^{uA2(?trv7A+)jdR zyN7t!{ppfKO$X18rgCE>rXu3@0cCLvsEQXU4K3)+W}y!-vID#KX`G%P9q>_{_n3R@ zI b=r^u{T;X>e(P=?&*EGreYl(~SpJ>7I9Ld(`2Hyn3L*5!k{$>&LDIjdjyL{@)x zM`K<%QT)3RQz}jG*`nl6*gK}r; ;WDVwj$;$%eCnwZ z-D%=fdMJ7LLUNRuX|jK^RFR*>!&W&lPAWp8F<9#uz0($=JTg`XwF0iYL>E L`~Wq;Yj0kiQ sTb~en 9d(9Z|2NS^cUn;O`Xus@KhGh;NjtHO_cwp-xaK7 zvtk&S+&XxzbYD0Y&_VQt Y z9dE}A+Zk|Y5hXh^ZWpZAVbL(HdFnYteu^^CKWsOtgalWAo@Tb9dHVceag!`@6bTwh z^axPc>)nb9@~EL;-FN$iQ;UD=0n9%3DhZBVnw@z%X*oGLmWLcjoxG&fcr_KgmS#q^ z(lQ^kYO i-a9yWKdw5FK ph*&&$006^}&LwRPNg4DUU0u zlbNlzt)~?*1Fx&xi~5voYPb!_eR`B?OruM{@TOhf&X6Oq&s3b+bT96}1SXj#a@%Xi zy-s75E~8%ywddzOG0OE*{)%SmG|A#lCKMXVMCy>3I^j;NR&7n*P?Pu}*~ehzsn7D2 zo_oeuj!d^;It;%}(K7gR-yh>I@miXVFb$LuY#KWe@4@zb35_5yT-Ee*MUCk!a-j6o zfYOt*J{chCwRy-}g3?!fdGaCMl@lWIVi!u2{5Y`-Eod6-<@6exdtbhZOqg>O*@3N7 z6}vF2Irub8>&}_7QZ;N7uw`g47wT^gYi=W~a8I$;j!ro6t#x%dY;k@tOz_0TE!(~Z zx9v7d+{uaF=jmyjPNbr9Ky-C^y5!5J%;bDK^kMfY6PK9|t%r~o+YJC0dppe{qZb7z zwA0o9TmR~cp;ue STcKPlF=& rP @37lEo*PH4WfX{gp` z{vl&~5KqnVU4e2fZ6qQr5MyNIW|^NRGVob(5j*P8Yg3jDDT4dYO{oHLtT{8=jA~oG z#+?>d3aV%0y_xR3p)mr7+;;Lo8^kJ?z ffFiWG#SH$S78EmP*!X#GFVEl(OQ5Vmluds#SD4c)QFFiRHVMGo5FG zY%wWW<~db%TbCLKr4fiQ@sX=QMPfx$-=*W!;`83AkCX;5Z~+Y5Uz3jAPAa t04}Ly3xOX;phYKJE)UWlo3cM&iDr zehZfesKTu*3GT^m?@3pd3polF4cgNZo1Ypheu?~$qVKaZgM$$1>-9@Q`@(g=@SEOG zy1bvwzL~4+BXM|>nEiXV8;)vWgH<(AYJvTXtMl^JUv$R>yaz*s7p0CJrD&*vsBv1F zz}JzqA&q5-WzLZ?kxeoB(fJ;AZrr__Z!Y?um^o8sdo#lKAbkN(^;h*BtmcqmUn?Dm zIwm>p#o~87THmC|HnBjR2j|dPKU|nP|13dR1#x!7EbiuqKwj;U)Y$n|wF|^VeQtx> z7_JUIZvf>FtA3&egJ?aeN2M(yj;DI{+mhwN)bRGwqyunVs$hfNB s<976(EB%0uzdo_jp#y7Nw&_krAXG}Iz) fRNJgYa)u%|h+d7|P&lE&Lgmsd+c`Q`5ei-i*wArjvU{_Y{lFLpBxm+tKY z2M#zh;a;Rjx1=ZQ>FLqBj8ZFqB7OfgQiYmZ`>rH$+LI9a%;LwIolS?(`@)nojBEJ`KeFvy`cxPkKNUH6azHQN0hI~h3&mFJJy}H_rln{sFElg;3a*4 zLY0^1#Zj_k!Suo>A%mzuoEpSknbnY%TFW&a kzYa8?vqrgVp;4 z 1E96I11;-wE +{I1(GcVz!cmqlj3mrl^qm0TRoT}x2jt5!P!<3A#2zuf7y}Q5 zR*J?gy6z*?JVb#zMLg&4E_RmHq$6(i^48tzE&Hm735h6S2iSa{bG}8-KeO{rGrLN| zV~_`F*bk;GSuW>Ly`?s<=<~booXO0u7>R#`tG~8W^448QE4BGa?nLFDzVnjtPBh4r zn7P|N)j&x=QkA3m_rE?FCFd@`6~!z9yv!l+5{KTa7c-(HRu@`3AY};hyFX=GiYc(J z*y5GusZ%$4?ixu)okQ@+AyC0Xx72S-pyu8 yX$bn1V>0O2p%9Rt@oW&jTM* zuIzoV*{_hKC0 T_z<^M8!gqv1^+fgb^P@*78n?}kw8UK`MPaFT z37ChAGa6OpjU{gNiv;7kHL!)ep>KNy=O9 kIUw7${j2pUESIJ Ok4APifHg8Ln&GA|Nc9ki-+&8!pG~r_i9C_KvDsfE$zdTUs!p^~BE%Jsz z8dj1 5^k|!p#npql@6?+BX zqTjo{=KshF-l;h*NqL%F(9eFyKiHvltQ-)`ru;^Rco -r-=?t=ieV!2PX1MMsB8Z zLPjs;cG;Jvq#V;9T6q*N1Xa{2-W>Y$Zb~6Rs-E+C=(U6B?wqnaj)MZX^M;5vEab!K z`G`@}^F*Xu<~U{2nwGq4o&a7yBlh@&sb&TQPY-2N3W%G-$@7V}yX$*=N?#Nq<%ncg zerbp)!qo4kcPF{+St;|N2`R9EKhD}m9fyvG=+GSYsr6oQKAdrq^2qJJ(XN6n!+yZw z-|Qgg?YL^&UsL^UwSKPYaP7h~yBsY8ciGQ<)n|NItL4M?dW &G4GdQxZRD&0Vj$M?piL9e4{`fLI2vOp1@lk9p5$BuJ1cPI$ =nhK7MmZY~Tg+s!%=mYoUASi{Qd@oAiQ* zQ9Opi7$9S)1caWCSUu5RR9`&N6tx;Z8@wAMccC%UwWVu1AXREcs2NRb;FgkKtFt}I zqdl|lacIcdierQJ9AsgbS22#k* 6%uscuzg>vde5lw^&xhV)_L9f+vRaMpR+Flc zr8wSwP0IsD-j|0)Gx`RS?@Wpa)oUzjELO(u79Xu;({S`h47$f)3DI<~?R_q`l2k|+ zu!U! W_6h&%39%rBx;+`39J~5B|=)Lyfyg!UiV~Wkoeww_OW*uE mh@)zx0v_V$2Fb%=F5Q&R9cP4s_lNdLv+&DK< g_?B z?n0~wrxxlZpuSOqO<8;>PMQWKj;68&;c~*m<$0_t)Oz9=MRa|^m6+BCKJ_1t%5k$V zM92Em) Z? zvk+&X+kS)do4#&mj&dyTvCpsXNsG<2YhcBA_Dk2f`n6n2?TJ i_v{(X9+mE zH&676+K%*hUEIXd&ojPgT`aV8$fU^Hep6|8GP;j|Ua#}IM=YBF21B8z9yxL4VKS*H zW#AOo&dof*lvOxg@kl3hkhd-7uBa5xAM?j2_l$-uUj5wU?Y#IduDUnnoL<{f8j zq%=orn;5WZE_YQ-q7{YSHH%!=Nn32c|N5ShsquroWp5mV_F5L^=~#1+byk;#bh3Yq zS52@>bEygWHdP`eK@}jRn;=2w55j+@DDG|W86jO-*X{~HeH}5i%h+m_2q=nv#1bB- zs!6LgSup<2%bLuqI)4hc=*`D?rXY7~O_(Gls??i3!aS(?gD4=tK10@`Mqm%lS8%p7 z__YJt5+5a#QnP%*O07@w$_yUy_D9 zl0$OEQ`d?C;Sr#roE2(+0)3yRz?YJAL?*4#W7JUzc~hVWF98_d2j5CEIj_-5fs8 z4}TaM&rgmIRNG0k2Qo;9+jTUlp~RYlbrRSP+=?t^=uq_bDhkP4-yjxPOmHAVUOnL_ z-0!IYG1rsCH?#h*;C6^=G$nZYpwgM-w(h&e{mGiHZyc`lx!LSJ6@??yI83At$nb=k znJP7sq}%SNQ)HT*ne44wJ^6s#0WH6q#6%7VkhuH|m~=Rs-?58ZK8=WfeIc!5DP$wd z1f|j(l#IkIKx==Z{u`k6^>jr1zHnxM*nvkb<{;&o4r|y--mhVL*tUG&vPe+IA)+dX zaNWD_2#~?bM7Wv42tEOW(&q*tmX$UvjRuLVHo 3;X(T0b8 z nJCxr(T)Vj!uH)~^1G^hGk?zX2(A|LOda68>2B=iH@O;r z)HUDo^ ohwP_K#9d!<9m@YK}D;4DUqWGJVN7qCzdsYDV4C3gKa zor@DaC5l~kP=T5QnFE*764eBpDDP&w@C4;2M*3PBO)g25xca$QkWM}!FX5&`USTf^ zs2?D$dE0|#p_f@xN9XtyRYrPk(4xY|?QRW{`(NXK;!yu_- zAA7_lrxI#szbdsr-D+MxOY+MI9gYgBV$ZiN=xq!~G+PhoJGaSNLZqGp<+3@2h3dpR zsO(Ga`txtMK>2TyK+uf|f5s{i;%45N@t%_0?Oq6u91h)$Vb_v(S8*$Cxg`5)OPoS4 z2)}K#a#MrwAlCGrZN)H+4f|(-laz06>qGT$TmHz>!X8$o_(eL#!5%>9EBBAJY~LfI zYCNK1+A@SS-89^PN4MlicHY^BNWOipxM-oK5eH0yDQ^F&EilD>{I?lSojPSXH~#i; z@7*8(m|h=W>=R@6KVPpSG01FGEgt%~WwBzK3U^+aRMvLR@PL)X**bz5B;9Y9Gjdol zdyF~r;Hh3EHAvZY0DN;KWScjzDAv0@?7yE@vPghsq8pNJ{KuYNVysY&XEJKqdYPG1 z(f`JB*QGsFnk{)ZJgZ-;qO0yIazq5x93tLQ%boJ1B|_oj^)943nCzM9X7E_mrkxF! zA}7amUno8ZjH`}NrPR|EAUxS(>BL+As@UjB@NUcH`7bA=u9NPa5-YOawe_;mD|?;# z;g@HZ()(T}Q--sVDEKt-*F?n>1PfYqemr}S@EOtm>@)V98n_!1V(*zhe8Xwg#wXm1 za%yP)s=*hk7Gr$#o8L*DVNzMnQHq${={9-BPhoGGTVC+^EGWh#NWIlKq}rR5de%I= zw&tNCi(^Ve`kV8gd$Q9NV{!rm$-L^L$g?UY!+?z8(k o zp^PiUo*wce-mA)gaL;*OasFJafjVetbjMx6e)8GuxBxyEPR;1JxJZ6~mz4=HGjANL z+k1%&FjmxgVNv^zbrGF);4@||N1rj@6E{a>7Gz?o_?(l+f%8e*q0O1|Pq{ItSkTyv z+|NQ^ffRY=cU(xLnUaWy$eOghw19oNT8b8 triihEV&=eJyDr4D>h z#QKtEq38L{qfSQby8?$s3m=(8$4uE!hGEddz3*(I8>RwMJ!eQKR{2+HF2pTd*P+K; zgk>%?k%jTxI|9D-+muU}ex~=AAj6Nltv(G-Drrq>7kQeRCgG?8S@jgP_W-^N!FKmZ zsd))C^)BvCeFLS~%yRN3eiF+AJC0DibsG#> >~JQ0p1=jQch$@a zuF!h9$z{b37uoOPa9KE1)po?qXgha(fb?~kOaXDswh*7hX0v)MKNaik6$n*CEixKJ zVzK l;=&31tv mBadzO77+Zhh1 2YH$ys0eXP)i;wf2f2m5wY&O=5<1?XGa*PqM!LwBG^ zE)g}&+;gO# 6AaXFh>~}F|ldC6%%7-HNw5^Z!z)N0!*;Ty#Xy# z*CFcVtEJ@P1IlBL opc>$4GhtU0T@au2_9jxhx+nI$3+z0fqT#d z1fv0^_BlzrBMg0~#`bq>dO?-bKB%JFO@rX1Q(%8*wvoH *obn8Ue~tA|p4y@&uPop-ewlJS|EbSSC;0vt2z?00na}&qbsG zI{3Uwzv;dBX>ofIlJF9~9J$&G9CINTldIo2fT{?c;m$i}%;+z6USNYQ%sHASEH~bB zpmleI*_O?Ql%Y_?lrfZ20DzLf&wYC2)BR(Lyp}I+5i*guft#L6r607qq!a|X$YzhC z?ryW>I|!e a)e%GO$Byb<8uZ?)OZ~ac zJhgf}aR^&KK^wlB @hcf^IqpG zy?&t9TrM$l*`oGk}kq5>Vi$?^Q>_0!E=K ac)5RT&h!H(3CaTe%B2CQZ zC!cgp7>GTur7fh4Q#AleaN&h6qn&Sp!=hOHWNcC9O_&LC?s|p!>qm2%GjHDBzF;u5 zm(!}=f3r(ce|yoX+|!Fy>`a?SEv!g+J3|$XjD7;A+GJMpHz=|o%_GB+b0I2fe!G;~ zHG8c1q5h=QcS=E?wU9AAVy%=Us soDtIijXJbPA`6i^3%TH3*Auq!r?kKef@C!So+5k8&<7nalSO)+ z>4*G4`z2DUc3;9x{OykMxQjsatD4yCp$g1vd!lQvpK_er(a|rmJB0_l+>s%ohat;H zMKv_Wl+^fuc1dE^;EB8b8mQY4m0Ief8YW9rPWR47Ne496FvsnVqCaZjK70d-G)(o8 z4K19-K>4a1y;Z#nP#nGh>95fhallQRj*`r*SXI^!JYPRyitMsW#boPsSi4_onyXx| zQjv<#K?PGEz8KIrO= a**BEyljTd{==WwM-2o*jxnDkEra4RA z$uEvBe$~-$Hp{p-u!L@WsXckw@3HrylK8&;!tC387K77^w6EOYRx;gXc;T~P2|%HF z@=TevoCJw1&E<|S%%rlN=FJB7_NTMP_J6o^lKksfw?==V(euQ^C(AB2nLzx4JCL8^RR9=L*Gtq+!bU6BlZYH-O4b&IEXr5qqcDKb`T()`0jTGpdi5(q z!EpY2$1(>X?V(5$nc-gi3^%W(IfD-zJa{UGTR+j3{KlN(dXv iNj~4)d3vN--at-mXJB5)x%K <&I^Ur4J?w2Uq7W8cz%)Xfbe9ZNB-g)NQNQP z(A=1YqTkX)t)UpC;}@wc5Z4!Db6f2bWN(m0svC{Y_(AnRHdJ !kL=#`_3Hdx=+ zj~n}1MN>Z8V|By2CP~C0wd?b3hfh$xjPw9lAGtkUXXS^Ot)m95Nn&Saa2?H~r7z2! zH`c?tv7YL>4CRD&1YkmD!+T-4uPkOu#)iC6u5UhM^bbJ^8`oMaE*C
(*TeeS26qQ-PDFe&~0?7;0G~4Hq=Vv&N`1*d@z0KE7uEE>&PbYu5S`k5vuSK zY-2%oiB*?rr|;!n*u-=WG=!zfkYLG{3xQ0CZo9s|>*t>I45hf#k=En_h~dxKJ!(%g zkx~=8>vj+_Z(J{m%v3t6+?@o$c%+66gpi=2T;zlfM+7eROfRFDhh_+!;0Xw?@}8fS z0pwafy%(68WA7#h9^!Ix^VOktMGLUVY>GnhJ~nXc=qt?G@t1BwoSp*+BO9oM97z3U zZD%+#WLfP#ZQ21Dj*c=r!xHZmkB)Rj+7id%6D3X`o=5iWPe3;>oXf~c>`5f|vnI8M zau#Bih3Yv#Jx9-kWR`S-W^?Y4H7(5o!ZOF=RfZrc;!<)>&H= T!AtI6oD`ud zj*00-fuY1q0FUP}vB|nk I3z*)w&*jjMMn;*K8Bsk3Pzi`_0eppvXW!fzy>w2LcQDN@T#MU597&@a#7I4mFO z0T&d!*6S<~12jW?63IBjG_fgJrAz3z@M5 9!vEbL{`b}Z1Pl2b*UIW&PNFI2?&8v|uCQ5hfQ>->jK2>$7SA-S4(3w_D?Dv&? zEqM!-V>qz4Dn8h3Biy>Zy$Dsch`j|m53y973oFy_F79}LNwOOGKGkDe>|zy=vW#4P zK?q6c47D6y6Bqh5;7Vyok#^G*z-q*>KH9LFL^z5psAP1lGAJ~;hD4^5Qnxq|wam)$ zQ*TND8a2xSD*Yd^-L-vtq$5*>5gdv89!jJH08tVg9SfUJvZ^LO12Jrp5^ApBr`F?Z zo4gC}5#Yg%58OECxuHxp>&isn=RvZSUPuXUY9E)NxkigBS+_RcQlRIEFCxNm+J7$T z%CYlV>c#DsSWplP8~UuXHdtPW>-SE`#@^o7>i^<_@I#Q0n-PsKGXsthSz0H4X(uRN z1IVZxuN?jQEfoNB)g?-iN3QEOXV?CX3#1%sl6!rMp)zTOgTh^im50cG-Ek$8;Kw3a zBMt3pS4wrOJzOrSi?qwH_fgKi(Z^Me7u6SBSI&M;hT^fEitp`_>j>a42IDr)iYc|O z{vz=V__tT)V5_cb(_LADU*duImF9K70+&%q8ZM8*_4d(_uKwi_VPlT#%z7KX$p}A{ zSRzpK4AV96L0dB!5PKqh*UxYokqag{zb}JNbGr Tzz-D>u4AuLl4E9P3Vg&yiq!OUHvoDhe)gt*Na0*a7mHl5DiT+ kgmk?6I?ueq2;z0$xrF(zF_I8(jl3Ii@<#{9SZ|Sl3Lf z^2W*t71t^{j6TA#C-l_%)GofKt<73(K1jdb>-7y7!9-D12L;o)4^^Oc!(;i&(++t? zuiH={DGlVAG?cvAWkYg+X#}ILN4LI;LA<^&nfd|w)QsHU?>P1meo08h%VFb1s5d`_ zP}0WYERWNnP6H7jZoB}Uqd|%)7Q0)$GgkK} s$|J$r_VG*5$Wtg#R23)mHk2)zeH<3YY (@*Sa#~#tl;$XK-+i zK6>7~LqWh}Id#E70LougeEYT9^1QwnXJm!Og_=LSl;&0bkhA(KRDF`qJF2PVWFo6! z6Z9A1fg}yoAR?>WzZn 0L3b>Xc8%&6L>3x} znt2?i8r4qnzG{s{$=*3RoSKBr;_<$edRva-gDebBaXiGAhj!++q}Tt?rV1Bc#BF*6 z-ad!a&q&XGxch>H-hw{gJWC*whHEdkBM((Ne@cz!*3TK5N6Obuoj#p| akuO`EM>73kT7Pvh?dB1gvwgBWOWSiZb{P3SP>O12AACLxz%YR`ZD zs3r&z_Y9;UWnCuv^nLn0y{3j5EukpIvd)+AQfjOmbqWXj@xWuq8Q5zveNM@OYF*r& zvOaaVf|3Jx<%DUx35|jQ)cEZ~KNk3kzsd&r#rr6W9kK}1gw&QP+7@17S2UZ-$ 3j?vzO=tufkCyU^-I$Xjv79Bj= l1B$Zjj8=6Ml%OJ-wR>rLdqJ1LHcXPr|D#gBt%bD= 4rumUoBmQLJj%AiTMrVL&G z@039`IjGWeYfbFa^N+gAff2!7KsOGG52Y;x7);&Lb{FqiUYK?Y+i|UEZ$MK{nBifZ z2JSGxlqQEgh&AvPMy2bu@7ODv#rWueYji$W)+0X|xMq28oF6DG`Y&*I70g5H=J#Z> z{2H&IkPFK3&jUP;d815IX5F1?SLxQNV}=w3jZP@ULe*8Q_XP4AQtF!K#4FT{Ap>dI zf^J+o;`}jul)BT1=|c`wyWuEU1|Ey%8v~1ZMBwwA3XT4_o@F2RWKzy4 z7xxgzXwe43ui43w3*D2A)V(ENWPb|G%BShE?xOu=p6pLIn-%)cK&m+eq_wkN3CGo{ znE-V}jf%GE^XU#};ik>&gYBe <=5ryiRR|u4$=IVJtftxo^}8R zD#tu81h$N+i=YEqcZ;?HBjA|AvHhd^@_P}xH(2~H_ku0_fUM;M6tA#x9W#fREeE*2 z!eF*$GfF+AR&6j2JD`g8Gz8?|HzsD%5Dqm}tZ3?-uom9U&AdBexk?64{QmwReM(YU zyV(n6=BuI;ZTO2+z)3%QhE}K;n2Vj>64Q$GqjJ~wW$3`eE2CIpQpNNt=xbQCG;ANb zn 7=yf!=FOX*qZ<(APfCKjPmJlv~+-YRRlsnqjMJ`g;MhahT& zRH@X&;d3f&*9H_gPOO9-phoiGkWrwJ=YV1p2`|&==O(l1;uu-Suzl{35j+ux JP(WN?pAlTwgjd+E-=R5C}=HSwKBSyW_E1x7HOxRh$La`@<)ha)3;Ng1dv zsisbic)lC$D|_Hh2Gs3GuKAe7NB{4X^)Dy;N5lh?+?T6TNg?TXNSBaPBwjVj|Ku&Q z^^6ZwIC4E oZbOmmUlaJhwgchhvW;2+cp(C*AzPNn8Ss4eMS^FF Q0RAY*o|MU#I_v-c0o!aW;Q#;t literal 0 HcmV?d00001 From 83af31bf814f6a7f0f263eac8e4c05f9823c8c92 Mon Sep 17 00:00:00 2001 From: Nas <94843416+Nasirhus@users.noreply.github.com> Date: Fri, 19 Jul 2024 10:21:12 +0100 Subject: [PATCH 06/13] Update README.md Co-authored-by: JackMead --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d30ec6c12..10a6803b2 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ docker build --target production --tag todo-app:prod . ``` docker run --env-file .env -it -p 5001:5000 todo-app:prod ``` -This command pases through the environment variables, `-it` makes it easier to interact with the container, the app can be accessed at port `http://localhost:5001` +This command pases through the environment variables with the `--env-file` flag, and the `-it` flags make it easier to interact with the container (e.g. allowing us to shut it down with ctrl+c from our host terminal). With the `-p` flag, the app can be accessed at the address `http://localhost:5001`. ### Command to run dev container ``` From 0f5a3cb9a5551cb6f771c2e4d15ad75468e36710 Mon Sep 17 00:00:00 2001 From: Nas <94843416+Nasirhus@users.noreply.github.com> Date: Fri, 19 Jul 2024 10:21:28 +0100 Subject: [PATCH 07/13] Update Dockerfile Co-authored-by: JackMead --- Dockerfile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 6d1c04e4f..8a0df9c05 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,10 +6,6 @@ RUN poetry install ENTRYPOINT poetry run flask run --host=0.0.0.0 - - -# Perform common operations, dependency installation etc... - FROM base as production ENV FLASK_DEBUG=false ENTRYPOINT poetry run flask run --host=0.0.0.0 From 0912f573802918f61addff3f901619c315180025 Mon Sep 17 00:00:00 2001 From: Jack Mead Date: Fri, 19 Jul 2024 10:27:52 +0100 Subject: [PATCH 08/13] Add a dummy unit test --- poetry.lock | 109 +++++++++++++++++++++++++++++++++++++++------ pyproject.toml | 1 + test/__init__.py | 0 test/dummy_test.py | 10 +++++ 4 files changed, 107 insertions(+), 13 deletions(-) create mode 100644 test/__init__.py create mode 100644 test/dummy_test.py diff --git a/poetry.lock b/poetry.lock index 26406b36e..072560de7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,10 +1,9 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. [[package]] name = "blinker" version = "1.6.2" description = "Fast, simple object-to-object and broadcast signaling" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -16,7 +15,6 @@ files = [ name = "click" version = "8.1.3" description = "Composable command line interface toolkit" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -31,7 +29,6 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -39,11 +36,24 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "exceptiongroup" +version = "1.2.2" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, +] + +[package.extras] +test = ["pytest (>=6)"] + [[package]] name = "flask" version = "2.3.2" description = "A simple framework for building complex web applications." -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -67,7 +77,6 @@ dotenv = ["python-dotenv"] name = "importlib-metadata" version = "6.6.0" description = "Read metadata from Python packages" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -83,11 +92,21 @@ docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker perf = ["ipython"] testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"] +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + [[package]] name = "itsdangerous" version = "2.1.2" description = "Safely pass data to untrusted environments and back." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -99,7 +118,6 @@ files = [ name = "jinja2" version = "3.1.2" description = "A very fast and expressive template engine." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -117,7 +135,6 @@ i18n = ["Babel (>=2.7)"] name = "markupsafe" version = "2.1.3" description = "Safely add untrusted strings to HTML/XML markup." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -141,6 +158,16 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -173,11 +200,58 @@ files = [ {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, ] +[[package]] +name = "packaging" +version = "24.1" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, + {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, +] + +[[package]] +name = "pluggy" +version = "1.5.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pytest" +version = "8.2.2" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-8.2.2-py3-none-any.whl", hash = "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343"}, + {file = "pytest-8.2.2.tar.gz", hash = "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=1.5,<2.0" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} + +[package.extras] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + [[package]] name = "python-dotenv" version = "0.14.0" description = "Add .env support to your django/flask apps in development and deployments" -category = "main" optional = false python-versions = "*" files = [ @@ -188,11 +262,21 @@ files = [ [package.extras] cli = ["click (>=5.0)"] +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + [[package]] name = "werkzeug" version = "2.3.6" description = "The comprehensive WSGI web application library." -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -210,7 +294,6 @@ watchdog = ["watchdog (>=2.3)"] name = "zipp" version = "3.15.0" description = "Backport of pathlib-compatible object wrapper for zip files" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -225,4 +308,4 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "d8d856f03434ab9857d0c9bd058ef199cc0438a15afe205c0fcd177e92d0691f" +content-hash = "34187741501d30279611f3933c014bfa5ca2cb78f67a3d4911391cdcf774288d" diff --git a/pyproject.toml b/pyproject.toml index 4d9bb90f6..299d93979 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,6 +8,7 @@ authors = [] python = "^3.8" Flask = "^2.2.5" python-dotenv = "^0.14.0" +pytest = "^8.2.2" [tool.poetry.dev-dependencies] diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/dummy_test.py b/test/dummy_test.py new file mode 100644 index 000000000..83892bd9d --- /dev/null +++ b/test/dummy_test.py @@ -0,0 +1,10 @@ +def test_that_basic_addition_works(): + # Given + num1 = 2 + num2 = 3 + + # When + result = num1 + num2 + + # Then + assert result == 5 \ No newline at end of file From 810923ad36ce27633dbb70dc1e1220a916da84fb Mon Sep 17 00:00:00 2001 From: Nas <94843416+Nasirhus@users.noreply.github.com> Date: Fri, 26 Jul 2024 11:25:43 +0100 Subject: [PATCH 09/13] Mod7 test --- .github/workflows/continousint.yaml | 10 ++++++++++ Dockerfile | 6 +++++- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/continousint.yaml diff --git a/.github/workflows/continousint.yaml b/.github/workflows/continousint.yaml new file mode 100644 index 000000000..d4ef60b55 --- /dev/null +++ b/.github/workflows/continousint.yaml @@ -0,0 +1,10 @@ +name: Continuous Integration +on: [push] + +jobs: + build: + name: Build and test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: echo Hello World \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 8a0df9c05..0d4e27b59 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,4 +14,8 @@ ENTRYPOINT poetry run flask run --host=0.0.0.0 FROM base as development ENV FLASK_DEBUG=true ENTRYPOINT poetry run flask run --host=0.0.0.0 -# Configure for local development \ No newline at end of file +# Configure for local development + +FROM base as test + +ENTRYPOINT poetry run pytest From 99ffbf45e8aa2cfbe8ac07696a9f2c7f2d8cfe6d Mon Sep 17 00:00:00 2001 From: Nas <94843416+Nasirhus@users.noreply.github.com> Date: Tue, 30 Jul 2024 13:22:18 +0100 Subject: [PATCH 10/13] Add test container to CI pipeline --- .github/workflows/continousint.yaml | 4 +++- README.md | 5 +++++ test/dummy2_test.py | 10 ++++++++++ todo_app/app.py | 4 +--- 4 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 test/dummy2_test.py diff --git a/.github/workflows/continousint.yaml b/.github/workflows/continousint.yaml index d4ef60b55..76ca7ec75 100644 --- a/.github/workflows/continousint.yaml +++ b/.github/workflows/continousint.yaml @@ -7,4 +7,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - run: echo Hello World \ No newline at end of file + - run: docker build --tag todo-app:test --target test . + - run: docker run todo-app:test + \ No newline at end of file diff --git a/README.md b/README.md index 10a6803b2..4e43a5b90 100644 --- a/README.md +++ b/README.md @@ -73,3 +73,8 @@ This command pases through the environment variables with the `--env-file` flag, docker run --env-file .env -it -p 5001:5000 --mount "type=bind,source=$(pwd)/todo_app,target=/app/todo_app" todo-app:dev ``` Bind mount is miroring a folder and the folder in this instance is the todo app folder allowing changes to the code without having to rebuild the container. Running dev changes without having to access the container + +### Running Pytest +``` +poetry run pytest +``` diff --git a/test/dummy2_test.py b/test/dummy2_test.py new file mode 100644 index 000000000..db6ab3751 --- /dev/null +++ b/test/dummy2_test.py @@ -0,0 +1,10 @@ +def test_basic_multiplication(): + # Given + num1 = 5 + num2 = 10 + + # When + result = num1 * num2 + + # Then + assert result == 50 \ No newline at end of file diff --git a/todo_app/app.py b/todo_app/app.py index 5c99596dc..0375806fc 100644 --- a/todo_app/app.py +++ b/todo_app/app.py @@ -19,6 +19,4 @@ def index(): def new_todo(): todo = request.form.get("user todo") item = add_item(todo) - return redirect('/') - - \ No newline at end of file + return redirect('/') \ No newline at end of file From f24dfa52940b8d0bb21823bf75b3a6dd79e11fd7 Mon Sep 17 00:00:00 2001 From: Nas <94843416+Nasirhus@users.noreply.github.com> Date: Tue, 30 Jul 2024 14:35:43 +0100 Subject: [PATCH 11/13] Invert filter condition on triggers --- .github/workflows/continousint.yaml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/continousint.yaml b/.github/workflows/continousint.yaml index 76ca7ec75..f2f6b2f89 100644 --- a/.github/workflows/continousint.yaml +++ b/.github/workflows/continousint.yaml @@ -1,5 +1,12 @@ name: Continuous Integration -on: [push] +on: + push: + paths-ignore: + - 'README.md' + + pull_request: + paths-ignore: + - 'README.md' jobs: build: @@ -8,5 +15,4 @@ jobs: steps: - uses: actions/checkout@v4 - run: docker build --tag todo-app:test --target test . - - run: docker run todo-app:test - \ No newline at end of file + - run: docker run todo-app:test \ No newline at end of file From 888d9d5d151ab5a54631710f0c6d684ec9aee5e5 Mon Sep 17 00:00:00 2001 From: Nas <94843416+Nasirhus@users.noreply.github.com> Date: Fri, 2 Aug 2024 11:15:03 +0100 Subject: [PATCH 12/13] Novel Adjustment Filter pipeline --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4e43a5b90..becacf665 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,6 @@ docker run --env-file .env -it -p 5001:5000 --mount "type=bind,source=$(pwd)/tod Bind mount is miroring a folder and the folder in this instance is the todo app folder allowing changes to the code without having to rebuild the container. Running dev changes without having to access the container ### Running Pytest -``` +```bash poetry run pytest ``` From 5a14ad9e2d867366c4996bc426e57f14b8b91394 Mon Sep 17 00:00:00 2001 From: Nas <94843416+Nasirhus@users.noreply.github.com> Date: Thu, 22 Aug 2024 10:18:56 +0100 Subject: [PATCH 13/13] Updated README to explain deployment process --- README.md | 15 +++++++++++++++ todo_app/templates/index.html | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index becacf665..750de35b0 100644 --- a/README.md +++ b/README.md @@ -78,3 +78,18 @@ Bind mount is miroring a folder and the folder in this instance is the todo app ```bash poetry run pytest ``` + + +### Azure Hosting +The container image that is deployed on Azure is hosted on Docker Hub at https://hub.docker.com/repository/docker/nashussain76/todo-app/general + +The website is hosted at https://nashusappservice.azurewebsites.net/ + +To update the website you will need to run the following commands to build and push the updated container image: +```Bash +docker build --target production --tag nashussain76/todo-app:prod . +docker push nashussain76/todo-app:prod +``` +Next you will need to make a POST request to the webhook link provided on the App Service (under the Deployment Centre tab)> This will trigger Azure to pull the updated image from Docker Hub (link not provided as it includes credentials) + + diff --git a/todo_app/templates/index.html b/todo_app/templates/index.html index 6ee8dd7f8..a7a167dd5 100644 --- a/todo_app/templates/index.html +++ b/todo_app/templates/index.html @@ -3,7 +3,7 @@ {% block content %} -To-Do App
+Azure To-Do App
Just another to-do app.