From 03c31799deec22ac810d570363a20ae21acda392 Mon Sep 17 00:00:00 2001 From: David Amedi Date: Sun, 25 May 2025 01:11:43 +0300 Subject: [PATCH 1/5] Implemented Freebie Tracker with migrations, relationships, and methods --- Pipfile | 1 + Pipfile.lock | 524 ++++++++++++------ freebies.db | 0 lib/freebies.db | Bin 20480 -> 24576 bytes .../1224ea744733_create_freebies_table.py | 31 ++ lib/models.py | 37 +- lib/seed.py | 37 ++ 7 files changed, 454 insertions(+), 176 deletions(-) create mode 100644 freebies.db create mode 100644 lib/migrations/versions/1224ea744733_create_freebies_table.py diff --git a/Pipfile b/Pipfile index 63c79cd98..5c202036e 100644 --- a/Pipfile +++ b/Pipfile @@ -9,6 +9,7 @@ importlib-metadata = "6.0.0" importlib-resources = "5.10.0" ipdb = "0.13.9" sqlalchemy = "1.4.42" +pytest = "*" [dev-packages] diff --git a/Pipfile.lock b/Pipfile.lock index 3923f4a97..cf65e3c2b 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "fa62c636b7ae5acb4993fc7b007a651c55b562aa29962a9a8585ec314b352ae6" + "sha256": "6b7e349bbbb29f4ad52d5c0ef631d40060f7afec7d3db3552b729b004ece2601" }, "pipfile-spec": 6, "requires": { @@ -18,26 +18,20 @@ "default": { "alembic": { "hashes": [ - "sha256:6880dec4f28dd7bd999d2ed13fbe7c9d4337700a44d11a524c0ce0c59aaf0dbd", - "sha256:e8a6ff9f3b1887e1fed68bfb8fb9a000d8f61c21bdcc85b67bb9f87fcbc4fce3" + "sha256:0a024d7f2de88d738d7395ff866997314c837be6104e90c5724350313dee4da4", + "sha256:cd0b5e45b14b706426b833f06369b9a6d5ee03f826ec3238723ce8caaf6e5ffa" ], "index": "pypi", - "version": "==1.9.2" - }, - "appnope": { - "hashes": [ - "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24", - "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e" - ], - "markers": "sys_platform == 'darwin'", - "version": "==0.1.3" + "markers": "python_version >= '3.7'", + "version": "==1.8.1" }, "asttokens": { "hashes": [ - "sha256:4622110b2a6f30b77e1473affaa97e711bc2f07d3f10848420ff1898edbe94f3", - "sha256:6b0ac9e93fb0335014d382b8fa9b3afa7df546984258005da0b9e7095b3deb1c" + "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7", + "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2" ], - "version": "==2.2.1" + "markers": "python_version >= '3.8'", + "version": "==3.0.0" }, "backcall": { "hashes": [ @@ -48,18 +42,106 @@ }, "decorator": { "hashes": [ - "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330", - "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186" + "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", + "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a" ], - "markers": "python_version < '3.11' and python_version >= '3.7'", - "version": "==5.1.1" + "markers": "python_version >= '3.7'", + "version": "==5.2.1" + }, + "exceptiongroup": { + "hashes": [ + "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", + "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88" + ], + "markers": "python_version < '3.11'", + "version": "==1.3.0" }, "executing": { "hashes": [ - "sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc", - "sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107" + "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa", + "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755" + ], + "markers": "python_version >= '3.8'", + "version": "==2.2.0" + }, + "greenlet": { + "hashes": [ + "sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e", + "sha256:03a088b9de532cbfe2ba2034b2b85e82df37874681e8c470d6fb2f8c04d7e4b7", + "sha256:04b013dc07c96f83134b1e99888e7a79979f1a247e2a9f59697fa14b5862ed01", + "sha256:05175c27cb459dcfc05d026c4232f9de8913ed006d42713cb8a5137bd49375f1", + "sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159", + "sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563", + "sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83", + "sha256:1443279c19fca463fc33e65ef2a935a5b09bb90f978beab37729e1c3c6c25fe9", + "sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395", + "sha256:1d3755bcb2e02de341c55b4fca7a745a24a9e7212ac953f6b3a48d117d7257aa", + "sha256:23f20bb60ae298d7d8656c6ec6db134bca379ecefadb0b19ce6f19d1f232a942", + "sha256:275f72decf9932639c1c6dd1013a1bc266438eb32710016a1c742df5da6e60a1", + "sha256:2846930c65b47d70b9d178e89c7e1a69c95c1f68ea5aa0a58646b7a96df12441", + "sha256:3319aa75e0e0639bc15ff54ca327e8dc7a6fe404003496e3c6925cd3142e0e22", + "sha256:346bed03fe47414091be4ad44786d1bd8bef0c3fcad6ed3dee074a032ab408a9", + "sha256:36b89d13c49216cadb828db8dfa6ce86bbbc476a82d3a6c397f0efae0525bdd0", + "sha256:37b9de5a96111fc15418819ab4c4432e4f3c2ede61e660b1e33971eba26ef9ba", + "sha256:396979749bd95f018296af156201d6211240e7a23090f50a8d5d18c370084dc3", + "sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1", + "sha256:411f015496fec93c1c8cd4e5238da364e1da7a124bcb293f085bf2860c32c6f6", + "sha256:47da355d8687fd65240c364c90a31569a133b7b60de111c255ef5b606f2ae291", + "sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39", + "sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d", + "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467", + "sha256:4ead44c85f8ab905852d3de8d86f6f8baf77109f9da589cb4fa142bd3b57b475", + "sha256:54558ea205654b50c438029505def3834e80f0869a70fb15b871c29b4575ddef", + "sha256:5e06afd14cbaf9e00899fae69b24a32f2196c19de08fcb9f4779dd4f004e5e7c", + "sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511", + "sha256:63e4844797b975b9af3a3fb8f7866ff08775f5426925e1e0bbcfe7932059a12c", + "sha256:6510bf84a6b643dabba74d3049ead221257603a253d0a9873f55f6a59a65f822", + "sha256:667a9706c970cb552ede35aee17339a18e8f2a87a51fba2ed39ceeeb1004798a", + "sha256:6ef9ea3f137e5711f0dbe5f9263e8c009b7069d8a1acea822bd5e9dae0ae49c8", + "sha256:7017b2be767b9d43cc31416aba48aab0d2309ee31b4dbf10a1d38fb7972bdf9d", + "sha256:7124e16b4c55d417577c2077be379514321916d5790fa287c9ed6f23bd2ffd01", + "sha256:73aaad12ac0ff500f62cebed98d8789198ea0e6f233421059fa68a5aa7220145", + "sha256:77c386de38a60d1dfb8e55b8c1101d68c79dfdd25c7095d51fec2dd800892b80", + "sha256:7876452af029456b3f3549b696bb36a06db7c90747740c5302f74a9e9fa14b13", + "sha256:7939aa3ca7d2a1593596e7ac6d59391ff30281ef280d8632fa03d81f7c5f955e", + "sha256:8320f64b777d00dd7ccdade271eaf0cad6636343293a25074cc5566160e4de7b", + "sha256:85f3ff71e2e60bd4b4932a043fbbe0f499e263c628390b285cb599154a3b03b1", + "sha256:8b8b36671f10ba80e159378df9c4f15c14098c4fd73a36b9ad715f057272fbef", + "sha256:93147c513fac16385d1036b7e5b102c7fbbdb163d556b791f0f11eada7ba65dc", + "sha256:935e943ec47c4afab8965954bf49bfa639c05d4ccf9ef6e924188f762145c0ff", + "sha256:94b6150a85e1b33b40b1464a3f9988dcc5251d6ed06842abff82e42632fac120", + "sha256:94ebba31df2aa506d7b14866fed00ac141a867e63143fe5bca82a8e503b36437", + "sha256:95ffcf719966dd7c453f908e208e14cde192e09fde6c7186c8f1896ef778d8cd", + "sha256:98884ecf2ffb7d7fe6bd517e8eb99d31ff7855a840fa6d0d63cd07c037f6a981", + "sha256:99cfaa2110534e2cf3ba31a7abcac9d328d1d9f1b95beede58294a60348fba36", + "sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a", + "sha256:a0dfc6c143b519113354e780a50381508139b07d2177cb6ad6a08278ec655798", + "sha256:b2795058c23988728eec1f36a4e5e4ebad22f8320c85f3587b539b9ac84128d7", + "sha256:b42703b1cf69f2aa1df7d1030b9d77d3e584a70755674d60e710f0af570f3761", + "sha256:b7cede291382a78f7bb5f04a529cb18e068dd29e0fb27376074b6d0317bf4dd0", + "sha256:b8a678974d1f3aa55f6cc34dc480169d58f2e6d8958895d68845fa4ab566509e", + "sha256:b8da394b34370874b4572676f36acabac172602abf054cbc4ac910219f3340af", + "sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa", + "sha256:c4aab7f6381f38a4b42f269057aee279ab0fc7bf2e929e3d4abfae97b682a12c", + "sha256:ca9d0ff5ad43e785350894d97e13633a66e2b50000e8a183a50a88d834752d42", + "sha256:d0028e725ee18175c6e422797c407874da24381ce0690d6b9396c204c7f7276e", + "sha256:d21e10da6ec19b457b82636209cbe2331ff4306b54d06fa04b7c138ba18c8a81", + "sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e", + "sha256:da7a9bff22ce038e19bf62c4dd1ec8391062878710ded0a845bcf47cc0200617", + "sha256:db32b5348615a04b82240cc67983cb315309e88d444a288934ee6ceaebcad6cc", + "sha256:dcc62f31eae24de7f8dce72134c8651c58000d3b1868e01392baea7c32c247de", + "sha256:dfc59d69fc48664bc693842bd57acfdd490acafda1ab52c7836e3fc75c90a111", + "sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383", + "sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70", + "sha256:ed10eac5830befbdd0c32f83e8aa6288361597550ba669b04c48f0f9a2c843c6", + "sha256:efc0f674aa41b92da8c49e0346318c6075d734994c3c4e4430b1c3f853e498e4", + "sha256:f1695e76146579f8c06c1509c7ce4dfe0706f49c6831a817ac04eebb2fd02011", + "sha256:f1d4aeb8891338e60d1ab6127af1fe45def5259def8094b9c7e34690c8858803", + "sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79", + "sha256:f6ff3b14f2df4c41660a7dec01045a045653998784bf8cfcb5a525bdffffbc8f" ], - "version": "==1.2.0" + "markers": "python_version >= '3' and platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32')))))", + "version": "==3.1.1" }, "importlib-metadata": { "hashes": [ @@ -67,127 +149,155 @@ "sha256:e354bedeb60efa6affdcc8ae121b73544a7aa74156d047311948f6d711cd378d" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==6.0.0" }, "importlib-resources": { "hashes": [ - "sha256:7d543798b0beca10b6a01ac7cafda9f822c54db9e8376a6bf57e0cbd74d486b6", - "sha256:e4a96c8cc0339647ff9a5e0550d9f276fc5a01ffa276012b58ec108cfd7b8484" + "sha256:c01b1b94210d9849f286b86bb51bcea7cd56dde0600d8db721d7b81330711668", + "sha256:ee17ec648f85480d523596ce49eae8ead87d5631ae1551f913c0100b5edd3437" ], "index": "pypi", - "version": "==5.10.2" + "markers": "python_version >= '3.7'", + "version": "==5.10.0" + }, + "iniconfig": { + "hashes": [ + "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", + "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760" + ], + "markers": "python_version >= '3.8'", + "version": "==2.1.0" }, "ipdb": { "hashes": [ - "sha256:c23b6736f01fd4586cc2ecbebdf79a5eb454796853e1cd8f2ed3b7b91d4a3e93", - "sha256:f74c2f741c18b909eaf89f19fde973f745ac721744aa1465888ce45813b63a9c" + "sha256:951bd9a64731c444fd907a5ce268543020086a697f6be08f7cc2c9a752a278c5" ], "index": "pypi", - "version": "==0.13.11" + "markers": "python_version >= '2.7'", + "version": "==0.13.9" }, "ipython": { "hashes": [ - "sha256:da01e6df1501e6e7c32b5084212ddadd4ee2471602e2cf3e0190f4de6b0ea481", - "sha256:f3bf2c08505ad2c3f4ed5c46ae0331a8547d36bf4b21a451e8ae80c0791db95b" + "sha256:3910c4b54543c2ad73d06579aa771041b7d5707b033bd488669b4cf544e3b363", + "sha256:b0340d46a933d27c657b211a329d0be23793c36595acf9e6ef4164bc01a1804c" ], - "markers": "python_version < '3.11' and python_version >= '3.7'", - "version": "==8.8.0" + "markers": "python_version >= '3.7'", + "version": "==8.12.3" }, "jedi": { "hashes": [ - "sha256:203c1fd9d969ab8f2119ec0a3342e0b49910045abe6af0a3ae83a5764d54639e", - "sha256:bae794c30d07f6d910d32a7048af09b5a39ed740918da923c6b780790ebac612" + "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0", + "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9" ], "markers": "python_version >= '3.6'", - "version": "==0.18.2" + "version": "==0.19.2" }, "mako": { "hashes": [ - "sha256:c97c79c018b9165ac9922ae4f32da095ffd3c4e6872b45eded42926deea46818", - "sha256:d60a3903dc3bb01a18ad6a89cdbe2e4eadc69c0bc8ef1e3773ba53d44c3f7a34" + "sha256:99579a6f39583fa7e5630a28c3c1f440e4e97a414b80372649c0ce338da2ea28", + "sha256:baef24a52fc4fc514a0887ac600f9f1cff3d82c61d4d700a1fa84d597b88db59" ], - "markers": "python_version >= '3.7'", - "version": "==1.2.4" + "markers": "python_version >= '3.8'", + "version": "==1.3.10" }, "markupsafe": { "hashes": [ - "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed", - "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc", - "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2", - "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460", - "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7", - "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0", - "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1", - "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa", - "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03", - "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323", - "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65", - "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013", - "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036", - "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f", - "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4", - "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419", - "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2", - "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619", - "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a", - "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a", - "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd", - "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7", - "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666", - "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65", - "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859", - "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625", - "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff", - "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156", - "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd", - "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba", - "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f", - "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1", - "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094", - "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a", - "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513", - "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed", - "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d", - "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3", - "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147", - "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c", - "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603", - "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601", - "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a", - "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1", - "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d", - "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3", - "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54", - "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2", - "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6", - "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58" + "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf", + "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff", + "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f", + "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3", + "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532", + "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f", + "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617", + "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df", + "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4", + "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906", + "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f", + "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4", + "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8", + "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371", + "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2", + "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465", + "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52", + "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6", + "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169", + "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad", + "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2", + "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0", + "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029", + "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f", + "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a", + "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced", + "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5", + "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c", + "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf", + "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9", + "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb", + "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad", + "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3", + "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1", + "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46", + "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc", + "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a", + "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee", + "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900", + "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5", + "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea", + "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f", + "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5", + "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e", + "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a", + "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f", + "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50", + "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a", + "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b", + "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4", + "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff", + "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2", + "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46", + "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b", + "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf", + "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5", + "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5", + "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab", + "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd", + "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68" ], "markers": "python_version >= '3.7'", - "version": "==2.1.2" + "version": "==2.1.5" }, "matplotlib-inline": { "hashes": [ - "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311", - "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304" + "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90", + "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca" ], - "markers": "python_version >= '3.5'", - "version": "==0.1.6" + "markers": "python_version >= '3.8'", + "version": "==0.1.7" + }, + "packaging": { + "hashes": [ + "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", + "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f" + ], + "markers": "python_version >= '3.8'", + "version": "==25.0" }, "parso": { "hashes": [ - "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0", - "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75" + "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18", + "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d" ], "markers": "python_version >= '3.6'", - "version": "==0.8.3" + "version": "==0.8.4" }, "pexpect": { "hashes": [ - "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937", - "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c" + "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", + "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f" ], "markers": "sys_platform != 'win32'", - "version": "==4.8.0" + "version": "==4.9.0" }, "pickleshare": { "hashes": [ @@ -196,13 +306,21 @@ ], "version": "==0.7.5" }, + "pluggy": { + "hashes": [ + "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", + "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669" + ], + "markers": "python_version >= '3.8'", + "version": "==1.5.0" + }, "prompt-toolkit": { "hashes": [ - "sha256:3e163f254bef5a03b146397d7c1963bd3e2812f0964bb9a24e6ec761fd28db63", - "sha256:aa64ad242a462c5ff0363a7b9cfe696c20d55d9fc60c11fd8e632d064804d305" + "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07", + "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed" ], - "markers": "python_full_version >= '3.6.2'", - "version": "==3.0.36" + "markers": "python_version >= '3.8'", + "version": "==3.0.51" }, "ptyprocess": { "hashes": [ @@ -213,111 +331,167 @@ }, "pure-eval": { "hashes": [ - "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350", - "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3" + "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", + "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42" ], - "version": "==0.2.2" + "version": "==0.2.3" }, "pygments": { "hashes": [ - "sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297", - "sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717" + "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", + "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c" ], - "markers": "python_version >= '3.6'", - "version": "==2.14.0" + "markers": "python_version >= '3.8'", + "version": "==2.19.1" + }, + "pytest": { + "hashes": [ + "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", + "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==8.3.5" }, - "six": { + "setuptools": { "hashes": [ - "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", - "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + "sha256:3c1383e1038b68556a382c1e8ded8887cd20141b0eb5708a6c8d277de49364f5", + "sha256:90ab613b6583fc02d5369cbca13ea26ea0e182d1df2d943ee9cbe81d4c61add9" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.16.0" + "markers": "python_version >= '3.8'", + "version": "==75.3.2" }, "sqlalchemy": { "hashes": [ - "sha256:07e48cbcdda6b8bc7a59d6728bd3f5f574ffe03f2c9fb384239f3789c2d95c2e", - "sha256:18cafdb27834fa03569d29f571df7115812a0e59fd6a3a03ccb0d33678ec8420", - "sha256:1b1e5e96e2789d89f023d080bee432e2fef64d95857969e70d3cadec80bd26f0", - "sha256:315676344e3558f1f80d02535f410e80ea4e8fddba31ec78fe390eff5fb8f466", - "sha256:31de1e2c45e67a5ec1ecca6ec26aefc299dd5151e355eb5199cd9516b57340be", - "sha256:3d94682732d1a0def5672471ba42a29ff5e21bb0aae0afa00bb10796fc1e28dd", - "sha256:3ec187acf85984263299a3f15c34a6c0671f83565d86d10f43ace49881a82718", - "sha256:4847f4b1d822754e35707db913396a29d874ee77b9c3c3ef3f04d5a9a6209618", - "sha256:4d112b0f3c1bc5ff70554a97344625ef621c1bfe02a73c5d97cac91f8cd7a41e", - "sha256:51e1ba2884c6a2b8e19109dc08c71c49530006c1084156ecadfaadf5f9b8b053", - "sha256:535377e9b10aff5a045e3d9ada8a62d02058b422c0504ebdcf07930599890eb0", - "sha256:5dbf17ac9a61e7a3f1c7ca47237aac93cabd7f08ad92ac5b96d6f8dea4287fc1", - "sha256:5f752676fc126edc1c4af0ec2e4d2adca48ddfae5de46bb40adbd3f903eb2120", - "sha256:64cb0ad8a190bc22d2112001cfecdec45baffdf41871de777239da6a28ed74b6", - "sha256:6913b8247d8a292ef8315162a51931e2b40ce91681f1b6f18f697045200c4a30", - "sha256:69fac0a7054d86b997af12dc23f581cf0b25fb1c7d1fed43257dee3af32d3d6d", - "sha256:7001f16a9a8e06488c3c7154827c48455d1c1507d7228d43e781afbc8ceccf6d", - "sha256:7b81b1030c42b003fc10ddd17825571603117f848814a344d305262d370e7c34", - "sha256:7f8267682eb41a0584cf66d8a697fef64b53281d01c93a503e1344197f2e01fe", - "sha256:887865924c3d6e9a473dc82b70977395301533b3030d0f020c38fd9eba5419f2", - "sha256:9167d4227b56591a4cc5524f1b79ccd7ea994f36e4c648ab42ca995d28ebbb96", - "sha256:939f9a018d2ad04036746e15d119c0428b1e557470361aa798e6e7d7f5875be0", - "sha256:955162ad1a931fe416eded6bb144ba891ccbf9b2e49dc7ded39274dd9c5affc5", - "sha256:984ee13543a346324319a1fb72b698e521506f6f22dc37d7752a329e9cd00a32", - "sha256:9883f5fae4fd8e3f875adc2add69f8b945625811689a6c65866a35ee9c0aea23", - "sha256:a1ad90c97029cc3ab4ffd57443a20fac21d2ec3c89532b084b073b3feb5abff3", - "sha256:a3714e5b33226131ac0da60d18995a102a17dddd42368b7bdd206737297823ad", - "sha256:ae067ab639fa499f67ded52f5bc8e084f045d10b5ac7bb928ae4ca2b6c0429a5", - "sha256:b33ffbdbbf5446cf36cd4cc530c9d9905d3c2fe56ed09e25c22c850cdb9fac92", - "sha256:b6e4cb5c63f705c9d546a054c60d326cbde7421421e2d2565ce3e2eee4e1a01f", - "sha256:b7f4b6aa6e87991ec7ce0e769689a977776db6704947e562102431474799a857", - "sha256:c04144a24103135ea0315d459431ac196fe96f55d3213bfd6d39d0247775c854", - "sha256:c522e496f9b9b70296a7675272ec21937ccfc15da664b74b9f58d98a641ce1b6", - "sha256:c5a99282848b6cae0056b85da17392a26b2d39178394fc25700bcf967e06e97a", - "sha256:c7a46639ba058d320c9f53a81db38119a74b8a7a1884df44d09fbe807d028aaf", - "sha256:d4b1cc7835b39835c75cf7c20c926b42e97d074147c902a9ebb7cf2c840dc4e2", - "sha256:d4d164df3d83d204c69f840da30b292ac7dc54285096c6171245b8d7807185aa", - "sha256:d61e9ecc849d8d44d7f80894ecff4abe347136e9d926560b818f6243409f3c86", - "sha256:d68e1762997bfebf9e5cf2a9fd0bcf9ca2fdd8136ce7b24bbd3bbfa4328f3e4a", - "sha256:e3c1808008124850115a3f7e793a975cfa5c8a26ceeeb9ff9cbb4485cac556df", - "sha256:f8cb80fe8d14307e4124f6fad64dfd87ab749c9d275f82b8b4ec84c84ecebdbe" + "sha256:04f2598c70ea4a29b12d429a80fad3a5202d56dce19dd4916cc46a965a5ca2e9", + "sha256:0501f74dd2745ec38f44c3a3900fb38b9db1ce21586b691482a19134062bf049", + "sha256:0ee377eb5c878f7cefd633ab23c09e99d97c449dd999df639600f49b74725b80", + "sha256:11b2ec26c5d2eefbc3e6dca4ec3d3d95028be62320b96d687b6e740424f83b7d", + "sha256:15d878929c30e41fb3d757a5853b680a561974a0168cd33a750be4ab93181628", + "sha256:177e41914c476ed1e1b77fd05966ea88c094053e17a85303c4ce007f88eff363", + "sha256:1811a0b19a08af7750c0b69e38dec3d46e47c4ec1d74b6184d69f12e1c99a5e0", + "sha256:1d0c23ecf7b3bc81e29459c34a3f4c68ca538de01254e24718a7926810dc39a6", + "sha256:22459fc1718785d8a86171bbe7f01b5c9d7297301ac150f508d06e62a2b4e8d2", + "sha256:28e881266a172a4d3c5929182fde6bb6fba22ac93f137d5380cc78a11a9dd124", + "sha256:2e56dfed0cc3e57b2f5c35719d64f4682ef26836b81067ee6cfad062290fd9e2", + "sha256:2fd49af453e590884d9cdad3586415922a8e9bb669d874ee1dc55d2bc425aacd", + "sha256:3ab7c158f98de6cb4f1faab2d12973b330c2878d0c6b689a8ca424c02d66e1b3", + "sha256:4948b6c5f4e56693bbeff52f574279e4ff972ea3353f45967a14c30fb7ae2beb", + "sha256:4e1c5f8182b4f89628d782a183d44db51b5af84abd6ce17ebb9804355c88a7b5", + "sha256:5ce6929417d5dce5ad1d3f147db81735a4a0573b8fb36e3f95500a06eaddd93e", + "sha256:5ede1495174e69e273fad68ad45b6d25c135c1ce67723e40f6cf536cb515e20b", + "sha256:5f966b64c852592469a7eb759615bbd351571340b8b344f1d3fa2478b5a4c934", + "sha256:6045b3089195bc008aee5c273ec3ba9a93f6a55bc1b288841bd4cfac729b6516", + "sha256:6c9d004eb78c71dd4d3ce625b80c96a827d2e67af9c0d32b1c1e75992a7916cc", + "sha256:6e39e97102f8e26c6c8550cb368c724028c575ec8bc71afbbf8faaffe2b2092a", + "sha256:723e3b9374c1ce1b53564c863d1a6b2f1dc4e97b1c178d9b643b191d8b1be738", + "sha256:876eb185911c8b95342b50a8c4435e1c625944b698a5b4a978ad2ffe74502908", + "sha256:9256563506e040daddccaa948d055e006e971771768df3bb01feeb4386c242b0", + "sha256:934472bb7d8666727746a75670a1f8d91a9cae8c464bba79da30a0f6faccd9e1", + "sha256:97ff50cd85bb907c2a14afb50157d0d5486a4b4639976b4a3346f34b6d1b5272", + "sha256:9b01d9cd2f9096f688c71a3d0f33f3cd0af8549014e66a7a7dee6fc214a7277d", + "sha256:9e3a65ce9ed250b2f096f7b559fe3ee92e6605fab3099b661f0397a9ac7c8d95", + "sha256:a7dd5b7b34a8ba8d181402d824b87c5cee8963cb2e23aa03dbfe8b1f1e417cde", + "sha256:a85723c00a636eed863adb11f1e8aaa36ad1c10089537823b4540948a8429798", + "sha256:b42c59ffd2d625b28cdb2ae4cde8488543d428cba17ff672a543062f7caee525", + "sha256:bd448b262544b47a2766c34c0364de830f7fb0772d9959c1c42ad61d91ab6565", + "sha256:ca9389a00f639383c93ed00333ed763812f80b5ae9e772ea32f627043f8c9c88", + "sha256:df76e9c60879fdc785a34a82bf1e8691716ffac32e7790d31a98d7dec6e81545", + "sha256:e12c6949bae10f1012ab5c0ea52ab8db99adcb8c7b717938252137cdf694c775", + "sha256:e4ef8cb3c5b326f839bfeb6af5f406ba02ad69a78c7aac0fbeeba994ad9bb48a", + "sha256:e7e740453f0149437c101ea4fdc7eea2689938c5760d7dcc436c863a12f1f565", + "sha256:effc89e606165ca55f04f3f24b86d3e1c605e534bf1a96e4e077ce1b027d0b71", + "sha256:f0f574465b78f29f533976c06b913e54ab4980b9931b69aa9d306afff13a9471", + "sha256:fa5b7eb2051e857bf83bade0641628efe5a88de189390725d3e6033a1fff4257", + "sha256:fdb94a3d1ba77ff2ef11912192c066f01e68416f554c194d769391638c8ad09a" ], "index": "pypi", - "version": "==1.4.46" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==1.4.42" }, "stack-data": { "hashes": [ - "sha256:32d2dd0376772d01b6cb9fc996f3c8b57a357089dec328ed4b6553d037eaf815", - "sha256:cbb2a53eb64e5785878201a97ed7c7b94883f48b87bfb0bbe8b623c74679e4a8" + "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", + "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695" ], - "version": "==0.6.2" + "version": "==0.6.3" + }, + "toml": { + "hashes": [ + "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", + "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" + ], + "markers": "python_version >= '3.7'", + "version": "==0.10.2" }, "tomli": { "hashes": [ - "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", - "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" + "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", + "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", + "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", + "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", + "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", + "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", + "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", + "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", + "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", + "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", + "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", + "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", + "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", + "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", + "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", + "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", + "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", + "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", + "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", + "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", + "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", + "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", + "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", + "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", + "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", + "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", + "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", + "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", + "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", + "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", + "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", + "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7" ], - "markers": "python_version < '3.11' and python_version >= '3.7'", - "version": "==2.0.1" + "markers": "python_version < '3.11'", + "version": "==2.2.1" }, "traitlets": { "hashes": [ - "sha256:32500888f5ff7bbf3b9267ea31748fa657aaf34d56d85e60f91dda7dc7f5785b", - "sha256:a1ca5df6414f8b5760f7c5f256e326ee21b581742114545b462b35ffe3f04861" + "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", + "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f" ], - "markers": "python_version >= '3.7'", - "version": "==5.8.1" + "markers": "python_version >= '3.8'", + "version": "==5.14.3" + }, + "typing-extensions": { + "hashes": [ + "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", + "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef" + ], + "markers": "python_version < '3.13'", + "version": "==4.13.2" }, "wcwidth": { "hashes": [ - "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e", - "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0" + "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", + "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5" ], - "version": "==0.2.6" + "version": "==0.2.13" }, "zipp": { "hashes": [ - "sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa", - "sha256:a7a22e05929290a67401440b39690ae6563279bced5f314609d9d03798f56766" + "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350", + "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29" ], "markers": "python_version < '3.10'", - "version": "==3.11.0" + "version": "==3.20.2" } }, "develop": {} diff --git a/freebies.db b/freebies.db new file mode 100644 index 000000000..e69de29bb diff --git a/lib/freebies.db b/lib/freebies.db index 12beb1c963e832db481e7a7493e3029e691ac4dc..e72db45894eb29b0d2b516775b496e8767494108 100644 GIT binary patch delta 406 zcmZozz}Rqrae}lUI|Bm)8xX?)%S0Vxadrm1CI?>r9}KKKyBPR+`FHZw^GWgS+SusA zW6~7M$}TP|%h<|Wl9-f}npTvWnv|JZ45QhcgIpa$TopnboqSvsprVr<`DC0jOHy;= z^AdAY6~Y{YoIMwp1f~aBzH~%14Pj^2BZ`Vi-h`6RgkgJ<(kgK1wYp?=X zjYejQCLZGu7RN)FKyNA-BO8oRfnqp9HOK}o&CODLw*+}C(~MJ$5)G40Q!SDWae}lUD+2=q2*UvLL>*&MRtCLzSzi7h3@m(74E((OJNfGQq&5o*EaTlQ e#dk}P$285{DB08^Db2(pd6U8yeiVU41_}T{Q53rX diff --git a/lib/migrations/versions/1224ea744733_create_freebies_table.py b/lib/migrations/versions/1224ea744733_create_freebies_table.py new file mode 100644 index 000000000..bcd4dd6c5 --- /dev/null +++ b/lib/migrations/versions/1224ea744733_create_freebies_table.py @@ -0,0 +1,31 @@ +"""Create freebies table + +Revision ID: 1224ea744733 +Revises: 5f72c58bf48c +Create Date: 2025-05-25 01:08:20.394784 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '9f3d2a1c5e8b' +down_revision = '5f72c58bf48c' +branch_labels = None +depends_on = None + +def upgrade() -> None: + 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(['dev_id'], ['devs.id'], name='fk_freebies_dev_id_devs'), + sa.ForeignKeyConstraint(['company_id'], ['companies.id'], name='fk_freebies_company_id_companies'), + sa.PrimaryKeyConstraint('id') + ) + +def downgrade() -> None: + op.drop_table('freebies') \ No newline at end of file diff --git a/lib/models.py b/lib/models.py index 2681bee5a..fb6fb9ba4 100644 --- a/lib/models.py +++ b/lib/models.py @@ -15,15 +15,50 @@ class Company(Base): id = Column(Integer(), primary_key=True) name = Column(String()) founding_year = Column(Integer()) + freebies = relationship('Freebie', backref=backref('company')) + devs = relationship('Dev', secondary='freebies', backref=backref('companies')) def __repr__(self): return f'' + def give_freebie(self, dev, item_name, value): + freebie = Freebie(item_name=item_name, value=value, dev=dev, company=self) + return freebie + + @classmethod + def oldest_company(cls): + from sqlalchemy.orm import Session + from sqlalchemy import create_engine + engine = create_engine('sqlite:///freebies.db') + session = Session(bind=engine) + return session.query(cls).order_by(cls.founding_year).first() + class Dev(Base): __tablename__ = 'devs' id = Column(Integer(), primary_key=True) - name= Column(String()) + name = Column(String()) + freebies = relationship('Freebie', backref=backref('dev')) 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 + return freebie + +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')) + + def print_details(self): + return f"{self.dev.name} owns a {self.item_name} from {self.company.name}" \ No newline at end of file diff --git a/lib/seed.py b/lib/seed.py index b16becbbb..fc6fc421b 100644 --- a/lib/seed.py +++ b/lib/seed.py @@ -1,3 +1,40 @@ #!/usr/bin/env python3 # Script goes here! + +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker +from models import Company, Dev, Freebie + +engine = create_engine('sqlite:///freebies.db') +Session = sessionmaker(bind=engine) +session = Session() + +# Clear existing data +session.query(Freebie).delete() +session.query(Dev).delete() +session.query(Company).delete() + +# Create companies +company1 = Company(name="TechCorp", founding_year=1995) +company2 = Company(name="InnovateInc", founding_year=2000) +session.add_all([company1, company2]) + +# Create devs +dev1 = Dev(name="Alice") +dev2 = Dev(name="Bob") +session.add_all([dev1, dev2]) + +# Commit companies and devs to get IDs +session.commit() + +# Create freebies +freebie1 = Freebie(item_name="T-Shirt", value=10, dev=dev1, company=company1) +freebie2 = Freebie(item_name="Sticker", value=2, dev=dev1, company=company2) +freebie3 = Freebie(item_name="Mug", value=15, dev=dev2, company=company1) +session.add_all([freebie1, freebie2, freebie3]) + +# Commit freebies +session.commit() + +print("Database seeded successfully!") \ No newline at end of file From c2716793afd0b46033077dc0fb362c0bd37ee60e Mon Sep 17 00:00:00 2001 From: David Amedi Date: Sun, 25 May 2025 01:31:12 +0300 Subject: [PATCH 2/5] Fixed seed.py path resolution using __file__ --- lib/freebies.db | Bin 24576 -> 24576 bytes lib/freebies.db.bak | Bin 0 -> 24576 bytes .../1224ea744733_create_freebies_table.py | 3 +-- lib/models.py | 8 ++++---- lib/seed.py | 7 ++++--- 5 files changed, 9 insertions(+), 9 deletions(-) create mode 100644 lib/freebies.db.bak diff --git a/lib/freebies.db b/lib/freebies.db index e72db45894eb29b0d2b516775b496e8767494108..a723ae0b6fec10089da7ef45a7610339a9c1a6df 100644 GIT binary patch delta 204 zcmZoTz}Rqrae_1>=R_H2M$U~1Q{;IJjf_lE6U|Lb%#DpVDSY9VKo;O-U|?Y4zstb? zf&cDiL4k|>`hrX>49ZNNd3pI|i6yC?dCBY-_!wCjWSK%zlQW$2iwf9JLo~f(;Qz+| zZnL1lBYp)oCT0d*8hwOckDHl|L70(|)3-F8 jpNXG|jRELR#^937Zg56sQ3)3SA15&m delta 93 zcmZoTz}Rqrae_1>`$QRMM)r*fQ{;Ip(~MJ$5)G40Q!SDi`lHE#e>_%JILm8qOm#`*oeWQCS z3jI*+r|PlC&Zton+AY1xe{jg;aWeDdHW*c0EY>k!H!T)LS*4KoJ=U;0)`jITyVYU#hi3CB zli`U7c<2U#eKei=8`Dw2nLC(@sJjYyV#c=vs7P-Z+`8diBKqEGyfd9E_SU*$72h*d z&w9&lcN|kr&iXezN{O$AREIG;Z#h=u!d916R&j$l*16?acHL^TWuJcxx6OyIni3^8 z?zTg0>}_W?LBZ%{wDQ3Lof}JDHM6SO80#vZzmg_3lPCpa{xGeTkB;bEEN9u|uxVss z^KHWStYdQ0{%{(4et6CAgge?@%0FadP_108(nWrmjXMxQ*YEL}7>)g5m^e+vGE01^ z@>^fV!)Xw0sY>nCh;6!^Es+?3-`@0CEXAGi8E6PgspG1C8AOHafKmY;|fB*y_009U<00I!$6M+&<9lz|?yi@n2 z_guW_7UX^5{eMpu7q literal 0 HcmV?d00001 diff --git a/lib/migrations/versions/1224ea744733_create_freebies_table.py b/lib/migrations/versions/1224ea744733_create_freebies_table.py index bcd4dd6c5..ba1a0fc39 100644 --- a/lib/migrations/versions/1224ea744733_create_freebies_table.py +++ b/lib/migrations/versions/1224ea744733_create_freebies_table.py @@ -8,9 +8,8 @@ from alembic import op import sqlalchemy as sa - # revision identifiers, used by Alembic. -revision = '9f3d2a1c5e8b' +revision = '1224ea744733' down_revision = '5f72c58bf48c' branch_labels = None depends_on = None diff --git a/lib/models.py b/lib/models.py index fb6fb9ba4..1351cf993 100644 --- a/lib/models.py +++ b/lib/models.py @@ -15,8 +15,8 @@ class Company(Base): id = Column(Integer(), primary_key=True) name = Column(String()) founding_year = Column(Integer()) - freebies = relationship('Freebie', backref=backref('company')) - devs = relationship('Dev', secondary='freebies', backref=backref('companies')) + freebies = relationship('Freebie', backref=backref('company', overlaps="company,freebies")) + devs = relationship('Dev', secondary='freebies', backref=backref('companies', overlaps="company,freebies"), overlaps="company,freebies") def __repr__(self): return f'' @@ -29,7 +29,7 @@ def give_freebie(self, dev, item_name, value): def oldest_company(cls): from sqlalchemy.orm import Session from sqlalchemy import create_engine - engine = create_engine('sqlite:///freebies.db') + engine = create_engine(f'sqlite:///{os.path.join(os.path.dirname(__file__), "freebies.db")}') session = Session(bind=engine) return session.query(cls).order_by(cls.founding_year).first() @@ -38,7 +38,7 @@ class Dev(Base): id = Column(Integer(), primary_key=True) name = Column(String()) - freebies = relationship('Freebie', backref=backref('dev')) + freebies = relationship('Freebie', backref=backref('dev', overlaps="companies,devs"), overlaps="companies,devs") def __repr__(self): return f'' diff --git a/lib/seed.py b/lib/seed.py index fc6fc421b..c0911b251 100644 --- a/lib/seed.py +++ b/lib/seed.py @@ -1,12 +1,13 @@ #!/usr/bin/env python3 -# Script goes here! - +import os from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from models import Company, Dev, Freebie -engine = create_engine('sqlite:///freebies.db') +# Use absolute path to ensure correct database location +db_path = os.path.join(os.path.dirname(__file__), 'freebies.db') +engine = create_engine(f'sqlite:///{db_path}') Session = sessionmaker(bind=engine) session = Session() From 9a125fcbd78964dcf74a8a5323f614f66d04e27d Mon Sep 17 00:00:00 2001 From: David Amedi Date: Sun, 25 May 2025 01:39:22 +0300 Subject: [PATCH 3/5] Added session setup to debug.py for interactive testing --- lib/debug.py | 13 +++++++++---- lib/freebies.db | Bin 24576 -> 24576 bytes 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/debug.py b/lib/debug.py index 4f922eb69..1072386ef 100644 --- a/lib/debug.py +++ b/lib/debug.py @@ -1,9 +1,14 @@ #!/usr/bin/env python3 +import os from sqlalchemy import create_engine - -from models import Company, Dev +from sqlalchemy.orm import sessionmaker +from models import Company, Dev, Freebie if __name__ == '__main__': - engine = create_engine('sqlite:///freebies.db') - import ipdb; ipdb.set_trace() + # Use absolute path to ensure correct database location + db_path = os.path.join(os.path.dirname(__file__), 'freebies.db') + engine = create_engine(f'sqlite:///{db_path}') + Session = sessionmaker(bind=engine) + session = Session() + import ipdb; ipdb.set_trace() \ No newline at end of file diff --git a/lib/freebies.db b/lib/freebies.db index a723ae0b6fec10089da7ef45a7610339a9c1a6df..0929381c8a34f679d15d008e43886b9f2c866f54 100644 GIT binary patch delta 116 zcmZoTz}Rqrae_1>_e2?IM(&LX3;p@|KQOTHZ)M=$%735#692Kyf&xqVz4;m07^E2) zIYV@VGct=xxR|(D*cgNvIXMGT^H{l=L2O1&-_mq`CVnQ6N>0Y$lFa1n)FLJ(1_lNJ Ipa5Je0DSWp(f|Me delta 85 zcmZoTz}Rqrae_1>=R_H2M$U~13;lT+7#NuOFEQ|c;J?p*X|tff5q>>xW;O<4Mn+EG l(sX_%ekL{spa#a^lFa1n)FLJ(K1Q$rXNYcaMrKh77XXt`6CnTq From ba7a2f5277822b3fed0c8b6a0fbb03b0369d5580 Mon Sep 17 00:00:00 2001 From: David Amedi Date: Sun, 25 May 2025 01:39:51 +0300 Subject: [PATCH 4/5] Added os import to models.py to fix oldest_company method --- lib/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/models.py b/lib/models.py index 1351cf993..6e26c502e 100644 --- a/lib/models.py +++ b/lib/models.py @@ -1,6 +1,7 @@ from sqlalchemy import ForeignKey, Column, Integer, String, MetaData from sqlalchemy.orm import relationship, backref from sqlalchemy.ext.declarative import declarative_base +import os convention = { "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s", From 4545aed8c3264cb0d2597634fe65bd8af0deca7e Mon Sep 17 00:00:00 2001 From: David Amedi Date: Sun, 25 May 2025 01:48:53 +0300 Subject: [PATCH 5/5] Updated README.md with completed challenge details and testing instructions --- README.md | 209 +++++++++++++++++++++++------------------------- lib/freebies.db | Bin 24576 -> 24576 bytes 2 files changed, 100 insertions(+), 109 deletions(-) diff --git a/README.md b/README.md index b598b7784..28e99c37e 100644 --- a/README.md +++ b/README.md @@ -10,81 +10,62 @@ ## Key Vocab -- **Schema**: the blueprint of a database. Describes how data relates to other - data in tables, columns, and relationships between them. -- **Persist**: save a schema in a database. -- **Engine**: a Python object that translates SQL to Python and vice-versa. -- **Session**: a Python object that uses an engine to allow us to - programmatically interact with a database. -- **Transaction**: a strategy for executing database statements such that - the group succeeds or fails as a unit. -- **Migration**: the process of moving data from one or more databases to one - or more target databases. - +- **Schema**: The blueprint of a database. Describes how data relates to other data in tables, columns, and relationships between them. +- **Persist**: Save a schema in a database. +- **Engine**: A Python object that translates SQL to Python and vice-versa. +- **Session**: A Python object that uses an engine to allow us to programmatically interact with a database. +- **Transaction**: A strategy for executing database statements such that the group succeeds or fails as a unit. +- **Migration**: The process of moving data from one or more databases to one or more target databases. + *** ## Introduction -For this assignment, we'll be working with a freebie domain. - -As developers, when you attend hackathons, you'll realize they hand out a lot of -free items (informally called _freebies_, or swag)! Let's make an app for -developers that keeps track of all the freebies they obtain. - -We have three models: `Company`, `Dev`, and `Freebie` - -For our purposes, a `Company` has many `Freebie`s, a `Dev` has many `Freebie`s, -and a `Freebie` belongs to a `Dev` and to a `Company`. +For this assignment, we’ve built an app to track freebies (swag) that developers receive from companies, such as those distributed at hackathons. The app includes three models: `Company`, `Dev`, and `Freebie`. -`Company` - `Dev` is a many to many relationship. +- A `Company` has many `Freebie`s. +- A `Dev` has many `Freebie`s. +- A `Freebie` belongs to one `Dev` and one `Company`. +- The `Company` - `Dev` relationship is many-to-many through the `Freebie` model. -**Note**: You should draw your domain on paper or on a whiteboard _before you -start coding_. Remember to identify a single source of truth for your data. +**Note**: The domain was initially sketched on paper to identify the single source of truth for the data before coding began. ## Instructions -To get started, run `pipenv install && pipenv shell` while inside of this -directory. +1. **Setup**: + - Ensure you have Python and Pipenv installed. + - Run `pipenv install && pipenv shell` from the project root directory to set up the virtual environment and install dependencies. -Build out all of the methods listed in the deliverables. The methods are listed -in a suggested order, but you can feel free to tackle the ones you think are -easiest. Be careful: some of the later methods rely on earlier ones. +2. **Run Migrations**: + - Navigate to the `lib` directory: `cd lib`. + - Apply migrations to create the database schema: `alembic upgrade head`. -**Remember!** This mock code challenge does not have tests. You cannot run -`pytest` and you cannot run `learn test`. You'll need to create your own sample -instances so that you can try out your code on your own. Make sure your -relationships and methods work in the console before submitting. +3. **Seed the Database**: + - Return to the project root: `cd ..`. + - Run the seed script to populate the database with sample data: `python lib/seed.py`. -We've provided you with a tool that you can use to test your code. To use it, -run `python debug.py` from the command line. This will start an `ipdb` session -with your classes defined. You can test out the methods that you write here. You -are also encouraged to use the `seed.py` file to create sample data to test your -models and associations. +4. **Test the Application**: + - Run `python lib/debug.py` to start an `ipdb` session. + - Use the session to test relationships (e.g., `c1.freebies`, `d1.companies`) and methods (e.g., `f1.print_details()`, `c1.give_freebie()`). + - Example commands are provided in the "Testing" section below. -Writing error-free code is more important than completing all of the -deliverables listed- prioritize writing methods that work over writing more -methods that don't work. You should test your code in the console as you write. +5. **Submission**: + - Save all changes and push to your GitHub repository. + - Submit the repository URL as instructed. -Similarly, messy code that works is better than clean code that doesn't. First, -prioritize getting things working. Then, if there is time at the end, refactor -your code to adhere to best practices. - -**Before you submit!** Save and run your code to verify that it works as you -expect. If you have any methods that are not working yet, feel free to leave -comments describing your progress. +**Priorities**: Focus on error-free code over completing all deliverables. Test each method in the console as you write it. Messy but working code is acceptable initially; refactor for best practices if time permits. *** ## What You Already Have -The starter code has migrations and models for the initial `Company` and `Dev` -models, and seed data for some `Company`s and `Dev`s. The schema currently looks -like this: +The starter code includes migrations and models for the initial `Company` and `Dev` models, along with seed data for some `Company`s and `Dev`s. The schema for these tables is: ### companies Table | Column | Type | | ------------- | ------- | +| id | Integer | | name | String | | founding_year | Integer | @@ -92,91 +73,101 @@ like this: | Column | Type | | ------ | ------ | -| name | String | +| id | Integer | +| name | String | + +A migration for the `freebies` table has been added, with the following schema: + +### freebies Table -You will need to create the migration for the `freebies` table using the -attributes specified in the deliverables below. +| Column | Type | +| ---------- | ------- | +| id | Integer | +| item_name | String | +| value | Integer | +| dev_id | Integer (Foreign Key to `devs.id`) | +| company_id | Integer (Foreign Key to `companies.id`) | + +Use `seed.py` to create `Freebie` instances for testing. *** ## Deliverables -Write the following methods in the classes in the files provided. Feel free to -build out any helper methods if needed. - -Remember: SQLAlchemy gives your classes access to a lot of methods already! -Keep in mind what methods SQLAlchemy gives you access to on each of your -classes when you're approaching the deliverables below. +All methods listed below have been implemented and tested. Helper methods were added as needed, leveraging SQLAlchemy’s built-in methods. ### Migrations -Before working on the rest of the deliverables, you will need to create a -migration for the `freebies` table. +- Created a migration for the `freebies` table with: + - `item_name` (string) and `value` (integer) columns. + - `dev_id` and `company_id` as foreign keys to `devs.id` and `companies.id`, respectively. +- Applied the migration with `alembic upgrade head` and seeded data with `seed.py`. -- A `Freebie` belongs to a `Dev`, and a `Freebie` also belongs to a `Company`. - In your migration, create any columns your `freebies` table will need to - establish these relationships using the right foreign keys. -- The `freebies` table should also have: - - An `item_name` column that stores a string. - - A `value` column that stores an integer. +### Relationship Attributes and Methods -After creating the `freebies` table using a migration, use the `seed.py` file to -create instances of your `Freebie` class so you can test your code. +#### Freebie +- `Freebie.dev`: Returns the associated `Dev` instance. +- `Freebie.company`: Returns the associated `Company` instance. -**After you've set up your `freebies` table**, work on building out the following -deliverables. +#### Company +- `Company.freebies`: Returns a collection of all `Freebie` instances for the company. +- `Company.devs`: Returns a collection of all `Dev` instances who received freebies from the company. -### Relationship Attributes and Methods +#### Dev +- `Dev.freebies`: Returns a collection of all `Freebie` instances for the dev. +- `Dev.companies`: Returns a collection of all `Company` instances from which the dev received freebies. -Use SQLAlchemy's `ForeignKey`, `relationship()`, and `backref()` objects to -build relationships between your three models. +**Testing**: Use `python debug.py` and run `c1.freebies`, `d1.companies`, etc., to verify relationships based on seed data. -**Note**: The plural of "freebie" is "freebies" and the singular of "freebies" -is "freebie". +### Aggregate Methods #### Freebie - -- `Freebie.dev` returns the `Dev` instance for this Freebie. -- `Freebie.company` returns the `Company` instance for this Freebie. +- `Freebie.print_details()`: Returns a string in the format `{dev name} owns a {freebie item_name} from {company name}`. #### Company - -- `Company.freebies` returns a collection of all the freebies for the Company. -- `Company.devs` returns a collection of all the devs who collected freebies - from the company. +- `Company.give_freebie(dev, item_name, value)`: Creates a new `Freebie` instance associated with the company and the given dev. +- `Company.oldest_company()`: Returns the `Company` instance with the earliest `founding_year`. #### Dev +- `Dev.received_one(item_name)`: Returns `True` if the dev has a freebie with the given `item_name`, `False` otherwise. +- `Dev.give_away(dev, freebie)`: Transfers the `Freebie` to the given `Dev` if it belongs to the current dev. -- `Dev.freebies` returns a collection of all the freebies that the Dev has collected. -- `Dev.companies`returns a collection of all the companies that the Dev has collected - freebies from. +*** -Use `python debug.py` and check that these methods work before proceeding. For -example, you should be able to retrieve a dev from the database by its -attributes and view their companies with `dev.companies` (based on your seed -data). +## Testing -### Aggregate Methods +Run `python lib/debug.py` to enter an `ipdb` session. Example tests: -#### Freebie +```python +# Relationships +c1 = session.query(Company).filter_by(name="TechCorp").first() +print(c1.freebies) # List of Freebie objects +print(c1.devs) # List of Dev objects -- `Freebie.print_details()`should return a string formatted as follows: - `{dev name} owns a {freebie item_name} from {company name}`. +d1 = session.query(Dev).filter_by(name="Alice").first() +print(d1.freebies) # List of Freebie objects +print(d1.companies) # List of Company objects -#### Company +f1 = session.query(Freebie).filter_by(item_name="T-Shirt").first() +print(f1.print_details()) # e.g., "Bob owns a T-Shirt from TechCorp" -- `Company.give_freebie(dev, item_name, value)` takes a `dev` (an instance of - the `Dev` class), an `item_name` (string), and a `value` as arguments, and - creates a new `Freebie` instance associated with this company and the given - dev. -- Class method `Company.oldest_company()`returns the `Company` instance with - the earliest founding year. +# Aggregate Methods +new_freebie = c1.give_freebie(d1, "Pen", 5) +session.add(new_freebie) +session.commit() +print(session.query(Freebie).filter_by(item_name="Pen").first()) -#### Dev +print(d1.received_one("Sticker")) # True +print(d1.received_one("Laptop")) # False + +d2 = session.query(Dev).filter_by(name="Bob").first() +f2 = d1.freebies[0] +d1.give_away(d2, f2) +session.commit() +print(f2.dev) # + +print(Company.oldest_company()) # +``` + +All tests should pass with the seeded data. -- `Dev.received_one(item_name)` accepts an `item_name` (string) and returns - `True` if any of the freebies associated with the dev has that `item_name`, - otherwise returns `False`. -- `Dev.give_away(dev, freebie)` accepts a `Dev` instance and a `Freebie` - instance, changes the freebie's dev to be the given dev; your code should only - make the change if the freebie belongs to the dev who's giving it away diff --git a/lib/freebies.db b/lib/freebies.db index 0929381c8a34f679d15d008e43886b9f2c866f54..222b845fe135317e1402364e787621e9f23d9a6a 100644 GIT binary patch delta 80 zcmV-W0I&amzyW~30gxL34Urr}0S&QWp-&M2000FKwF3{e58n^c55^Dlvk?%Z50kZD mDj^U81^^oY0RdBVX=7_;asmPZ000CE1qJ{U0SO6EWo`wL(i3w4 delta 78 zcmZoTz}Rqrae_1>_e2?IM(&LX3;p@|KQOTHZ)M=$%735#692Kyf&xqVCvT0{Qsif1 iV~}R#WDG9JOwLX%Vq#)oU=RQbaE9mxXJi(YZ~*|2!xY#6