From f2bbcb96f35e2c56c3e0bdae05389344667bd32f Mon Sep 17 00:00:00 2001 From: bolade Date: Fri, 26 Sep 2025 15:24:42 +0100 Subject: [PATCH] Refactor database models and schemas to allow nullable fields; update init_database function for improved initialization. --- app/__pycache__/main.cpython-312.pyc | Bin 3631 -> 3924 bytes app/db/__pycache__/__init__.cpython-312.pyc | Bin 169 -> 167 bytes app/db/__pycache__/db.cpython-312.pyc | Bin 1788 -> 1712 bytes app/db/__pycache__/models.cpython-312.pyc | Bin 5041 -> 5062 bytes app/db/db.py | 1 - app/db/models.py | 24 +- app/main.py | 13 +- .../__pycache__/__init__.cpython-312.pyc | Bin 174 -> 172 bytes .../__pycache__/companies.cpython-312.pyc | Bin 9573 -> 9571 bytes .../__pycache__/investors.cpython-312.pyc | Bin 9691 -> 9689 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 174 -> 172 bytes .../__pycache__/py_schemas.cpython-312.pyc | Bin 5067 -> 10708 bytes .../router_schemas.cpython-312.pyc | Bin 4539 -> 4537 bytes app/schemas/py_schemas.py | 217 ++++++++++++++---- .../__pycache__/__init__.cpython-312.pyc | Bin 175 -> 173 bytes .../__pycache__/llm_parser.cpython-312.pyc | Bin 13264 -> 13262 bytes .../__pycache__/querying.cpython-312.pyc | Bin 5346 -> 5344 bytes 17 files changed, 196 insertions(+), 59 deletions(-) diff --git a/app/__pycache__/main.cpython-312.pyc b/app/__pycache__/main.cpython-312.pyc index 8132a27985d4cb90f1599741e74d563c1440a779..b7576a75b10a53b4341e7f5db5d200909408bc78 100644 GIT binary patch delta 1568 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 OC#ZGXZI%>R%M1X(i*n`w diff --git a/app/db/db.py b/app/db/db.py index 27eace0..8097fa8 100644 --- a/app/db/db.py +++ b/app/db/db.py @@ -32,7 +32,6 @@ db_dependency = Annotated[Session, Depends(get_db)] def init_database(): """Initialize the database by creating all tables""" Base.metadata.create_all(bind=engine) - print("Database initialized successfully!") def get_session_sync() -> Session: diff --git a/app/db/models.py b/app/db/models.py index 0d7f8fc..a99459a 100644 --- a/app/db/models.py +++ b/app/db/models.py @@ -55,12 +55,12 @@ class InvestorTable(Base, TimestampMixin): id = Column(Integer, primary_key=True, index=True) name = Column(String, nullable=False) description = Column(Text, nullable=True) - aum = Column(Integer, nullable=False) # Assets Under Management - check_size_lower = Column(Integer, nullable=False) # Lower bound - check_size_upper = Column(Integer, nullable=False) # Upper bound - geographic_focus = Column(String, nullable=False) - stage_focus = Column(Enum(InvestmentStage), nullable=False) - number_of_investments = Column(Integer, default=0) + aum = Column(Integer, nullable=True) # Assets Under Management + check_size_lower = Column(Integer, nullable=True) # Lower bound + check_size_upper = Column(Integer, nullable=True) # Upper bound + geographic_focus = Column(String, nullable=True) + stage_focus = Column(Enum(InvestmentStage), nullable=True) + number_of_investments = Column(Integer, default=0, nullable=True) # Relationship to portfolio companies portfolio_companies = relationship( @@ -80,8 +80,8 @@ class InvestorMember(Base, TimestampMixin): __tablename__ = "investor_members" id = Column(Integer, primary_key=True, index=True) name = Column(String, nullable=False) - role = Column(String, nullable=False) - email = Column(String, nullable=False) + role = Column(String, nullable=True) + email = Column(String, nullable=True) investor_id = Column(Integer, ForeignKey("investors.id")) investor = relationship("InvestorTable", back_populates="team_members") @@ -92,8 +92,8 @@ class CompanyTable(Base, TimestampMixin): id = Column(Integer, primary_key=True, index=True) name = Column(String, nullable=False) - industry = Column(String, nullable=False) - location = Column(String, nullable=False) + industry = Column(String, nullable=True) + location = Column(String, nullable=True) description = Column(String, nullable=True) founded_year = Column(Integer, nullable=True) website = Column(String, nullable=True) @@ -115,8 +115,8 @@ class CompanyMember(Base, TimestampMixin): __tablename__ = "company_members" id = Column(Integer, primary_key=True) name = Column(String) - linkedin = Column(String) - role = Column(String) + linkedin = Column(String, nullable=True) + role = Column(String, nullable=True) company_id = Column(Integer, ForeignKey("companies.id"), nullable=False) company = relationship("CompanyTable", back_populates="members") diff --git a/app/main.py b/app/main.py index ac839bf..c32d579 100644 --- a/app/main.py +++ b/app/main.py @@ -1,7 +1,7 @@ import io import pandas as pd -from db.db import db_dependency, init_database +from db.db import Base, db_dependency, engine from dotenv import load_dotenv from fastapi import FastAPI, File, Form, UploadFile from pydantic import BaseModel @@ -11,6 +11,13 @@ from services.llm_parser import InvestorProcessor from services.querying import QueryProcessor load_dotenv() + + +def init_database(): + """Initialize the database by creating all tables""" + Base.metadata.create_all(bind=engine) + + init_database() app = FastAPI() @@ -34,7 +41,9 @@ def health(): @app.post("/parse-csv", tags=["CSV Upload"], response_model=list[dict]) -async def parse_csv(db: db_dependency, file: UploadFile = File(...), is_investor: int = Form(...)): +async def parse_csv( + db: db_dependency, file: UploadFile = File(...), is_investor: int = Form(...) +): # Read uploaded CSV with pandas content = await file.read() df = pd.read_csv(io.StringIO(content.decode("utf-8"))) diff --git a/app/routers/__pycache__/__init__.cpython-312.pyc b/app/routers/__pycache__/__init__.cpython-312.pyc index 476b0abe804dc321e1181a1337a6802ffa305393..b90f7c088531433e6dd327abe7f2cd617ad3d6b1 100644 GIT binary patch delta 16 XcmZ3-xQ20p9i#U|dn3lwi6vG5EM^5B delta 18 ZcmZ3(xQ=mx9i#6=dn4xfGNXw_Rsc6L1;PLT diff --git a/app/routers/__pycache__/companies.cpython-312.pyc b/app/routers/__pycache__/companies.cpython-312.pyc index 1daadddd1219a45e4959cbd524d08a9015e06766..2ab18c8913efe145fae4941c6d9378d0acfa12c5 100644 GIT binary patch delta 32 mcmaFr_1KH+G%qg~0}$|~ZRFBpW%QYB$!f%yx;c;ayF37q<_M|) delta 34 ocmaFt_0)^&G%qg~0}wn5-^iuM%IG)QlGTVgzRYNI4(oS$0JEkF7XSbN diff --git a/app/routers/__pycache__/investors.cpython-312.pyc b/app/routers/__pycache__/investors.cpython-312.pyc index eeeb4b1a557b73925577ee95122f6f23bdbdcbfa..76537986cb542ac2716e9dff34f64aa55ea41a59 100644 GIT binary patch delta 32 mcmccZebbxkG%qg~0}$|~ZRDEA%IGtBC94r*>gIc_f8_z3atZDL delta 34 pcmccVecPMsG%qg~0}$*A-^ewOmC(H0_%fr-cUb?*0|2}-3oifw diff --git a/app/schemas/__pycache__/__init__.cpython-312.pyc b/app/schemas/__pycache__/__init__.cpython-312.pyc index dd51e01e0423b0005807f32710022e441bd9c2c4..61947b41daa84537c4eb280160a9508d70cbceda 100644 GIT binary patch delta 16 XcmZ3-xQ20p9i#U|dn3lwi6vG5EM^5B delta 18 ZcmZ3(xQ=mx9i#6=dn4xfGNXw_Rsc6L1;PLT diff --git a/app/schemas/__pycache__/py_schemas.cpython-312.pyc b/app/schemas/__pycache__/py_schemas.cpython-312.pyc index a8e483af428fc605c28e7593e8731d6b12a88cf1..e923ca2d2ee0719a3c96b660f8a90ee6d3a82734 100644 GIT binary patch literal 10708 zcmdT~TWlQF8J^k8?0PTWU3(Yj=6Dh(Bnx33nvgbJ0wy*|z;Ph9fh?D0ymM@ivOBY! z87J(PN~VR%>61|_#X@~(B`N`lXv71m`UKCds-!}d8BtYLrB>}zsJEhu`q2MBbMef2 zjqQL$yVCr7_FVpR=A8fk{>$0lB$F`?J}>?J4>Pa!aok_IJBe z5aCMDu8p(WDAaa%Y7?wB2DNcdZIaa{pf>5L?PRr`P@D49rdVwnYBQeNG^_1`+HOy6 zhSg@FHs`7Bs^5|C`8zH%&zqrPb+(!hn4u9xH_YgnnxSZ_RLKX;jz=Y(oYrJgF~g53 zq#~QCDf}v3kSdBS85%8HuWC`={;|9V3YR&;6?vH}24ub%lmo?(94v#fU5v zqxDEWYNk%97l>|DiE4})(ljwcW5dHkW^`=$?5W|g(x6*<)GZx1g%fAbJTrdMjExMA z50}Qq2Tu%-<~z)2siaC(QYx9TQmLxRvlT2SN~M=)rHa);B+(#o^AMt$HJjh-Jk{lw6Kq#Bx9x~NbxMPb$fsa6}% z%QK`Z=>xTT$u1UZb&Ar+NCXPH2;_BcDV~`dT1su5JLw_G+}vYJncmkPr#WYcZ-Z@d zT5TZI z9UvkxcVw&{&nL{p7%9UckFmFE{3IsAXZV#Gp@vwKs7~np;u*D47s)FImCA;wv+kmz zPHD6%p%{tElvu71i9#<$h7DAv6lt*@m(8-t%ZuGh7O3;S=|sPiFi=ds5niDWDr^qCv>dw@-Ms_ zFascPahd34sxYZH1B%>u+-8RBDu~t^t>x(kRn%$ZqH0Fl_Y$Y5R%L4j^^gkh@^m|_ z&kP|i-%+}{f^xTVlz5Q!Kt6b@+q?CJ8aBK+uuXBlM>#BbZqODU^cKU9q7{Ym22#S@ zqw~RKE)W(z7r4wFOWBv8HY3ap&G)m~FQR<7@1GnHYt_iox1p|Xd#st&GPFLenpmAwe>kDGh#B;7##Pk{B|_1KvArj6gEzH znNh7m1`Ndju-T*%7t9b2Zk+Y916)@so8^QMgiukV+690=xnPDFpIb+qbKcy>nQ?`g zOO2Kk*(d(%;mLMqLa$)CxI%Z~9{QofQs;Z2;oI1VHr)#toh^Vt_hJVZEa;v1a~~1} z2)ZB10VMYz89>qwFYdwyB)B5|4ImrDi)Z|JVWY?kt7^M?ma;QY+a=5m&mVFSXG<@G zqO;JjMVNbHp}Q^U;JSRf?t;$mpyhTzM~+;Lx)6XSIfkkMhPlH95kZc5`XIzOed3-z z2~VGdr%%%D6OcPSU<6(!%#w1!hOZ`EIlOxK^!6YTYX`jmztL0cC5{HvvcV zZrHsQbTPTcL-sp3t62>(Ut-PCMTp2`N}8=0%#d3!^YDnGo+t7t74>>bsSt7E?1 zY^ILhBM!KZO~H&-7z0IZ9B*0PTA=l1i)3nb>pq9mrhFhXW}nt(@noAlomVzC04EQ? z`HbTkwZchib8r$y9t=|$I5A*3igoQUAKqOhQyuFOR#%o z-CjvK=i!v{aJs|pla{k`&($r?Y$PLZeVw~v?TPzc>|(+0Ht?&qJ3Wit;8*Q1leW0p zq0BEf3}Ty%Wi&f@7T5Hu3gRi%Ak&135Jb-sy?wmG*2iKS`W<-76-ZkFwADzqet6<_ zmQFf=p{O#1Otd~=g>QZ!+W=29>TqbBa(GrWD@YrVWSJ6OzYV4i3wjtfpmDVo)~Pkk3J2Dwb_?1);t;rOm3~rmYo3TCw1$rjjp>0exVf z57HwzAe+W6q0RB$K*gY}%GY>~W?rNg(Vdn9zaT2PxZ00GO8J&`$}% zv-}Z|%iOE{YpGXxIdC2jRF6R^$Vy=-g|I~VI&U~0CG<92UXEJPTnA@3paeax*uB3O zcr_r0&p!`5pfm=Fi80Q{$?=#tms130bw)sM9MR7iPM(h2!_gqmo#X2KMedd0Iqo8# z7aGUfWg(<;nbg(_%kf|_cE>%}M;pme@X7}r5n&=`Mkdtrs&-LjYL^e0F-2EY-HfVn!etm4IyXUibZbABK_b2h*n}JYr$7em; z7VrJ>g@w>kU;ocueyhG(K|U89@Hs z40G9?5Lzd9eA=`9W)Qw_>G%e3X9hFehdhvvGaZAy!H;+FKz(M(k&)#!vKU$a%Q|U{ zwZo0mFz*lHY4H#8+0D5J?6{60pNEm4x>M#dJc6Y`BvBw{oTZei#F)`!`UF<@BWVeQ z9>O{#&%&c)+H{rwfcAWK4r2^zJvj`BNpjnkvM)ky4!wr56MbN9X;tm+eay*t0sM&F z7?W&S?0>V@aWeY%FQqYkvXpH!BcXm_Ze(Hq;-NReLkWS0661FEv%%vqc&9LTV*c5M z@}(E7!7)zAExh>7{!hY(mcr@J1F`Uf%Rx@aAUS+91V6vn;!n2VyZg@F(fs8jAOT;u zI|A`e+(Cz8j6lR=I}962tgs|#YE`7O;*td9jHk7e#X()JE7I+8lu{5!MdTGXCFf~N zlMJ*u?g=Jd1I$4|2!Kzqi}BrR@rCqit5dQg-)nX{F}dxPytl4b;za+O&GBr+Eg7s- zM7RhbR4H%NH7UTGdR&uZ&ik;GuHQOuz>io-2F@tS#GpUpRe(rmR+9nmhrB#^~cWl@_Fjd~4I*APiC~im$eSf|+K_O318K!I>M?i5leUzmWyZ;>?Ya6GWS)Qf&rA%JbG!aG7!&9$|Xg zEc$FQ!L)2EQ-StMgfSY$teC3fZYG?v;K)F-h4$&cXCZvk0lP%#s?+MtfFGN`tZ ze6g*OOy`(|{4O-6g}LMNkkzx|_uk#ma5KQ=h62#mD_jp{7r+{CtT8(Yt8m9yHx_&H zOW89}y$20-pJUfyabTg-nWbzEjP!1pX6quP9Kk|=k?>ns+zg)xIDYc-`_R(f!d?wJ zUblVG7jmrFG~7>L6KD)J8O5Y zRJ}8wG82w~4#6#0VL zb@RaP9BW!_wgPv1PNaQNF=pCd$$3I}$0k+arn}vhhsD1Ep)vKW$;ZGy`P#Fx`#)yV zFg`}a*JxuHuh8lblnf4U%%&i&)qk=+-CIrAu(BmW^nsY%#SY|xRC_N z0r2`F=0_D=m2cPozfmP_N0SUx-d`V7EVZcrZ(s@}umDq>C4E&$iP(%9gN}+ioNZ-u zkk0*I#hM<9l@UW3U(L)0f{imXBMx>v;4I7mzs*2Khdan8zUzTT*KsSChXS$z%$SCE z{wqA2!3o0tr8V+ZM*8x z98rTm9~D}ylt$Z0+FGuGWtjDXr3H9u@K3U}O$IwwcHRv3nGCd?tpYqKl7GOX?*j4$ z_i52>i~4^5Wqp2Zd%=C*QYlw8_C&b9WElw+LnUY98JO<$RNa wujc&&(C1W>gRiE{=i$e>Cj9fTulXzwU2!xUfn^xM$^tJe9Q_x}U~SHS0Z4l5MgRZ+ literal 5067 zcmb7IO>Eo96&{MDME&_!j$CL1-$Zo2^%?IyA7WMeC6>}@tGwge-NZ6czm z4k^0|a`3`g!0Abg9^ylRUK?Z&K`%Y`So9KCDWD~`Xp0_--qKn{7CH63p(K-9rO685 zt@GR3@T zN_mMti$&QC=fh?s9}!51ED&9~Pjs0oRCp|TGv%Wk4+9>d;m2YNjd4@~H0nd+9E|}Q z_n`@nCIC(P&?HCu0PXjoeHi9@sLoG z7j%*j=|W!ALwQLT^Rh1G!@8W0=;6Fljbs$J|7vN2+Kx#}&a$JeQCC`?pPzG;<@p;| z=a#`eOxN-gF$`v=ZcyVQ3U0%7kFrUjrT}4$(nn_jFjj5_>>6Ie36RP^N zidOV`7@7l%qe!4gqUb}>58@Ho2T5LD&#qf0&059Ere9tCSKz0VY!pJmCBd96RG}k_0iVx#F00v>W zGmbODohRJkCIT*_bhwFuxkugM%a&QzO4YAXlk>Pyibm-U)r}Ivk9A`OZ}>MQXS~NU zZ@|rWU`^zwiEXSR0! z!CQ4{qA@YGb!BJ0WMBL6z{6F}jqB7dFoS1WH?e9}N;=imD%F@9*`&8^!=Y~YHeIzC#RLs0 zjTTywoNox-LWFC71H?mePxvHuPtb)svp|vztq``DP$f<~D8Lw}GedjtED+x^gWoy zUIej4o`*>yxpQGx*j4{@`1BLu$&KGe8pESs#z$(}uZEw+k3A2G$)jJ6j_;oRh|NlSNrh^9R3ap?#x&hFjNJ@JnF^^Ma{NN>a1HjdmrImx$zu! zpg04UeFsF_y)id7`Uba`JTZB4>ssyb?upNi)uoe-shO?C+U)N6&%pO*8pkHL7Ir?W z6&`$CmnQ!%r)od_&FnMzd_x}icSw;3_eB!s;_c@WJibT;6E3bE&}}E={{ngrblW@O zLTTyu`mTg~5Z-x<`#+Bz-0Pu&m-Hx)2{DKXn5N^MRKP3owx8r47QYn`aS)0}93UWTjN4F69$=`urJ@Lt0ydfD4NcA!{*i~DTA z-hx&ZO>AFj92%=jV*xpsu1o3076&ZR!d_L`C97E3CE66sX^wXH9SjSMuG5ljY|ymF ztHsiAqSDgdsUZz9KfSoPlrA%?Ky3)7Yc8Y^JStht9WGnUS+$CWr51RdVNlymI24W{ zCNCXrH)8V=-wvqYb(S*h-{u?G$%mjx6|OEj$z{6Zl^ao2-72UmXWc76euOU~DLnG9 z8`wIDf?FOI;5}{UI(DGA370(w;#2a4^n<_k9j!}88`-l@rP1BguDLgMx-OlCX9!W# zPe)Jf4e{rxX$Vp)wbOga<8^7eyBxu30}AWd%sTY=ZH9*le%t~(@YkLE-~|}gozYgo z!D~^#Vt~b47`GvQK$D@`40l3If}e`xt;B)m;zm4*;+ru#tZeI5U7Zlhck!?41^VV7}dL1DsW;~^OW-}DUM{o-E#P?}31FND%%)M*d1B|4FjVa9EhA6?Wfl5@= 0 else None except ValueError: return None - return v + return v if isinstance(v, int) and v >= 0 else None class Config: from_attributes = True class InvestorSchema(BaseModel): - id: int - name: str - description: Optional[str] = None - aum: int - check_size_lower: int - check_size_upper: int - geographic_focus: str - stage_focus: InvestmentStage - number_of_investments: int = 0 - + """ + Expert parser: Only extract investor information if clearly identifiable. + Leave optional fields empty if uncertain. All numeric values must be 0 or greater. + """ + + id: int = Field( + ge=0, description="Investor ID, must be 0 or greater. Use 0 if uncertain." + ) + name: str = Field( + description="Investor name. Leave empty string if not clearly identifiable." + ) + description: Optional[str] = Field( + default="", + description="Investor description. Leave empty if not clearly available or uncertain.", + ) + aum: int = Field( + ge=0, + description="Assets Under Management in USD, must be 0 or greater. Use 0 if not clearly identifiable or uncertain.", + ) + check_size_lower: int = Field( + ge=0, + description="Lower bound of typical investment check size in USD, must be 0 or greater. Use 0 if not clearly identifiable.", + ) + check_size_upper: int = Field( + ge=0, + description="Upper bound of typical investment check size in USD, must be 0 or greater. Use 0 if not clearly identifiable.", + ) + geographic_focus: str = Field( + description="Geographic investment focus. Leave empty string if not clearly identifiable." + ) + stage_focus: InvestmentStage = Field( + description="Investment stage focus. Use SEED as default if uncertain." + ) + number_of_investments: int = Field( + ge=0, + default=0, + description="Total number of investments made, must be 0 or greater. Use 0 if not clearly identifiable.", + ) class Config: from_attributes = True class InvestorData(BaseModel): - """Comprehensive investor data schema for LLM processing""" + """ + Expert parser: Comprehensive investor data schema for LLM processing. + Only populate fields with clearly identifiable information. Leave lists empty if uncertain. + """ - investor: InvestorSchema - portfolio_companies: List[CompanySchema] = [] - team_members: List[InvestorMemberSchema] = [] # Changed from TeamMember - sectors: List[SectorSchema] = [] + investor: InvestorSchema = Field( + description="Core investor information. Only populate with clearly identifiable data." + ) + portfolio_companies: List[CompanySchema] = Field( + default=[], + description="List of portfolio companies. Leave empty if not clearly identifiable.", + ) + team_members: List[InvestorMemberSchema] = Field( + default=[], + description="List of team members. Leave empty if not clearly identifiable.", + ) + sectors: List[SectorSchema] = Field( + default=[], + description="List of investment sectors. Leave empty if not clearly identifiable.", + ) class Config: from_attributes = True -class CompanyData(BaseModel): # Renamed from CompaniesData for consistency - company: CompanySchema - sectors: List[SectorSchema] = [] - members: List[CompanyMemberSchema] = [] # Changed to match model relationship name - investors: List[InvestorSchema] = [] +class CompanyData(BaseModel): + """ + Expert parser: Comprehensive company data schema for LLM processing. + Only populate fields with clearly identifiable information. Leave lists empty if uncertain. + """ + + company: CompanySchema = Field( + description="Core company information. Only populate with clearly identifiable data." + ) + sectors: List[SectorSchema] = Field( + default=[], + description="List of company sectors. Leave empty if not clearly identifiable.", + ) + members: List[CompanyMemberSchema] = Field( + default=[], + description="List of company members. Leave empty if not clearly identifiable.", + ) + investors: List[InvestorSchema] = Field( + default=[], + description="List of investors. Leave empty if not clearly identifiable.", + ) class Config: from_attributes = True class InvestorList(BaseModel): - investors: List[InvestorData] = [] + """Expert parser: List of investors with clearly identifiable information only.""" + investors: List[InvestorData] = Field( + default=[], + description="List of investors. Leave empty if no clearly identifiable investors.", + ) diff --git a/app/services/__pycache__/__init__.cpython-312.pyc b/app/services/__pycache__/__init__.cpython-312.pyc index 0bd9599e36d2b529c881d563ecbf2e1b715eb3f3..b3e9b6b2809b3af17ae954c4046d7490863f7294 100644 GIT binary patch delta 16 XcmZ3_xR!B(9iz`gdn3lwi6zzmERF>t delta 18 ZcmZ3>xSnx>9i!hwdn4xfGNXw_)&MtP1;zjX diff --git a/app/services/__pycache__/llm_parser.cpython-312.pyc b/app/services/__pycache__/llm_parser.cpython-312.pyc index d575eb3657415b6523f0aa7c085a5dfb53ad14d5..0837f36ce41c6407c744f84ee5dfeac14a422488 100644 GIT binary patch delta 33 ncmcbRelDH+G%qg~0}!x8UE9bl&BEw6S)Ij*F?DkcONl-Jq4EgP delta 35 pcmX??ej%OvG%qg~0}uq8T;0em&B7QkS)Ij*Iljzja}-O7J^;8F37r4{ diff --git a/app/services/__pycache__/querying.cpython-312.pyc b/app/services/__pycache__/querying.cpython-312.pyc index df4cdea36f826bb74ed78789e9256cfe0c1ea1f1..cadd1a498dea270518b95482a0eee754bc1bb677 100644 GIT binary patch delta 32 mcmaE)`9PEFG%qg~0}$|~ZR8SRWAvFU&t}A!x;cccj}HKawFjL5 delta 34 ocmaE$`AC!NG%qg~0}z}K+Q=os#^^U$p3R6kzRYNI5L+J~0Hity?f?J)