From d5d0a24403898438caa17a8eab9b13d2e78a2ffb Mon Sep 17 00:00:00 2001 From: c-d-p Date: Wed, 23 Apr 2025 00:57:31 +0200 Subject: [PATCH] fixed linting issues --- backend/alembic/env.py | 13 ++------- ..._initial_migration_with_existing_tables.py | 2 -- .../versions/9a82960db482_add_todo_table.py | 2 -- .../core/__pycache__/config.cpython-312.pyc | Bin 1353 -> 1314 bytes .../core/__pycache__/database.cpython-312.pyc | Bin 1887 -> 1865 bytes backend/core/config.py | 1 - backend/core/database.py | 2 +- backend/main.py | 5 +--- .../admin/__pycache__/api.cpython-312.pyc | Bin 1762 -> 1661 bytes backend/modules/admin/api.py | 5 ++-- .../auth/__pycache__/api.cpython-312.pyc | Bin 4396 -> 4320 bytes .../__pycache__/dependencies.cpython-312.pyc | Bin 1372 -> 1328 bytes backend/modules/auth/api.py | 4 +-- backend/modules/auth/dependencies.py | 2 +- .../calendar/__pycache__/api.cpython-312.pyc | Bin 3080 -> 3020 bytes .../__pycache__/service.cpython-312.pyc | Bin 4517 -> 4510 bytes backend/modules/calendar/api.py | 1 - backend/modules/calendar/service.py | 8 +++--- .../nlp/__pycache__/api.cpython-312.pyc | Bin 11382 -> 11327 bytes .../nlp/__pycache__/models.cpython-312.pyc | Bin 1383 -> 1363 bytes backend/modules/nlp/api.py | 26 ++++++++---------- backend/modules/nlp/models.py | 2 +- .../todo/__pycache__/models.cpython-312.pyc | Bin 1006 -> 985 bytes backend/modules/todo/models.py | 1 - .../user/__pycache__/api.cpython-312.pyc | Bin 4271 -> 4235 bytes backend/modules/user/api.py | 2 +- .../test_admin.cpython-312-pytest-8.3.5.pyc | Bin 11514 -> 11443 bytes ...test_calendar.cpython-312-pytest-8.3.5.pyc | Bin 52694 -> 52676 bytes .../test_main.cpython-312-pytest-8.3.5.pyc | Bin 2160 -> 2142 bytes .../test_nlp.cpython-312-pytest-8.3.5.pyc | Bin 27018 -> 26986 bytes .../test_todo.cpython-312-pytest-8.3.5.pyc | Bin 26725 -> 26662 bytes backend/tests/test_admin.py | 2 -- backend/tests/test_calendar.py | 1 - backend/tests/test_main.py | 1 - backend/tests/test_nlp.py | 2 +- backend/tests/test_todo.py | 2 -- 36 files changed, 28 insertions(+), 56 deletions(-) diff --git a/backend/alembic/env.py b/backend/alembic/env.py index 4770a9c..c9fe209 100644 --- a/backend/alembic/env.py +++ b/backend/alembic/env.py @@ -7,22 +7,15 @@ from sqlalchemy import pool from alembic import context +from core.database import Base # Import your Base + + # --- Add project root to sys.path --- # This assumes alembic/env.py is one level down from the project root (backend/) PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, PROJECT_DIR) # ----------------------------------- -# --- Import Base and Models --- -from core.database import Base # Import your Base -# Import all your models here so Base registers them -from modules.auth.models import User # Example: Import User model -from modules.calendar.models import CalendarEvent # Example: Import CalendarEvent model -from modules.nlp.models import ChatMessage # Import the new ChatMessage model -from modules.todo.models import Todo # Import the new Todo model -# Add imports for any other models you have -# ---------------------------- - # this is the Alembic Config object, which provides # access to the values within the .ini file in use. config = context.config diff --git a/backend/alembic/versions/69069d6184b3_initial_migration_with_existing_tables.py b/backend/alembic/versions/69069d6184b3_initial_migration_with_existing_tables.py index c74bf5b..6dece1c 100644 --- a/backend/alembic/versions/69069d6184b3_initial_migration_with_existing_tables.py +++ b/backend/alembic/versions/69069d6184b3_initial_migration_with_existing_tables.py @@ -7,8 +7,6 @@ Create Date: 2025-04-21 01:14:33.233195 """ from typing import Sequence, Union -from alembic import op -import sqlalchemy as sa # revision identifiers, used by Alembic. diff --git a/backend/alembic/versions/9a82960db482_add_todo_table.py b/backend/alembic/versions/9a82960db482_add_todo_table.py index fea09ee..c264d75 100644 --- a/backend/alembic/versions/9a82960db482_add_todo_table.py +++ b/backend/alembic/versions/9a82960db482_add_todo_table.py @@ -7,8 +7,6 @@ Create Date: 2025-04-21 20:33:27.028529 """ from typing import Sequence, Union -from alembic import op -import sqlalchemy as sa # revision identifiers, used by Alembic. diff --git a/backend/core/__pycache__/config.cpython-312.pyc b/backend/core/__pycache__/config.cpython-312.pyc index 1ae3b10615b3cacb804329dd24c8c18d41833dd5..fbfe8fd6b30cd35a6a8a319ddf49cee887384aba 100644 GIT binary patch delta 459 zcmX@fwTO%FG%qg~0}x2dab)aep2#OrzYNHm&XB^8!kEL5%NWJT2x2qkFhwz?GG(!W z)S`kcPEE!D5g`BEVlFNzy2T$KpO}}IUy@jonV(l2A78`{k_Y*%2;}Tr%$a#5MZ6%c zAcz2&S0n=>z{bmgSgbGtq_sF2NVGCM5SlE(62T2t1d`X}nq18yIe9UQvXcZ%`7MrO ssLRnz{Ka9Do1apelWJF_1yl?QsA5MT@qw9m)?{v0D;AK^06Hc~fB*mh delta 482 zcmZ3)b&`wkG%qg~0}veI=g8n=naC$mzX`~j&XB^8!kEL5%NWJT2x2qkFy%5wF@xF6 zIV@2usVrGweIUIEkj0B&!&o>}^26j2bSlScMuu=OKZRvA6GS44lZnBdA%(StA%!iK zaWykkl#7WWm1{LrZxnYWvnKmX5Koiw7LQY6acXdCNl9j2dNGjC>XwTByKTh=9Lujfw)2- zLIFg`f(Wol@*ox)jNq93ojFAxECCYJB diff --git a/backend/core/__pycache__/database.cpython-312.pyc b/backend/core/__pycache__/database.cpython-312.pyc index bd6580dee5f73e898026c69d0ffe9206c90b5b43..300d627ac6ecd91596583779bf31b8a8ced9b6e4 100644 GIT binary patch delta 226 zcmcc5cao3yG%qg~0}x2dab!%`$jipa7`0i1(S}iihmoO#A0z_;Da@-GA*`m!1x!!b zS2BDCaVIA*TXTs48N5JT+&XzFbEEhNW=76v#$UxeK%s*YB2Jslb^E2|o#=wunT{d&?M ojbPofAeJ(S5C#zk delta 245 zcmX@fcb|{ZCW>kYyI5=;Sjjk`f|7RksAvQ%mBDQ;Ul;^Yd~Ovr~(T zWG4S*(P#S1FjIO%is)@GVVjwz(fx=s+d~c#5Aklv zL4QIa-ueghR`AlJECfHmg9pL0Ao$Lt4aJ3d_L=8>c)xbPJAZBGljB$jp36;huX*4! zaP6SonqWi_Q9>=!eO+=jG$PYCCD+1yWcilldRT~T-v(|FGjyV&U&JVfs6z6@8em{5 zwdYt=Kxly97v{>6`=uPZkBB`*#G(31Ez{Do4K!JL&LJtDB_X9Lnx97eD%jiSY^Riz zSMCZelPbm3l&x52`fjcP-d&Ykn5wI6wQ{{;OW@^F^F6URv!q?C9$xIBLFB-u|X z%ZzP0qA}sZayQ`gVM1sK7vm}Ae3-;Q^#M(LWasDucCcH4giL?~hZ_K|(PyhT?K05< ztIU4owzn<`DnW{CaLp`61JVmfG>lmjgfbj1lDtA+?fRRSCxy)ub(1xYBBh7BS0TWv z0G=XWtN=XIptoQQQcHwg0m8$@S8!dI$wFp7qydA5*#^k<*+uP!A=-H4)n{GJy_K1x zF$v;y*k?M(S&_d8gRs9xqj4u;5fd|IPCsF^LxMEefu%5WcC57~c@fdlfIsKUesm_6 zDEE;muqHWKrj8Px%Ig0u;g7i$C1gLOw^;{ri64o-1^BICjDMgjU(mG$YA(?F0=Wxx ZbAi^r<*Vym%MtZ4dqtp1et*R7DToJPU$vrnW2w^74Ma_j@1nGJkU4EbF6XWe_~O-}RGc zr&b*|Pq#NmzUF8c5kwR(?dy&%ebqC3(=ny5c^NL48*tE4hkm*wiiYNPg3 z)M((u+zo;-awAF_3V_EC4#Po2S)%XLJ`D&@)V+`lg>cX1^kGP-2S9&9Iq!u*BL#8b zlXRCxZE_^=Qx55du!o^XL45WaXRuv`eoUA=yj%zK3VqJx#|La(M&b{t{VQw2l}3^q z0Fw-(E@`{O?*(iNh+=FjHN1XyOKIbSiz1;0rlH6WD~J>grgVouT@vBT3k?^4#kOrG z>lz)8x(tS9+d$XiFY1mix;|>G#ud#jvNV9i=nsh-M7<8v<9k}=wjoHX6EfN&ZsZ=p z;h6~>6ZbAD`ym;4l(*bLbkYJqJ?a zkVkT^|F-elxHE5Ym)(R~;>z*2V16kW;~!{khMJ#HbBZ>mXlsV9&QNQLu20eGSF`ly N+PfI1U#jAae*yEcu*d)a diff --git a/backend/modules/admin/api.py b/backend/modules/admin/api.py index 63990fa..120ab82 100644 --- a/backend/modules/admin/api.py +++ b/backend/modules/admin/api.py @@ -1,10 +1,9 @@ # modules/admin/api.py from typing import Annotated -from fastapi import APIRouter, Depends, Body # Import Body +from fastapi import APIRouter, Depends # Import Body from pydantic import BaseModel # Import BaseModel from sqlalchemy.orm import Session -from core.database import Base, get_db -from modules.auth.models import User, UserRole +from core.database import get_db from modules.auth.dependencies import admin_only from .tasks import cleardb diff --git a/backend/modules/auth/__pycache__/api.cpython-312.pyc b/backend/modules/auth/__pycache__/api.cpython-312.pyc index edff5ae78ea265e5552b70d0aa4d024b08a1a25c..b69dc645886052535e326b83d55dce93e4529856 100644 GIT binary patch delta 1421 zcmaJ>O>7%Q6y90y+H0@Z>%_6s#CB{aX;L?>Qv_*5OOcA|Bo#lZk{r-Ts50Jh;;^%8 zX4ft0#g_`s)f_l*=1@5o@C9+@$PuZBl@JIaAtVl*IB;U#tgsrSFo#dyyq|C0d$Y4= z%Re`)?=35%h*e%Pj&D4(7Dk_{it@SQC=PNJiZG%oR%rq!sD?EJcGcBs5+@~3xG8F2 zLvqbc(+ti?uDd49;w-hWMRPbuZEVv#&P!j?ouRXMR`QfvpmTVR7IBf5aEZ?2XJ5|j zNtfYPXcbo_PrFOBhHH{%+&XRGhUBKZOjq!VUdERtx7;#vbk&v5Eb^=YM>r;Xh;XkEbFP0!?4PYHW2T1bkM%gR?Edx~efzjBW6SS$bYhYOgkn&r=ZVCt>wGN9l z1&egoKk9qz79Sg5ppD6H`U5nAv?s;;-lLA&cj}Dv7zvK+q5l!_*rxEYR{>rV&{UaJ z-Ue<&`hfMlP@co85K{!m3y4zt?VbJh!5)+KLMNig+u)W(LTOQY7!dZ*;VWj{gyLeM zoBTcVadkuNpQJWLwPMOqwmW2uc;Q3HU|akb^MyHWQOxqY?Dj55##PJ%GX$JF@-47V zlm0uGWPB29^Sjm~bc26mRr#-0VJ#)HBJIQ%=YnEXpuRJ7Nzm#H!{e6N5I10HUd=5Q z;rGH!fGmIokmK*<$|GCQsCX_jAflyycq*sGW*~MJK#mLUG@hmW4xpbX7kun?-0m@< zr!AjRb_tBh@O04kjuOKclO7~WZXy=$*Ge&t~|iC-ZPH^okAOGtu(Dw>cWpp{7^YbYwlJ5C&SyzcBe zC8u1<6)74C4xBh}fV3R&86nPa>7__}0SP3;jWa@s`FFuIh%kpw-~5m7f9&Ij(u1<` zjbX$jaUOpe+21`ea>pOYlJucuN+z--iZG%wmT3rwXc&j7f)yIU5vpPpL5yr^G>W4> z4_Ps)W8LRrD^3k;_*}6@XaXl_5+`X2r)V0dX$EI}U&I=vV|dKxsx?k0@X05s2A#rF zbQ(|7JkI+r%_`6$F8Vxbm1r54=?tFn?=kBsI*Vt0u3K|-9?$zcZY|IXuK3)rF49H3 zc=E?Y;S#xY@CFQg_LwP>B+9{U{&6IeOP_`UubCkUbCi@xQI<%E%<{L;^l|MRg>jO4 zFmWoj2gl5ctSDri1_r4u=fM7i+9?WLfu|idbN9o4N8_b)s$Af|BfXaXU!AEZbS{Gq ze^xFWhe&Q%5t)-DbH0X|7u_5F%-La1(0_qE)7H%5eP!6`m7`Ln{0odyQN8H(TibQJ z?-J%kUbO9ZI>b|NkRIup{98Gj@zgrG+b53eX?5cC?5;xwKgk6&E{n`=*LIsOF+J^O z&+XXVrZq@}HH6YUs}v*iq5xaq>&hmo^7oWAG&}fO`2wLi?yA?&HU62pvIZMw7XcOl zA^@rYZ)|I4=hmI8OPBBLzIJ_gXX|Et8*kiT;}B2)DDu2kTAmQJqOc{fECBdLSAeYw za1;SWIP7V`JjJs2I$gHT54Dd_ZIF(>iO>S?#U>k9AY~cgIRO=!`5J4$HBafWPS^Dn zSqWmY02u*dJsX?#jn}t=&R`PJ&I{o7+gas5#ujy`9b~WaoPH10_=!G=R`^5xu|Dio ztm^&v@=MTmP~-wIUBDT|O|TA={ykts3@9EZ+vaiO@Rh5c+HN{-v)5tpeXuY9tmL0X zGYzg$0bcU2*s4QXeb#Z082o3v@PX|Rrt`0iTssbiQEHogi#XM0-`%e|t$jk94l_V! z1Rw#B1V{<+#?FQlcGzhVho%3^7u4mij^vJm9p^v>7U7LJcde!c#g3{rqihn45%;Lq z>F%*92%83r(Xtt-noYO)c2l&S2b(6Y#O+Yxzd4@nhqUZ&yR*lN5RmXKq? zpFbLzdATZ_Y#jieiWhQR#N5c*kad?z&? UNe#Z1m=Ap~%?(K69tuP9pO6Sdh5!Hn diff --git a/backend/modules/auth/__pycache__/dependencies.cpython-312.pyc b/backend/modules/auth/__pycache__/dependencies.cpython-312.pyc index b6e718cab69e5890ee06189805175eda1e495e8f..bce22974b01e0ba1c02bdf99cb73cb14c88c4a70 100644 GIT binary patch delta 465 zcmY+9KTE?v7{>1|m*$U6Q)vBLT8fKi35w831VONqgJTAvG*?P+nPorfHZ!>58>`@liC`2KS zP>chNL6eBYTA(SdMKsm}U1=JXVk0n=)*~~v0t+L8j!{^;M4@p{U^GI3O%Su0e!h}j zHJjz1VqyLz)3bR!E0*e&ndw>YV0pMOj@X2a!@P=LE3m9b3MyDM;PwL{+qea9+)xHD zgRV*l$Zof}lXtaK?B+Mx?v4&-1)u>apaiH%+#&9Qb^w+_{-t&H)Fad zks44e$4NMinDBekbm$A#pYl;U<1|m`MhC)*+P@B2ut=!L!tE!V`Rt<4Cg~^{3-tkR mI7{`-K+UvEwzKDX=S}F=!gwu=z$%`Dw$%S^>T;ofH?y2MiIt2u7*HaCzR9|*?a08~snzzkj_a)J zwL0w}Dm~ll^*>)yNodppDw*35$=heVhzpPtMpzIj&|?Y`tQLzR?U%>_&iZGhvZ6yV z10aAXAO@IFxJDuiIt@sK@Sn))Y?y?2uaph+hOMl0TcZIKx+4A(ozBCoV4QcHp37v} z?s?6!tT!3ArOdtiArRkPwSLnr) z2alHdD`a~R*8jr&3%Ykf5Cjh%JozR`OV(Wn^7!V>`+nxln-Ar)lKNFuQv$4NUFmPWx>P7V#P;1;~1Tl7k9$t$~M&vZ>B!~}wH3ST=wi}Xp1Qv|`S zkjmk9praA1L?`0m-Dob*iww&ldnZfsI7hNLPo$oVwfE9VSnAe*xO3SDM1|-kY%Fy4 z4Yi(O0~@{g3W5tHNo2l_i!0Sra47<|{sS%(-ACHnCTXmA&{QSj-30HWE1Ft+?{ROI zXluWMs}cVe_@7+m#~X_pT*tO9o?VZ4ug?s}Vn1Tu=~x`1Vh%9N*Z?~st$?Ie9yZvo z_;YC!WQOfYHY&4`^lGmT|4xi*yu#u-9#-?j77r~5lQ@J1EZP9EOdXJEhrA`D>4df+ zQDk|!iJI(=JboGi^N?NvZLWhJxZ*AS1I(_0oj0@208z6uyvbxN=@cqr_DYpGiD_VD9v6cOWJ;)c-;wAIXlBc7Si5l36a7){dq?ojR#=2y delta 1079 zcmZ{jzi-n(6vusW>^dcGnmTUc{Aki7RT@;K5^GB(7!Ya&R7}VciqhPrO%=z{*{SFR z0|SiJ{S~O$x-ha+!EOoB6(J!pf*5#bCzdH-$xq*V_kEvxcV}N_U***IsyZ*gb5K-{ zuFg~gy*q2z&yj!yoER)wnyFbCGh^wd?&szQ%U0IRS~)Xk8Kz<7&Ae4G3rL6w1mPPv zd59+Jd5jYU!7P&E@m8Rt5iby(h{xN}T%aeZa}gB#jHM1xE0k8fCY!KZ?HcEL?o$;Wl zLZr4vitI&9mqPCr_b!r5=vQzt;$MTc9{ghy1};rjp#4Vq&$Y^t+QzBgtgx$?mC=T_ z+wR%pA#RgrT{3d}_V8j?w9#@J*j}uUn<6cMq(vS|>|^|qR0Wx0HK~CNwkJKkSB7yj zMm6rJa2=nzd7{q48U!Z}p#l$G1>wyf61PoG$k26Y0}@&GO{$_AOUt9ZDR2qWGvGSc zK@VK6`QzP4h>@{j~Ji;B91f9|i zUdCR}Rn;1(FPD6XXr8^D+rK-->yQiZVt@~ucKD|m?mvmifP~;pn7YMwm6FWC&2?re zryHrRO-U=f7l$Tc&eJR#j|aqQb;j;d3kGE1P?h~sR(2L(o~C$M diff --git a/backend/modules/calendar/__pycache__/service.cpython-312.pyc b/backend/modules/calendar/__pycache__/service.cpython-312.pyc index 4b3a1bc96b3054b4520231f6b732409ddd3cedc5..725eba92da1974a57a6d25654ff3f0865ee44321 100644 GIT binary patch delta 198 zcmZ3gJWrYTG%qg~0}#xY9?K zSUUM4i^AkoRu{&u$*WjBSyO?El3|M0vB*u1V$%XE(%ig(?I9Cm%;ZU&sm3c*E(q#v zvAu5WcG1}Fgz!aUpNj&%R|4a%2PRz%OuCSobulpOqCoZ&LAmRKN*4u{7NlI5tjU$3 b2-oLw(b(k#^F?Ftivm8#sy1)p`pgCZ6xvAH delta 217 zcmbQIyi}R@G%qg~0}yDQXUXv2$a|leQD^d7<~ghrYM6`qCik&8FlU=HOm<{dnEak4 zkU3ie#7<%DsbMNo2Fi+0c4k!;Sj`ABfq|ixB`+PQEfu7VDcgLq98gyXn-)};!shvG zub3F4CwFnC8ZAh start), + (CalendarEvent.end is not None) & (CalendarEvent.start < end) & (CalendarEvent.end > start), # Case 2: Event is a point event within the range - (CalendarEvent.end == None) & (CalendarEvent.start >= start) & (CalendarEvent.start < end) + (CalendarEvent.end is None) & (CalendarEvent.start >= start) & (CalendarEvent.start < end) ) ) # If only start is provided, filter events starting on or after start @@ -63,9 +63,9 @@ def get_calendar_events(db: Session, user_id: int, start: datetime | None, end: query = query.filter( or_( # Event ends before the specified end time - (CalendarEvent.end != None) & (CalendarEvent.end <= end), + (CalendarEvent.end is not None) & (CalendarEvent.end <= end), # Point event occurs before the specified end time - (CalendarEvent.end == None) & (CalendarEvent.start < end) + (CalendarEvent.end is None) & (CalendarEvent.start < end) ) ) # Alternative interpretation for "ending before end": include events that *start* before end diff --git a/backend/modules/nlp/__pycache__/api.cpython-312.pyc b/backend/modules/nlp/__pycache__/api.cpython-312.pyc index 054df8cd5b6c08ad2e640ddb4305f94bbe8ad5c2..b18dfb9dc6c2c0cfc99dfc961bbc437fcfc5eaf9 100644 GIT binary patch delta 1623 zcmZWpU1%It6uz_Boy~4G8=KutvVXIiWV8Ppn`qE#Q>~?>D2bu9H66ue*n2nGc4lWe zGpUVG0umpjeXv{~L<*wN2T2r4eDFnl5)pk9L>59`{CSg#MMMz1=Wc?b4$L>_obTLo z@AE~@*`%&s^}Gkc*p{w z$F>L^X65ZZJPINDX4ONOLL)S~s_ewJJqP9*9btZ!jtiBJ3TYaprk9RwdG$wWTv(?5 z$0Y=JoYk&0dNGb7O|p@l)M0e7qlXP_E9k+qp2&Qf#i+&xX@>clD$Q>BwhtETvm)N= z(MUa+j*Ami@dP_59`Y2DhpWAG;>ha9HzrFtzU29dpYHpLhx6|acRelIRUOu*47y&I zU3dAt{4M{-OZ1XUr!w1A~j01BuS5lZ~c zLT(bhB?%Rjq;CzS>>-TtZwi%wB+$02dh;G-j@Q)k>}jDps(`F~02g*gnl@O5TW=Vq zII;nCc8#@N2NndGy*x9wI?Z5@W&hWc|Pn7EJh2Y{)5GK%nQUL!n zzLJXwp*w6)`p`+?Npw4b@H8(cGD?&`p8zGszerqCUqtg7k0&ojuHyOu+^fFcp@z$Z z{jFq1d4b~1!(YkIy;xa(FBMb9`PZq5P0Ryub6JtDD*7qv1fysfMmU9lsRP!x z+t;x>;6rr`Au4UF%!L?AA$b6Y!L?R{0gjza9Fj;5G=PbN)zJr*kV}zGfmcv$qld2p zt+opk4NMwL`*ks9fwR{etmC%qc4-_gB6|tpWds}jLJixpj5e){%ni`d{tCjY2(O_> zz-ZNtwj-j!9O{u?clfXAXswBc!QSa;Z$RKIu9O*vuqnWtj@=fCHF!~bRyoI8S~@Cg z9_p2w_R?DB?`s#88o#f_d^bgi`Q2c~>*xOzJ~)3Fck!7mtL2tF5XSg&a{B&Drt4p8 zIj#*G4*p!k6!&KMn5dhWi#0LE2RytZ_+R*M#hf3n!cu9D$4fu(m&%d3gWAj9$-ZKX zdfgedY`ShTXZr9mObY`u9T?%uWlfVk$F6omhmNvU_>+KjeybecOduOQ%1%3tHD(!( zY_Vvl;QKop)M&e{2BdMNywh1ERIt~@V8RTV@dC=>=z2T0;{sL-Tm;PRq5J=L|4H05 zY_e1Ek)RdvIw$ySC12eqH@+t~_Q=dWS^SwC-y^ww^28p|_DK4H*RN#WD?K3M^ZPIf TMz~Y?uJ> delta 1664 zcmZ8hU1(fY5I%RayZPDOr1{w-&F;-^(rtEc(xy$)qzFls)>x}e6=`F771qn1lVt7v zS?1o~s3fe&r|ZeNN8Yuk2=fz{#6=Ww+P`$1n|N&>YlQhzX7F;jIhW z?Y6ZLm1oQx;_aedWcH%XPj#SqfXw+YPp*W`gS-=&yb^b6U8oI{PMJjr-=h4DTyx>i>U zH;-VU3%iSu$NRChBh;EImwH$#%=hgmHE}s-?3c$wza+G3?8KrK%n0AN7G$pO>-9)< zAf)xl0}X>M2QiHwMaZg0<{~3{=e!4w6%yhs?tcCt!>*I|d zX=wu)7(loZ%NAY`PTA!G3@9LTU;fdg=Z4U#MnNesOinnk{0r4knHy1`C)JWGMx*k6E&e~6r007p_`a?fzm=n4<`q1f)rfl|W#ZMT&t*qII^6_!614l+{QD%5DJXh?rG` z?Y)LGYn;AR5|yCrxkev6N$NDgQv?>p#Y>*!SS~N(7%X^}_|pV41kX`Kqg5_iu8-NE zkNo!9b;&O>9S2_|B2nv(*A@mw=uLIvINcBkzv8)gu(R^N%oEy#oXYAQ>H^}m+4I`5 z9+z(RTuLoOO9i|V?rm|qH@J!^$JT$!hU?|;bvIjJib|X!cm_ePhObYAluc3%iEI8KV*2#BX?u;BEPCB)1O-%Yej3Qoe8s&9=NNbo7t4O&!DU#* z$b0fmAy-dH&lpGLgTfEVHpk;jw(y5tyE2TnuzhHg-x{Mr`Mo>k)yv#90iq4)*j+jsI0)2B%3*roW}8EFx5?NE<`w}d|#xK0fHJE%>q zhAW;QoK|;LZKz!4mK&5y@H**gq-uQgLAGrzLK8!WfUj^1r-lg|&`>iYX^glU-#rf-Gowaf>`7Q?SU+vL{J$uLdx Ee>d2w*8l(j diff --git a/backend/modules/nlp/__pycache__/models.cpython-312.pyc b/backend/modules/nlp/__pycache__/models.cpython-312.pyc index 9536465f94cc698ca4434a7be50d434b058122d8..4eebfa54dfd716b31b0d75677d34ff2196a5b311 100644 GIT binary patch delta 436 zcmY+9ze~eF6vywHOnO zGJm3TEcHCa^l%WCdUt3&6;?JcLC&SXr1_Y;BkDO9d zh*~m?xnWXt$tO$+YRJHTm7y&~k^41vp|;>6yHzLZ((9#XQ7<~`V=`LiNGkT4hotL!5IIPi#>#I>pDui)uGiBAN(z^Q^gWe1Tz>~a?GxT5=PnI4` z=X8Pf$@0|)p25a|@MX*fvuS0*E<<q&ur9!%ah2uGbR6cB%o_H#gRnqZ*Z+xt5S9 zAdG2{QB!i9G96CZuvVhD&dsz+Ns{{XkO2qJ#q~%W=!KL-D1qz$72r({gb3E2(UbLO zGt<>wTP7h??#fbiLNg&hmR+blP1)5=jzT}&+b6U!DQx?Gl?YDm?8S^s27c=A`r-}n z50bro=YNiGV~)l_EhO`7O60JZ$*hof1!MfFA-s+6(bf&xdP3t*Xy_5yFWFRXNCmtf D-+Flr diff --git a/backend/modules/nlp/api.py b/backend/modules/nlp/api.py index 8f0587c..14e3b8a 100644 --- a/backend/modules/nlp/api.py +++ b/backend/modules/nlp/api.py @@ -11,7 +11,6 @@ from modules.auth.models import User from modules.nlp.service import process_request, ask_ai, save_chat_message, get_chat_history, MessageSender # Import the response schema and the new ChatMessage model for response type hinting from modules.nlp.schemas import ProcessCommandRequest, ProcessCommandResponse -from modules.nlp.models import ChatMessage # Import ChatMessage model from modules.calendar.service import create_calendar_event, get_calendar_events, update_calendar_event, delete_calendar_event from modules.calendar.models import CalendarEvent from modules.calendar.schemas import CalendarEventCreate, CalendarEventUpdate @@ -19,7 +18,18 @@ from modules.calendar.schemas import CalendarEventCreate, CalendarEventUpdate from modules.todo import service as todo_service from modules.todo.models import Todo from modules.todo.schemas import TodoCreate, TodoUpdate +from pydantic import BaseModel +from datetime import datetime +class ChatMessageResponse(BaseModel): + id: int + sender: MessageSender # Use the enum directly + text: str + timestamp: datetime + + class Config: + from_attributes = True # Allow Pydantic to work with ORM models + router = APIRouter(prefix="/nlp", tags=["nlp"]) # Helper to format calendar events (expects list of CalendarEvent models) @@ -217,20 +227,6 @@ def process_command(request_data: ProcessCommandRequest, current_user: User = De # ---------------------------------- return ProcessCommandResponse(responses=[error_response]) -# --- New Endpoint for Chat History --- -# Define a Pydantic schema for the response (optional but good practice) -from pydantic import BaseModel -from datetime import datetime - -class ChatMessageResponse(BaseModel): - id: int - sender: MessageSender # Use the enum directly - text: str - timestamp: datetime - - class Config: - from_attributes = True # Allow Pydantic to work with ORM models - @router.get("/history", response_model=List[ChatMessageResponse]) def read_chat_history(current_user: User = Depends(get_current_user), db: Session = Depends(get_db)): """Retrieves the last 50 chat messages for the current user.""" diff --git a/backend/modules/nlp/models.py b/backend/modules/nlp/models.py index b92a1bc..ddeba47 100644 --- a/backend/modules/nlp/models.py +++ b/backend/modules/nlp/models.py @@ -1,6 +1,6 @@ \ # /home/cdp/code/MAIA/backend/modules/nlp/models.py -from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey, Enum as SQLEnum +from sqlalchemy import Column, Integer, Text, DateTime, ForeignKey, Enum as SQLEnum from sqlalchemy.orm import relationship from sqlalchemy.sql import func import enum diff --git a/backend/modules/todo/__pycache__/models.cpython-312.pyc b/backend/modules/todo/__pycache__/models.cpython-312.pyc index 32eb8e91d2a054c942708cd635a64f30ea2255d5..54ad6662b9c02ae2fc55bf15d08efeae74ccee4f 100644 GIT binary patch delta 124 zcmaFIev_T|G%qg~0}x2dab#3ZMf)R*|Wr4&8W=2NF=M28r8GP?DsNZFf U`@+J-sMulhl>tZ<$pcjY0N=12F#rGn delta 147 zcmcb~{*ImZG%qg~0}wFwvt@KnljA6uxsD*G_UKjY-n9p-DP`0-`De7C<(|7mY`@VNicW+y-TI>^JIRa~G z*&GZftVVB7&TP1paKa6*Fk&tn*{&V$=e!f6qFao)>CKNyZiy0&hzz%QZj_5Hia4htdzE31{27jB^tStg-=o z9iRzIR)Iw3rU)K|zL2t|t{X#In{69!v}zq<>lsYY<=7LE9)?3M7Ztb8HhwoCPeDR# zFPD)u5KOgeT`9*oE4WX&s~^@SCw9$;Tf7&D#CT2J%pHL7)%-4ffW~brX&f*4Zx0AW z1{a=yE1$!xCcqyz%O~-~qoca)`5ZpGyY0IAz_>bZR}K6KGOzB~jTZ%=kuw_e&=dY@ zFAN5&uo0erI9@ppal9EAmt4Ty3`|+JkY%@e!Q+8kL$Qkp9fS%38pd<}ZeB~Y*JT&Z i@FVyi0l#G^rTe5_*dwREl9heZ+#|PU2lhLvW9?6ie6)E0 delta 1027 zcma)5&ubG=5PmPa*=Cb$w&|uxleQ*}V2PDtNkI^)KMqwq2p+sF!4mUcn#gVw-|m8X z5kc@E9>V?sUOXtNh(!DwL{H*vK`KZup1cX3oY`$9{%G+XhM9TaeDlp4-lK(=3)*{4 zOA^e3b1Cx2ElYEK@V0iq6*)-1}^C5bZEI-Cv0_Icy!;Gx8!}J!$ zSm*q$*oC4LR z{>fy?Usu*?Y4lim8Y|30c1=RGEP56XWY6m|G3#GakC%U`5k~+JY7u4hDri)Hpq`!% zF-I{Tlj46?SB+3Y%ImYH%Oe#l{$lbwG%lxJ&?YvnsnHZT@xOb(MW8TlahU%Eq87mX zF=i^dk9w@a{aM8HVN%n7sFfy45MHUx`_D91jUG2=_n2pKXBl_1?6f-EZaN|bIFa^i znesgi+`#w^1p&95y@iOLhYOM5fd&49K!Ux5uN=htO}Et%D@ayHgNj4}4GIZ2^CNL4 q;$9QyA%|bec?b5JL@C`RbNUWB_K8$?No9vLK9I)fW9BuLvHT}w8_u@? diff --git a/backend/modules/user/api.py b/backend/modules/user/api.py index 964b891..1804394 100644 --- a/backend/modules/user/api.py +++ b/backend/modules/user/api.py @@ -4,7 +4,7 @@ from fastapi import APIRouter, Depends from sqlalchemy.orm import Session from core.database import get_db -from core.exceptions import unauthorized_exception, not_found_exception, forbidden_exception +from core.exceptions import not_found_exception, forbidden_exception from modules.auth.schemas import UserPatch, UserResponse from modules.auth.dependencies import get_current_user from modules.auth.models import User diff --git a/backend/tests/__pycache__/test_admin.cpython-312-pytest-8.3.5.pyc b/backend/tests/__pycache__/test_admin.cpython-312-pytest-8.3.5.pyc index c7f94ca53d2ba330b678e525307df408e8cddefa..04cfef124065b10ebe9ea110f91cce8ab65ec685 100644 GIT binary patch delta 1362 zcma)6OHUI~6u!5e>1#S|nLePDN5JwJ0Sgo`q98#*P$_6oWI&tZw4vGuxh)G_$OhfG zB6n}xnZ}KA!VfUAbK%OE)DTv#+!z-oc7yj!5u_>6F1~zozH`pp@0__UEozJ62T`;k z_6sywR(G~UzoCS-I$JgjDO1|4m@!h3YD`(uR>i7wE@ev#ilB2oWlxKWsB=@wk#;Ih z#?5i7YEf~5Q>~kv;!oVrcpZ>z1aJa)0KC*8oHqG@*3wa-k@GW3m))nV1v`-;Y@yGEW}yeD-k^oP5o+m< zEa7&#$CUF-fquCki0;c{blSd+JGFhglW*>VBE3=ob_O5>&Ek8-$(Zd^Cx;5`KwH>(?Xu7nAzI)F7V2st&$XqttCTx!_fUyJVw-&BbP;P zl?5gX2GR#_m;ivCkP(3D%SZ&eXGTGu0k{Y-1~3kAi9takX5hz%QRLRLxjd-_MPKk` zUbqrue49hTFt4F=(8 zbl>jRezx@)H~#l{{qTmW8)8C4c2(N}xd}x_D;R=DSOKXA2r!@tcRfB!-^pI~ZGDy- zd4&bXwO_J;rA|g=U(vF%o=oMFnH&jFUst$%9dC81O9bvWfy+kVi_~YYyCl%0fCw}o zu&R>fLOQFir{bd|&K}_}DfflJcO%Al51~!;3Dxf+c^9?rqUNtCNWR7<0D(Js13MZ4%C-SmD=lr&W+j5I%eKKJvv_nc!p zoZFf+UKxf;#P9o7W%2I^MrTusJ{Uc`Mt#|lUE((R%@xH_C=oj0w^UR|jkV-!72VNe zo%D@L%1Omq_S2P&lZkb+-&!#pQ)tCg-4>TFNUpjrIhLz=`ff~ibrEaZA6s(`5zICb zFXg75Q5=wv{T4U9E@JWunw(8{gA zV>hb47cS6YNp2AqmgWzWkCUT9>ftH5U7|WKsw0Xa0(JV$9X>4;`71S*O~af3GC&q+ z=fA6C@*&6$-lz5QkFEX`J1nm2IvYc{h2Pb3xpBxiK|j<0FbE6*!~BVzr6c@DEvKCo zfmZPk{v>?EE^u3aLG5ruPbYIn;f*utP!qr;a11cGVSe$JLw;+z8j>;-u=u7qG}(KjI=8^Z_bvEPfnJuU**%*z_qxjNcuXcF5Bsy(qL4}Ze?k?v?}__PUH47 zz`N>wZWTnmn^te~s<3y3>9+e+l=&!oJL&9}xn)k2SC%H?4JN+wy)tv>_o|MhMG=^( zH?iZ`aR$K5*c5Q^ux7fCUOJEEB2WOPfeXMzfx5|>q4zf@l2)ogjdfrpegH1Z_gTr%fNeg0_H2gC%~ut%bw1@5g{Y9<^{DuLO(d_}!wmQbN8Gi@s#M)o-wVdetF^^( zapCy^Q-qD-!@=;@GCa!hjN)!EY*Qx;TQH1tOF6rpWQr|{OMC=_p9S6|D5V>OtdsAI e2I*=LyFvOJB=;*BY>?46N`e;nA4h(Wkmw(6KPce< diff --git a/backend/tests/__pycache__/test_calendar.cpython-312-pytest-8.3.5.pyc b/backend/tests/__pycache__/test_calendar.cpython-312-pytest-8.3.5.pyc index c5e604174324fda528fd25c3dc08263944b1feda..fa5001267d2d31fbf8d0eb3b63d046aa643d89d7 100644 GIT binary patch delta 695 zcmZ9}KS&!<90&0G-Jf^4yIf*SViKdN+EyKkbFp=icIc4F;ox;^pRK|@6ojrpnyD?- zcrGPF+ofZdAC`iYE(Ia!5U6I!pn_8ek&Z&4zq>+)_lC#!_u>2C2e02YezXn0>-(-o zr&>#`UAFuRbXs#W4LxMi<~C?T6GoVl4tJ7lhOYFumt-qU%QR0*pZm$o!i>!FY?AG8 zMCN!d$*FKu=6RlSO*l>91>vqb!V~b!6zQhPi^5;^hQ>suX*T%S5KNJ!Qb{R|kd+n7 zkyR8MB^y^PPgYf|KsGV7M!X#pMZ(D;{9ej1|c3j!esj`jTCkG5Z-q0irj-OMLw4ECY*p|KO+1c-&#hn@8VTF0A9= l2z8i^b~+EDLFaGzm^Pq}w)LCtD+2&dHLaZM4rMFa&s37*vPA~F#pyHZF&3Stfo zc&nE2V2O}Zdl8B9q#o3p2T8#%bT1+*coh7&c(LNkYE)(q%m4lM&&)9UxTS|J-Pv*+ zTchW2(K`2I)yc!l)v0m=e8!p3M9en>i(8;k*8N0ab34k0KM*8&GRkq^2^{VODV~aE z=DR_fr=x88gF%L8qHOs?L6&DJkBdYTxF_tYEd~UfHAJ#$@L}OplfSJ&$V7@T_g~4S zdE{Ry>ZHl?iVcz#6w8o}DmFwmrdXD&C>noH5^drUjw{7svXWvsvK@+zknL0~PgYi} zKsM30ndn-W7$uzS;~yI%+of2Mtb*U*O$?Iw)Hoi8JXY+`gA#6+S{CfbwcXcUIEd4; zCp}Zp@2-C~WTUoEUYO-rK6*M4yQazK>&s}Kn6cp|&Yzh#p@U1c2aG-J)i23A?fdw3 zA&j$Ey?L*^T$_{b#sNHXv6M4E^lXwvOS&7=7_L-oV7PtbHUkfDwI>+t!Ds8jHRphu z_w;^KhASOBw%K8D3gOWU+dSXEWD84+)%v3Bc7GOL(`MAt X>YwQSMF)U)n%2~oowxXY>m&REhcCsA diff --git a/backend/tests/__pycache__/test_main.cpython-312-pytest-8.3.5.pyc b/backend/tests/__pycache__/test_main.cpython-312-pytest-8.3.5.pyc index 57e4dd2c4727316ddae87e21e1b71ec8ec51dbad..06dff4a624899274dee7a818b7af1447cc52ffc9 100644 GIT binary patch delta 113 zcmew$a8H2uG%qg~0}x2dab##sjE`10&%eN^rs|PfU5r~VWfy4)9Mn=Z_ c3=Ay{&AfLRG(T{#FzV09`oaLDiqwGe0Gq8HW&i*H diff --git a/backend/tests/__pycache__/test_nlp.cpython-312-pytest-8.3.5.pyc b/backend/tests/__pycache__/test_nlp.cpython-312-pytest-8.3.5.pyc index 454d395395e4482b0f6a52a672697362a028cb34..b0d485d2598b75fda4dadfbfff4d58ade7a50c63 100644 GIT binary patch delta 2425 zcmchYe{2(F7{~jzTX*Z${phx~>)2Khvfc`Vfy@~;6t_azWWy-|2hw%B>w2T@)%R}7 zX3S7PM28VyLo{*0kZ6D)Q7<7HN6h{*hQt{8!`P^aF)_htH1R)TjPLi3v9c_Vgv2KO zZ?>+BxuUsd;enZ^X+-{eR|LPiq3Kh~Nj9lCRg?A(dego^ zAFZ6iDUA3I+qP5#xRZ_v`ZfO75@7^F7?J&-1Ie z-;n25bH6dqui<_We!?z!xxI3NurV@7i19s%6cN!_RqQNqHuE#kFl%v(RUvNXN@6K> zRLR7~HJQ@Q#+Z9WF{xlDygfzbe0Z|)36}L%v){a(q{V3VJx5kRg$n}hL7raVQD7I) z&*uE=NG1Ej-%EC}Ewzn8I}eL~x|t2vUU7C~j*B$}T1g4p9S~QC5imC-!rBO|16qKG zfhd~^eCITGTF2%hH9}lF6pJhLsPT5)Uk=h{oNCMpq?-NHwBPw47L>DCDBRr%b1U!= zu#j&X+z7A(hyo5^C(sA!&!Mmm!%k$ zwXB-aWNisa*zaO%ZzZ39qkw}B0{b~22<%~?h$C01D|$+%0s_Z@mw*vK0?ZxC>|*!Y zm?a{D89?R8dEy#>dwOgno=WjOshJU3^wH(j&AHO*$f210jGWOeDaP4`c0ZYB?(oi% zBgp>(@FI(cgCxYx4g}acVK4qE6*99wSPXZ=$l(KVG1{gF35UMVj`8P8yFO$>OLI)RQumS5gljzge+9o>kUoQrY!MMblL}v8dCEcKQgC zbpeZeZ8?H@&6W)w?3?OA@Br`>V17)@YQ%m-GU-_p%1*S3TClS-2=jhX;}0L1?km&q;R#wl z8e(IK`^YSNE%Aw`4H;JDgyC@|r7IbYCfUBxO(emlM;Tk4tl4X71_^UT3FWXpPG!ow zh0SWZM`6tX=YaFTB>+dFvm6&}6px@Gj+;V9T9w9A@>Y6{y`F4#{9xlBmE@NNnDH-c Cj1o!! delta 2397 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