From b1bb41895547402bb2e42bc10ec4efc6ebe355cb Mon Sep 17 00:00:00 2001 From: Castrokimaru Date: Tue, 2 Dec 2025 22:37:52 +0300 Subject: [PATCH] lab completed --- .github/workflows/canvas-sync-ruby-update.yml | 31 ----------- lib/__pycache__/models.cpython-310.pyc | Bin 0 -> 3500 bytes lib/debug.py | 38 ++++++++++++- lib/freebies.db | Bin 20480 -> 24576 bytes .../__pycache__/env.cpython-310.pyc | Bin 0 -> 1848 bytes ...f48c_create_companies_devs.cpython-310.pyc | Bin 0 -> 1055 bytes .../7a71dbf71c64_create_db.cpython-310.pyc | Bin 0 -> 684 bytes ...c123def456_create_freebies.cpython-310.pyc | Bin 0 -> 1178 bytes .../versions/abc123def456_create_freebies.py | 37 +++++++++++++ lib/models.py | 50 ++++++++++++++++++ lib/seed.py | 31 ++++++++++- 11 files changed, 153 insertions(+), 34 deletions(-) delete mode 100644 .github/workflows/canvas-sync-ruby-update.yml create mode 100644 lib/__pycache__/models.cpython-310.pyc create mode 100644 lib/migrations/__pycache__/env.cpython-310.pyc create mode 100644 lib/migrations/versions/__pycache__/5f72c58bf48c_create_companies_devs.cpython-310.pyc create mode 100644 lib/migrations/versions/__pycache__/7a71dbf71c64_create_db.cpython-310.pyc create mode 100644 lib/migrations/versions/__pycache__/abc123def456_create_freebies.cpython-310.pyc create mode 100644 lib/migrations/versions/abc123def456_create_freebies.py diff --git a/.github/workflows/canvas-sync-ruby-update.yml b/.github/workflows/canvas-sync-ruby-update.yml deleted file mode 100644 index f8818dc0c..000000000 --- a/.github/workflows/canvas-sync-ruby-update.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Sync with Canvas Ruby v2.7 - -on: - push: - branches: [master, main] - paths: - - 'README.md' - -jobs: - sync: - name: Sync with Canvas - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: 2.7 - - - name: Install github-to-canvas - run: gem install github-to-canvas - - # Secret stored in learn-co-curriculum Settings/Secrets - - name: Sync from .canvas file - run: github-to-canvas -a -lr - env: - CANVAS_API_KEY: ${{ secrets.CANVAS_API_KEY }} - CANVAS_API_PATH: ${{ secrets.CANVAS_API_PATH }} diff --git a/lib/__pycache__/models.cpython-310.pyc b/lib/__pycache__/models.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d8efd155563678ef64487412270f4685e8bb3d47 GIT binary patch literal 3500 zcma)9TW=&s74GWGbWgiyJl;6VCWK&Eav509ENqZKF~-DZAt3w^CwXXrTJ5f~-FEl% zY}MGwjK&hkE0LG|1t@6uasN`i@|0(u*cbRt^<3-~k+!TpbLxKTt8>0Ou3D|oLiy(h z{d|4Jvi?Pt>%~Q72cP;1f?J#wR>@*k+Ob_au~WLSTY9m_sLw7Mr62oc5C^926wNY> zL+CE|au%-$Ppt696Bb7z6cP8KwSH&ufHxmoyeV2&PTWR4p~Kk|IAI{85Z`W49{K%YpVk9*o4Xkh*a&lKJ3R2Y(WybT1vHU0X*| z6zM3h2I?dqYX30J&ZIc%GTq@KD^iKR3y~bAN@)A&Z1UmJS@O>Nqx7&4$sjF7SD~7j zeUkgj7Azs86g;^;5{s^34lGErYH%S2v@IHg66SE2lhGlrmj)_3_|z$cuwuro*yb#D zge$x&0L+~ycHBVCzp}1a9MtX5nj$2S0j>?0L+%4q#+y8R;>HnQ;n8C&Zt)gxLLBBo`}LSH2DAyl zWLOQ)fvQm2*%KE!II0J#7wdEF9v2t)=F=SAR05E2tSr}YR2@_oLKf*zWenAMA>F~Z zi|^lU2+pR~sr3&4@wEf9o&8C3Yi9Vy3$_h=T)HIsRiZe0Zpj~D){FiANmYveSzh+{ zs_eYPO{o4zWG5;+sj8wsJi&EuKIjj}qmyc|Ief4=GkbF+aXcaWMSj>XD=rGv8;*65 zBvK4zlH4Z4Y=}0SbY_P1=A9XZ&b$Or=yvHSY99i(V^b(yy3CroBm2}jb#c4w(wpL@ zFB>CoYEPXh4$R#r?xjC%JZ((`3=mk4=B8SNoe8ZkrGP5(aIEt6B38{ zfOlQp%txX$9;>~Jv^W>q!JWuknAL6Swt7^gMRp>}aj%l4d>75y{Rp_o2&#Oa#2Pg^ zDd)O@t1R=8_OhZi-FeE{PwLFl+b+wK>|K*`@s%xaMwZ@k0#P(J@8dtn&@D zs18KL+N{AkEMx)xTsB#s<9vPi4Y%P@X@3!vqH2As))^oSUSH6Sg+hBs1J5{SFh`&|g4EpH1vxgp=8w(pVnK8Ynn1|354=hXfq zh)IMQOK!2zG%uvn4bd)&_8(b)w~iQj{o?>0&Gx|bSIiLR4bx~MO?p5R--P&^HMRZ{ zT(T)UwZ5{>?9V|nk8EyXD%*d~Ol;!~wR`s^&5?T~7T2kpTgPG`z8uQ!U($+Xll|8_ z*5odkE=48~;5?}YqPJC4Sz4&=-eLxpb@2WeB)fLaCx%MQ@@69fh2HPwI^=|kPH_kP z`|>6k9c^C7VW_@~PkjP0wNG)_Gh4m~j zf4v$1dc+fy=p2|&(p`0%wQGDEH^?3a$vz1a{*C&ihB*zShEEnm@RCdDrXjubi*)=U zmQY0AAtJvfNutPzx&N882#UqX{qCy#6>Ydp;@2d0NDv$*vgL0`TZZ-`swKU-bx{AF zw2w(Fopf>WCPe7O#-Mo|&!aeUOn-*{8-?6s2cMciyiyFCB*-K?Mx&Gmj!g;AyzZHL zBwD-y_xF(uwV_igMEWWvL`Z--vxr~gEqHdjj%cEwI>IMD2buM9K8b3gMKXk1O$4uD zSj|Zc+PsiHcdtc|H@6+TS_b>eJJD4cM4z+yknUJ3Z8`T#BwUKU28XHHlDmS`r?WBgtO^}fz{XY)UEhK=0QNoe2=7stU z!%V!r%_gtU&Ac&UzkBPIoo$&ZPzdV=P)~BM!`bTwy?$U!a2N~kl9_)XVSH~Xh#Jf_ z{uathuSo~5Nn}TOQQ(P0-t-cN%X~-D?$@Hh1Oo9z{lJ@Op!7|@xt!AzUygd${$Y?! z8UV}ZX?~pzn7qI|5atmvFUQhoqmku0*s34nZHAhnjQA}JMl;uO{~J1?jU#NVzwtk4 CPVsyI literal 0 HcmV?d00001 diff --git a/lib/debug.py b/lib/debug.py index 4f922eb69..1b30f66ac 100644 --- a/lib/debug.py +++ b/lib/debug.py @@ -1,9 +1,43 @@ #!/usr/bin/env python3 from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker -from models import Company, Dev +from models import Company, Dev, Freebie, Base if __name__ == '__main__': engine = create_engine('sqlite:///freebies.db') - import ipdb; ipdb.set_trace() + Session = sessionmaker(bind=engine) + session = Session() + + # Test relationships + rick = session.query(Dev).filter_by(name="Rick").first() + print("Rick's freebies:", rick.freebies) + print("Rick's companies:", rick.companies) + + google = session.query(Company).filter_by(name="Google").first() + print("Google's freebies:", google.freebies) + print("Google's devs:", google.devs) + + freebie = session.query(Freebie).first() + print("Freebie details:", freebie.print_details()) + + print("Oldest company:", Company.oldest_company()) + + print("Rick received MacBook:", rick.received_one("MacBook")) + + # Test give_freebie + new_freebie = google.give_freebie(rick, "Laptop", 2000) + session.add(new_freebie) + session.commit() + + print("Rick's freebies after give_freebie:", rick.freebies) + + # Test give_away + rick.give_away(morty, new_freebie) + session.add(new_freebie) + session.commit() + + print("Morty received Laptop:", morty.received_one("Laptop")) + + session.close() diff --git a/lib/freebies.db b/lib/freebies.db index 12beb1c963e832db481e7a7493e3029e691ac4dc..7ad3da6c0031734effe33f4d527b29b81f1fcb68 100644 GIT binary patch delta 672 zcmZozz}Rqrae}lUHvvb$LYY8!DY*Fuxq7<$DR{d^Y9JJ7Dg?Q@xdyrVIlBfc zK!ibxH8N8)@mK(KoH5WH@jx2YV2G7>!2gN=5&sqbBbx;Uw($G#v9K`6GPxxtrzYj+XR}}7VP;{FWOC2X zPtQqZKgY*}Cd-H{3o-E)1OIpaxBO4|Zvjm_#c##I!ptDzgSp->t0!)mIzKO|BKvy%rU}olL2J7O4>0;tz0%_ueX=37M1nJ@AgzEtS D8eq1! delta 120 zcmZoTz}T>Wae}lUD+2=q2*UvLL>*&MRtCLzSzi7h3@m(74E((OJNfGQq&5o*EaTlQ r#dk}P$285{DB08^Db2(pd6U8yej#K5UXW1&K-Ks8Cr*%NL*)VhkJ1_o diff --git a/lib/migrations/__pycache__/env.cpython-310.pyc b/lib/migrations/__pycache__/env.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..71161a74661a14311c1c3fe5043f3d0554058e14 GIT binary patch literal 1848 zcmZux&5ztP6t^>(%xvakw}n^i z?rya`l?xJ8#f9_kk$)*yPW%fLRGyuk?zZ5_FVBAV`>=mMm!nZku>E>-BKG=({NV=Y zTL%YUVK={^$VpBmDd?0^rw1}9I@6BVJE(`#(CeY>7SS}K1fo@M+JoMzpLc7jKLzUa z7wzsyZWQq}##QlZFdgQ@yq|CU6i!E|#rXiWF+|6kCq&$4`(bK*j?1aJKR7MX|T0cnRB*o6cs!S zau>UKg2Iwxn$r{doY-L1IU+X9gS?Z6g67?qShNj}yC>w;$ZOFFCi^|fqmYE;g*%?; z5xGgsC;M2q`+mUg=8_)&217lp6)VI-b1O<^m{9C`IiE``;yNqJ9CqTEVSBt3hP4IN z8Vs{ba6?xO+ZT4pR<*H=v+o{$>(_IYGgab@Vqg0sxq(~Cda*p4Vd#-(8B~_fB=}uR z(7?E1`yk~GV|Naj*%MVI)WQdBJ+VxK&(?3*2bP!Wx@GVb6jJ~>W^wP%?FaXnE!hm+ zJ>^2W2&a|Y>? zjm?je%WMh7;ZCjP<0h`S=7q6`5}K~!1>{NCbkNjnTCNvh(*i8dx#i7B3JaRcbS6}8 znqe-ugv_R8WzBBVYohktn@zuq3*{_$Te^$jXg1#7iXOP}g&80OQ>(c$Jag-sv948m zcF76Vj&{Ej{Q>^|dNNs-1x)rtF}YV}bpgtniG^%wvL)hnQY{gw+qWjwA>N?cu5NA5 zHNZ^3Hpa;IKu@HYP0rj;Kt0{54x7vGMomv)broZp4^hO!kOuyXX!Lj7i|MsD`Vt!6 zVMBlu8`wP?enZ6)OOFFfSDh1Ng$-BTJb2l8PL9YiV*l06=hPz2kEq>n9C?Whu)X6L zEkmyjPWjPY^FwVRJ8qn32eRj_)zSX_F|NONe!W|hM9+TyKPsvJFzLQRBq8)o28wG@ zBG_BlI!HQXBV^a4c}pd3OqmI9bGTIq54_lxdFQCOM&sZd8k3-jDh+dS&}_JOD3j>y zanfnxGe<3QHZ`ambjnRS<2GCFCPUr96W3!D&A_40w1Jz8E$C9A#ClGLZdHG`mhu6H z@sFL$)1y>xIX@1c`hpV|QD9<&(-a&%^%ZAuh-`&}NOS3Z4Egi?98JdIC_vBzG^Ei# zafFgaZ{jefSKo|Z2ifgc5cOAV$4x3!D#Xzer%0sEXHz1CkWwL4ND-o(aak&Fx?2n>Rm&_NVZhSoOCMC`( zf{p!Nr`KC#~NR5o^zWn&jn+8l}%r?EP} zI}||^oZ=&zLc7t4UKnppVid-Wwb6)4tk32)Qo~3MBlc~?sm@f98=Dv#eN)p*9QXfl zsw@i$*O0{eRMv0llSV>bV0SKErD-%zL0UA*;Eil9*ou;bUW99ixU>|@Er%P}gKU%{ zgvB<&5RtSeEL~+(I%l+i3*gc|FE}R4!&f}XBEEhJ>j|Tx;88-0uNproFYw4_VOeJt%N%R1XZ5-(8adqpbZI_<=iyz|FU)rkc zz18+1I;FN7y;292su(w?d=K}zjizOk9D0Paykzi>jM7t;$U0%~=(ey&xD*x|&)CZadz7@1F&_PcueVDLm5=Uno5-t>GYPmZhu5GxzWP0sQL_zW@LL literal 0 HcmV?d00001 diff --git a/lib/migrations/versions/__pycache__/7a71dbf71c64_create_db.cpython-310.pyc b/lib/migrations/versions/__pycache__/7a71dbf71c64_create_db.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..484a614794115d4ba9dc732e1ac7822e52b46918 GIT binary patch literal 684 zcmZ`$J#X7E5T!n1$#mSI9lC1upwNmc8xV@3K)iJE(4at}MUco#C4>@HQcmE``2+bG z`Ab|ob?(-wq+K9xfgW*>_rT-v9Z$^X7#Vv^Nc+h_=({DS<{9$dxU#@dftbTw?sRV9 zIyUyWSNO~?&X`wBj0eU;hS`J#4}LKo`bAg9fBFU(x<*gV_6fi_rm`TAi$ws literal 0 HcmV?d00001 diff --git a/lib/migrations/versions/__pycache__/abc123def456_create_freebies.cpython-310.pyc b/lib/migrations/versions/__pycache__/abc123def456_create_freebies.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a4daa8b0bb56dbc01b3f629e0c8a15bb08788398 GIT binary patch literal 1178 zcmZuw&2G~`5cb-R|C*$tRH7gb5w{#tr%79?2qC0Yl`5nNQBJv7j&~EgwRg>~6G+co zd57f4EA5pNZ-6*4{s{?`wRS!8&FnWjv$L$xa1H9(9%h*|k;5$geB|AQFVo+0ea5X3U^-WuV0!Eay- z@J59Kd(WxCaGlyFZfFrm9kn@D-$P(Rm#ElbA?5%1Gi-KOrAvZQ;jrA`MIy zUWBC+uq5^A66E`ODZ|AagQYdS^EQ;;)~gc12}0;O=e-GB#g-?#Tgm`lZfo0Ig(}K= zdH-HkoJtkGG=?mmCsdl(G$S*@rE!z-h|c8U72_nD(YItdWK?9_k7y>*R35(LQR4IE zUxsfAKY{?o^6Rr3vV^#IQQ}^*V4e_~2{$7_D1wl&*iA!UkWSxCms!YYC+&BtG&>L_ zxFg(+qlueDGwx^5n!;TWp7*G5ciYITa@myVI9*C}p28+f9>ZD0AuNV^fHvO|Izkq* ze)4Bvc+hV7Q!Co72}0R!YgApXI^qVPZMCeTgE>pf8g8>LrKjK~ZOlH=;v6qP6?x^G zDt}%w)ZjO2?@811Fbh0Sntn`@NfcDv;$!T`K}eD%e*~`5;?)b4jhxoosuS+hAoQTa uNGzm-NlGXd9-~EqMZEtW&w7 None: + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('freebies', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('item_name', sa.String(), nullable=True), + sa.Column('value', sa.Integer(), nullable=True), + sa.Column('dev_id', sa.Integer(), nullable=True), + sa.Column('company_id', sa.Integer(), nullable=True), + sa.ForeignKeyConstraint(['company_id'], ['companies.id'], name=op.f('fk_freebies_company_id_companies')), + sa.ForeignKeyConstraint(['dev_id'], ['devs.id'], name=op.f('fk_freebies_dev_id_devs')), + sa.PrimaryKeyConstraint('id') + ) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('freebies') + # ### end Alembic commands ### \ No newline at end of file diff --git a/lib/models.py b/lib/models.py index 2681bee5a..caa25138e 100644 --- a/lib/models.py +++ b/lib/models.py @@ -16,14 +16,64 @@ class Company(Base): name = Column(String()) founding_year = Column(Integer()) + freebies = relationship('Freebie', back_populates='company') + devs = relationship('Dev', secondary='freebies', back_populates='companies', overlaps="freebies,dev,company") + def __repr__(self): return f'' + def give_freebie(self, dev, item_name, value): + # I decided to assume the database session is managed externally, so this method just creates a new Freebie object and returns it without handling the commit - that's up to the caller. + freebie = Freebie(item_name=item_name, value=value, dev=dev, company=self) + return freebie + + @classmethod + def oldest_company(cls): + # I assumed the session is managed externally, but for testing this method, I set up a direct database connection here to query and find the company with the earliest founding year. + from sqlalchemy.orm import sessionmaker + from sqlalchemy import create_engine + engine = create_engine('sqlite:///freebies.db') + Session = sessionmaker(bind=engine) + session = Session() + oldest = session.query(cls).order_by(cls.founding_year).first() + session.close() + return oldest + class Dev(Base): __tablename__ = 'devs' id = Column(Integer(), primary_key=True) name= Column(String()) + freebies = relationship('Freebie', back_populates='dev') + companies = relationship('Company', secondary='freebies', back_populates='devs', overlaps="freebies,dev,company") + def __repr__(self): return f'' + + def received_one(self, item_name): + return any(freebie.item_name == item_name for freebie in self.freebies) + + def give_away(self, dev, freebie): + if freebie.dev == self: + freebie.dev = dev + # I assumed the session is managed externally again, so I'm just updating the freebie's dev without committing the change. + +class Freebie(Base): + __tablename__ = 'freebies' + + id = Column(Integer(), primary_key=True) + item_name = Column(String()) + value = Column(Integer()) + + dev_id = Column(Integer(), ForeignKey('devs.id')) + company_id = Column(Integer(), ForeignKey('companies.id')) + + dev = relationship('Dev', back_populates='freebies') + company = relationship('Company', back_populates='freebies') + + def __repr__(self): + return f'' + + def print_details(self): + return f"{self.dev.name} owns a {self.item_name} from {self.company.name}" diff --git a/lib/seed.py b/lib/seed.py index b16becbbb..e0f93bb24 100644 --- a/lib/seed.py +++ b/lib/seed.py @@ -1,3 +1,32 @@ #!/usr/bin/env python3 -# Script goes here! +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker +from models import Company, Dev, Freebie, Base + +if __name__ == '__main__': + engine = create_engine('sqlite:///freebies.db') + Base.metadata.create_all(engine) + Session = sessionmaker(bind=engine) + session = Session() + + # I'm creating some sample companies here to populate the database with initial data for testing and development. + google = Company(name="Google", founding_year=1998) + facebook = Company(name="Facebook", founding_year=2004) + + # Now I'm adding developers to the mix, creating instances for Rick and Morty. + rick = Dev(name="Rick") + morty = Dev(name="Morty") + + session.add_all([google, facebook, rick, morty]) + session.commit() + + # Finally, I'm setting up some freebies that connect devs to companies, like perks or swag they received. + freebie1 = Freebie(item_name="MacBook", value=1000, dev=rick, company=google) + freebie2 = Freebie(item_name="Sticker", value=1, dev=rick, company=facebook) + freebie3 = Freebie(item_name="T-shirt", value=10, dev=morty, company=google) + + session.add_all([freebie1, freebie2, freebie3]) + session.commit() + + session.close()