diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..e78b39a1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "python.pythonPath": "C:\\Users\\brhac\\.virtualenvs\\DS-Unit-3-Sprint-3-Productization-and-Clou-lU37dm1B\\Scripts\\python.exe", + "python.linting.pylintEnabled": false, + "python.linting.flake8Enabled": true, + "python.linting.enabled": true +} \ No newline at end of file diff --git a/Pipfile b/Pipfile new file mode 100644 index 00000000..add774d8 --- /dev/null +++ b/Pipfile @@ -0,0 +1,20 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] +flake8 = "*" + +[packages] +flask = "*" +flask-sqlalchemy = "*" +flask-migrate = "*" +python-dotenv = "*" +requests = "*" +basilica = "*" +tweepy = "*" +scikit-learn = "*" + +[requires] +python_version = "3.7" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 00000000..eeaf1cde --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,446 @@ +{ + "_meta": { + "hash": { + "sha256": "d5d27a91e98618698458869e62ca530a8531c2650b9e8326d5da0bc642c0a59f" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.7" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "alembic": { + "hashes": [ + "sha256:035ab00497217628bf5d0be82d664d8713ab13d37b630084da8e1f98facf4dbf" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.4.2" + }, + "basilica": { + "hashes": [ + "sha256:10d111538e7fee4ece43b9a2f0f33c8b6a34dc1a061e44c035b53ac4297e3a4d" + ], + "index": "pypi", + "version": "==0.2.8" + }, + "certifi": { + "hashes": [ + "sha256:5ad7e9a056d25ffa5082862e36f119f7f7cec6457fa07ee2f8c339814b80c9b1", + "sha256:9cd41137dc19af6a5e03b630eefe7d1f458d964d406342dd3edf625839b944cc" + ], + "version": "==2020.4.5.2" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "click": { + "hashes": [ + "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a", + "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==7.1.2" + }, + "flask": { + "hashes": [ + "sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060", + "sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557" + ], + "index": "pypi", + "version": "==1.1.2" + }, + "flask-migrate": { + "hashes": [ + "sha256:4dc4a5cce8cbbb06b8dc963fd86cf8136bd7d875aabe2d840302ea739b243732", + "sha256:a69d508c2e09d289f6e55a417b3b8c7bfe70e640f53d2d9deb0d056a384f37ee" + ], + "index": "pypi", + "version": "==2.5.3" + }, + "flask-sqlalchemy": { + "hashes": [ + "sha256:0b656fbf87c5f24109d859bafa791d29751fabbda2302b606881ae5485b557a5", + "sha256:fcfe6df52cd2ed8a63008ca36b86a51fa7a4b70cef1c39e5625f722fca32308e" + ], + "index": "pypi", + "version": "==2.4.3" + }, + "idna": { + "hashes": [ + "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb", + "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.9" + }, + "itsdangerous": { + "hashes": [ + "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19", + "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.1.0" + }, + "jinja2": { + "hashes": [ + "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0", + "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.11.2" + }, + "joblib": { + "hashes": [ + "sha256:61e49189c84b3c5d99a969d314853f4d1d263316cc694bec17548ebaa9c47b6e", + "sha256:6825784ffda353cc8a1be573118085789e5b5d29401856b35b756645ab5aecb5" + ], + "markers": "python_version >= '3.6'", + "version": "==0.15.1" + }, + "mako": { + "hashes": [ + "sha256:8195c8c1400ceb53496064314c6736719c6f25e7479cd24c77be3d9361cddc27", + "sha256:93729a258e4ff0747c876bd9e20df1b9758028946e976324ccd2d68245c7b6a9" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.1.3" + }, + "markupsafe": { + "hashes": [ + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.1.1" + }, + "numpy": { + "hashes": [ + "sha256:0172304e7d8d40e9e49553901903dc5f5a49a703363ed756796f5808a06fc233", + "sha256:34e96e9dae65c4839bd80012023aadd6ee2ccb73ce7fdf3074c62f301e63120b", + "sha256:3676abe3d621fc467c4c1469ee11e395c82b2d6b5463a9454e37fe9da07cd0d7", + "sha256:3dd6823d3e04b5f223e3e265b4a1eae15f104f4366edd409e5a5e413a98f911f", + "sha256:4064f53d4cce69e9ac613256dc2162e56f20a4e2d2086b1956dd2fcf77b7fac5", + "sha256:4674f7d27a6c1c52a4d1aa5f0881f1eff840d2206989bae6acb1c7668c02ebfb", + "sha256:7d42ab8cedd175b5ebcb39b5208b25ba104842489ed59fbb29356f671ac93583", + "sha256:965df25449305092b23d5145b9bdaeb0149b6e41a77a7d728b1644b3c99277c1", + "sha256:9c9d6531bc1886454f44aa8f809268bc481295cf9740827254f53c30104f074a", + "sha256:a78e438db8ec26d5d9d0e584b27ef25c7afa5a182d1bf4d05e313d2d6d515271", + "sha256:a7acefddf994af1aeba05bbbafe4ba983a187079f125146dc5859e6d817df824", + "sha256:a87f59508c2b7ceb8631c20630118cc546f1f815e034193dc72390db038a5cb3", + "sha256:ac792b385d81151bae2a5a8adb2b88261ceb4976dbfaaad9ce3a200e036753dc", + "sha256:b03b2c0badeb606d1232e5f78852c102c0a7989d3a534b3129e7856a52f3d161", + "sha256:b39321f1a74d1f9183bf1638a745b4fd6fe80efbb1f6b32b932a588b4bc7695f", + "sha256:cae14a01a159b1ed91a324722d746523ec757357260c6804d11d6147a9e53e3f", + "sha256:cd49930af1d1e49a812d987c2620ee63965b619257bd76eaaa95870ca08837cf", + "sha256:e15b382603c58f24265c9c931c9a45eebf44fe2e6b4eaedbb0d025ab3255228b", + "sha256:e91d31b34fc7c2c8f756b4e902f901f856ae53a93399368d9a0dc7be17ed2ca0", + "sha256:ef627986941b5edd1ed74ba89ca43196ed197f1a206a3f18cc9faf2fb84fd675", + "sha256:f718a7949d1c4f622ff548c572e0c03440b49b9531ff00e4ed5738b459f011e8" + ], + "markers": "python_version >= '3.5'", + "version": "==1.18.5" + }, + "oauthlib": { + "hashes": [ + "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889", + "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==3.1.0" + }, + "pillow": { + "hashes": [ + "sha256:b532bcc2f008e96fd9241177ec580829dee817b090532f43e54074ecffdcd97f", + "sha256:eaa83729eab9c60884f362ada982d3a06beaa6cc8b084cf9f76cae7739481dfa", + "sha256:f46e0e024346e1474083c729d50de909974237c72daca05393ee32389dabe457", + "sha256:b37bb3bd35edf53125b0ff257822afa6962649995cbdfde2791ddb62b239f891", + "sha256:ee94fce8d003ac9fd206496f2707efe9eadcb278d94c271f129ab36aa7181344", + "sha256:f784aad988f12c80aacfa5b381ec21fd3f38f851720f652b9f33facc5101cf4d", + "sha256:1f694e28c169655c50bb89a3fa07f3b854d71eb47f50783621de813979ba87f3", + "sha256:b67a6c47ed963c709ed24566daa3f95a18f07d3831334da570c71da53d97d088", + "sha256:0e2a3bceb0fd4e0cb17192ae506d5f082b309ffe5fc370a5667959c9b2f85fa3", + "sha256:70e3e0d99a0dcda66283a185f80697a9b08806963c6149c8e6c5f452b2aa59c0", + "sha256:04766c4930c174b46fd72d450674612ab44cca977ebbcc2dde722c6933290107", + "sha256:a0b49960110bc6ff5fead46013bcb8825d101026d466f3a4de3476defe0fb0dd", + "sha256:3d25dd8d688f7318dca6d8cd4f962a360ee40346c15893ae3b95c061cdbc4079", + "sha256:f54be399340aa602066adb63a86a6a5d4f395adfdd9da2b9a0162ea808c7b276", + "sha256:9744350687459234867cbebfe9df8f35ef9e1538f3e729adbd8fde0761adb705", + "sha256:ccc9ad2460eb5bee5642eaf75a0438d7f8887d484490d5117b98edd7f33118b7", + "sha256:12e4bad6bddd8546a2f9771485c7e3d2b546b458ae8ff79621214119ac244523", + "sha256:0f01e63c34f0e1e2580cc0b24e86a5ccbbfa8830909a52ee17624c4193224cd9", + "sha256:f455efb7a98557412dc6f8e463c1faf1f1911ec2432059fa3e582b6000fc90e2", + "sha256:4b02b9c27fad2054932e89f39703646d0c543f21d3cc5b8e05434215121c28cd", + "sha256:b943e71c2065ade6fef223358e56c167fc6ce31c50bc7a02dd5c17ee4338e8ac", + "sha256:d23e2aa9b969cf9c26edfb4b56307792b8b374202810bd949effd1c6e11ebd6d", + "sha256:ae2b270f9a0b8822b98655cb3a59cdb1bd54a34807c6c56b76dd2e786c3b7db3" + ], + "markers": "python_version >= '3.5'", + "version": "==7.1.2" + }, + "pysocks": { + "hashes": [ + "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299", + "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5", + "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.7.1" + }, + "python-dateutil": { + "hashes": [ + "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", + "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.8.1" + }, + "python-dotenv": { + "hashes": [ + "sha256:25c0ff1a3e12f4bde8d592cc254ab075cfe734fc5dd989036716fd17ee7e5ec7", + "sha256:3b9909bc96b0edc6b01586e1eed05e71174ef4e04c71da5786370cebea53ad74" + ], + "index": "pypi", + "version": "==0.13.0" + }, + "python-editor": { + "hashes": [ + "sha256:5f98b069316ea1c2ed3f67e7f5df6c0d8f10b689964a4a811ff64f0106819ec8", + "sha256:51fda6bcc5ddbbb7063b2af7509e43bd84bfc32a4ff71349ec7847713882327b", + "sha256:c3da2053dbab6b29c94e43c486ff67206eafbe7eb52dbec7390b5e2fb05aac77", + "sha256:1bf6e860a8ad52a14c3ee1252d5dc25b2030618ed80c022598f00176adc8367d", + "sha256:ea87e17f6ec459e780e4221f295411462e0d0810858e055fc514684350a2f522" + ], + "version": "==1.0.4" + }, + "requests": { + "hashes": [ + "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b", + "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898" + ], + "index": "pypi", + "version": "==2.24.0" + }, + "requests-oauthlib": { + "hashes": [ + "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc", + "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d", + "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a" + ], + "version": "==1.3.0" + }, + "scikit-learn": { + "hashes": [ + "sha256:04799686060ecbf8992f26a35be1d99e981894c8c7860c1365cda4200f954a16", + "sha256:058d213092de4384710137af1300ed0ff030b8c40459a6c6f73c31ccd274cc39", + "sha256:0c3464e46ef8bd4f1bfa5c009648c6449412c8f7e9b3fc0c9e3d800139c48827", + "sha256:0e7b55f73b35537ecd0d19df29dd39aa9e076dba78f3507b8136c819d84611fd", + "sha256:16feae4361be6b299d4d08df5a30956b4bfc8eadf173fe9258f6d59630f851d4", + "sha256:244ca85d6eba17a1e6e8a66ab2f584be6a7784b5f59297e3d7ff8c7983af627c", + "sha256:3e6e92b495eee193a8fa12a230c9b7976ea0fc1263719338e35c986ea1e42cff", + "sha256:5bcea4d6ee431c814261117281363208408aa4e665633655895feb059021aca6", + "sha256:93f56abd316d131645559ec0ab4f45e3391c2ccdd4eadaa4912f4c1e0a6f2c96", + "sha256:9e04c0811ea92931ee8490d638171b8cb2f21387efcfff526bbc8c2a3da60f1c", + "sha256:bded94236e16774385202cafd26190ce96db18e4dc21e99473848c61e4fdc400", + "sha256:c2fa33d20408b513cf432505c80e6eb4bf4d71434f1ae36680765d4a2c2a16ec", + "sha256:e3fec1c8831f8f93ad85581ca29ca1bb88e2da377fb097cf8322aa89c21bc9b8", + "sha256:e585682e37f2faa81ad6cd4472fff646bf2fd0542147bec93697a905db8e6bd2", + "sha256:e9879ba9e64ec3add41bf201e06034162f853652ef4849b361d73b0deb3153ad", + "sha256:ebe853e6f318f9d8b3b74dd17e553720d35646eff675a69eeaed12fbbbb07daa" + ], + "index": "pypi", + "version": "==0.23.1" + }, + "scipy": { + "hashes": [ + "sha256:00af72998a46c25bdb5824d2b729e7dabec0c765f9deb0b504f928591f5ff9d4", + "sha256:0902a620a381f101e184a958459b36d3ee50f5effd186db76e131cbefcbb96f7", + "sha256:1e3190466d669d658233e8a583b854f6386dd62d655539b77b3fa25bfb2abb70", + "sha256:2cce3f9847a1a51019e8c5b47620da93950e58ebc611f13e0d11f4980ca5fecb", + "sha256:3092857f36b690a321a662fe5496cb816a7f4eecd875e1d36793d92d3f884073", + "sha256:386086e2972ed2db17cebf88610aab7d7f6e2c0ca30042dc9a89cf18dcc363fa", + "sha256:71eb180f22c49066f25d6df16f8709f215723317cc951d99e54dc88020ea57be", + "sha256:770254a280d741dd3436919d47e35712fb081a6ff8bafc0f319382b954b77802", + "sha256:787cc50cab3020a865640aba3485e9fbd161d4d3b0d03a967df1a2881320512d", + "sha256:8a07760d5c7f3a92e440ad3aedcc98891e915ce857664282ae3c0220f3301eb6", + "sha256:8d3bc3993b8e4be7eade6dcc6fd59a412d96d3a33fa42b0fa45dc9e24495ede9", + "sha256:9508a7c628a165c2c835f2497837bf6ac80eb25291055f56c129df3c943cbaf8", + "sha256:a144811318853a23d32a07bc7fd5561ff0cac5da643d96ed94a4ffe967d89672", + "sha256:a1aae70d52d0b074d8121333bc807a485f9f1e6a69742010b33780df2e60cfe0", + "sha256:a2d6df9eb074af7f08866598e4ef068a2b310d98f87dc23bd1b90ec7bdcec802", + "sha256:bb517872058a1f087c4528e7429b4a44533a902644987e7b2fe35ecc223bc408", + "sha256:c5cac0c0387272ee0e789e94a570ac51deb01c796b37fb2aad1fb13f85e2f97d", + "sha256:cc971a82ea1170e677443108703a2ec9ff0f70752258d0e9f5433d00dda01f59", + "sha256:dba8306f6da99e37ea08c08fef6e274b5bf8567bb094d1dbe86a20e532aca088", + "sha256:dc60bb302f48acf6da8ca4444cfa17d52c63c5415302a9ee77b3b21618090521", + "sha256:dee1bbf3a6c8f73b6b218cb28eed8dd13347ea2f87d572ce19b289d6fd3fbc59" + ], + "markers": "python_version >= '3.5'", + "version": "==1.4.1" + }, + "six": { + "hashes": [ + "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", + "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.15.0" + }, + "sqlalchemy": { + "hashes": [ + "sha256:128bc917ed20d78143a45024455ff0aed7d3b96772eba13d5dbaf9cc57e5c41b", + "sha256:156a27548ba4e1fed944ff9fcdc150633e61d350d673ae7baaf6c25c04ac1f71", + "sha256:27e2efc8f77661c9af2681755974205e7462f1ae126f498f4fe12a8b24761d15", + "sha256:2a12f8be25b9ea3d1d5b165202181f2b7da4b3395289000284e5bb86154ce87c", + "sha256:31c043d5211aa0e0773821fcc318eb5cbe2ec916dfbc4c6eea0c5188971988eb", + "sha256:65eb3b03229f684af0cf0ad3bcc771970c1260a82a791a8d07bffb63d8c95bcc", + "sha256:6cd157ce74a911325e164441ff2d9b4e244659a25b3146310518d83202f15f7a", + "sha256:703c002277f0fbc3c04d0ae4989a174753a7554b2963c584ce2ec0cddcf2bc53", + "sha256:869bbb637de58ab0a912b7f20e9192132f9fbc47fc6b5111cd1e0f6cdf5cf9b0", + "sha256:8a0e0cd21da047ea10267c37caf12add400a92f0620c8bc09e4a6531a765d6d7", + "sha256:8d01e949a5d22e5c4800d59b50617c56125fc187fbeb8fa423e99858546de616", + "sha256:925b4fe5e7c03ed76912b75a9a41dfd682d59c0be43bce88d3b27f7f5ba028fb", + "sha256:9cb1819008f0225a7c066cac8bb0cf90847b2c4a6eb9ebb7431dbd00c56c06c5", + "sha256:a87d496884f40c94c85a647c385f4fd5887941d2609f71043e2b73f2436d9c65", + "sha256:a9030cd30caf848a13a192c5e45367e3c6f363726569a56e75dc1151ee26d859", + "sha256:a9e75e49a0f1583eee0ce93270232b8e7bb4b1edc89cc70b07600d525aef4f43", + "sha256:b50f45d0e82b4562f59f0e0ca511f65e412f2a97d790eea5f60e34e5f1aabc9a", + "sha256:b7878e59ec31f12d54b3797689402ee3b5cfcb5598f2ebf26491732758751908", + "sha256:ce1ddaadee913543ff0154021d31b134551f63428065168e756d90bdc4c686f5", + "sha256:ce2646e4c0807f3461be0653502bb48c6e91a5171d6e450367082c79e12868bf", + "sha256:ce6c3d18b2a8ce364013d47b9cad71db815df31d55918403f8db7d890c9d07ae", + "sha256:e4e2664232005bd306f878b0f167a31f944a07c4de0152c444f8c61bbe3cfb38", + "sha256:e8aa395482728de8bdcca9cc0faf3765ab483e81e01923aaa736b42f0294f570", + "sha256:eb4fcf7105bf071c71068c6eee47499ab8d4b8f5a11fc35147c934f0faa60f23", + "sha256:ed375a79f06cad285166e5be74745df1ed6845c5624aafadec4b7a29c25866ef", + "sha256:f35248f7e0d63b234a109dd72fbfb4b5cb6cb6840b221d0df0ecbf54ab087654", + "sha256:f502ef245c492b391e0e23e94cba030ab91722dcc56963c85bfd7f3441ea2bbe", + "sha256:fe01bac7226499aedf472c62fa3b85b2c619365f3f14dd222ffe4f3aa91e5f98" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.3.17" + }, + "threadpoolctl": { + "hashes": [ + "sha256:38b74ca20ff3bb42caca8b00055111d74159ee95c4370882bbff2b93d24da725", + "sha256:ddc57c96a38beb63db45d6c159b5ab07b6bced12c45a1f07b2b92f272aebfa6b" + ], + "markers": "python_version >= '3.5'", + "version": "==2.1.0" + }, + "tweepy": { + "hashes": [ + "sha256:8abd828ba51a85a2b5bb7373715d6d3bb32d18ac624e3a4db02e4ef8ab48316b", + "sha256:ecc7f200c86127903017e48824efd008734814e95f3e8e9b45ce0f4120dd08db" + ], + "index": "pypi", + "version": "==3.8.0" + }, + "urllib3": { + "hashes": [ + "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527", + "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", + "version": "==1.25.9" + }, + "werkzeug": { + "hashes": [ + "sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43", + "sha256:6c80b1e5ad3665290ea39320b91e1be1e0d5f60652b964a3070216de83d2e47c" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==1.0.1" + } + }, + "develop": { + "flake8": { + "hashes": [ + "sha256:15e351d19611c887e482fb960eae4d44845013cc142d42896e9862f775d8cf5c", + "sha256:f04b9fcbac03b0a3e58c0ab3a0ecc462e023a9faf046d57794184028123aa208" + ], + "index": "pypi", + "version": "==3.8.3" + }, + "importlib-metadata": { + "hashes": [ + "sha256:0505dd08068cfec00f53a74a0ad927676d7757da81b7436a6eefe4c7cf75c545", + "sha256:15ec6c0fd909e893e3a08b3a7c76ecb149122fb14b7efe1199ddd4c7c57ea958" + ], + "markers": "python_version < '3.8'", + "version": "==1.6.1" + }, + "mccabe": { + "hashes": [ + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + ], + "version": "==0.6.1" + }, + "pycodestyle": { + "hashes": [ + "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367", + "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.6.0" + }, + "pyflakes": { + "hashes": [ + "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92", + "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.2.0" + }, + "zipp": { + "hashes": [ + "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b", + "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96" + ], + "markers": "python_version >= '3.6'", + "version": "==3.1.0" + } + } +} diff --git a/module1-web-application-development-with-flask/.gitignore b/module1-web-application-development-with-flask/.gitignore new file mode 100644 index 00000000..47ca433e --- /dev/null +++ b/module1-web-application-development-with-flask/.gitignore @@ -0,0 +1,7 @@ +#ignore local database stuff: + +migrations/ + +*.db + +.env \ No newline at end of file diff --git a/module1-web-application-development-with-flask/instructions.md b/module1-web-application-development-with-flask/instructions.md new file mode 100644 index 00000000..f27ceff3 --- /dev/null +++ b/module1-web-application-development-with-flask/instructions.md @@ -0,0 +1,22 @@ +##Setup + + +Setup and activate a virtual environment: + + +Set up database + +# Windows users can omit the "FLASK_APP=web_app" part... + +FLASK_APP=web_app flask db init #> generates app/migrations dir + +# run both when changing the schema: +FLASK_APP=web_app flask db migrate #> creates the db (with "alembic_version" table) +FLASK_APP=web_app flask db upgrade #> creates the specified tables + +# Usage + +run the flask +'''py +flask run +''' diff --git a/module1-web-application-development-with-flask/web_app/__init__.py b/module1-web-application-development-with-flask/web_app/__init__.py new file mode 100644 index 00000000..a643c491 --- /dev/null +++ b/module1-web-application-development-with-flask/web_app/__init__.py @@ -0,0 +1,25 @@ +# web_app/__init__.py + +from flask import Flask + +from web_app.models import db, migrate +from web_app.routes.home_routes import home_routes +from web_app.routes.book_routes import book_routes + +DATABASE_URI = "sqlite:///web_app_brit.db" + +def create_app(): + app = Flask(__name__) + + app.config["SQLALCHEMY_DATABASE_URI"] = DATABASE_URI + app.config["SQLALCHEMY_TRACK_MODIFICATION"] =False + db.init_app(app) + migrate.init_app(app, db) + + app.register_blueprint(home_routes) + app.register_blueprint(book_routes) + return app + +if __name__ == "__main__": + my_app = create_app() + my_app.run(debug=True) \ No newline at end of file diff --git a/module1-web-application-development-with-flask/web_app/models.py b/module1-web-application-development-with-flask/web_app/models.py new file mode 100644 index 00000000..014c439f --- /dev/null +++ b/module1-web-application-development-with-flask/web_app/models.py @@ -0,0 +1,61 @@ +from flask_sqlalchemy import SQLAlchemy +from flask_migrate import Migrate + +db = SQLAlchemy() + +migrate = Migrate() + + +class Book(db.Model): + id = db.Column(db.Integer, primary_key=True) + title = db.Column(db.String(128)) + author_id = db.Column(db.String(128)) + + def __repr__(self): + return f"" + + +# def parse_records(database_records): +# """ +# A helper method for converting a list of database record objects into a list of dictionaries, so they can be returned as JSON + +# Param: database_records (a list of db.Model instances) + +# Example: parse_records(User.query.all()) + +# Returns: a list of dictionaries, each corresponding to a record, like... +# [ +# {"id": 1, "title": "Book 1"}, +# {"id": 2, "title": "Book 2"}, +# {"id": 3, "title": "Book 3"}, +# ] +# """ +# parsed_records = [] +# for record in database_records: +# print(record) +# parsed_record = record.__dict__ +# del parsed_record["_sa_instance_state"] +# parsed_records.append(parsed_record) +# return parsed_records + +class User(db.Model): + """Twitter users corresponding to Tweets in the Tweet table.""" + id = db.Column(db.BigInteger, primary_key=True) + name = db.Column(db.String(15), nullable=False) + # Tweet IDs are ordinal ints, so can be used to fetch only more recent + newest_tweet_id = db.Column(db.BigInteger) + + def __repr__(self): + return ''.format(self.name) + + +class Tweet(db.Model): + """Tweets and their embeddings from Basilica.""" + id = db.Column(db.BigInteger, primary_key=True) + text = db.Column(db.Unicode(300)) # Allowing for full + links + embedding = db.Column(db.PickleType, nullable=False) + user_id = db.Column(db.BigInteger, db.ForeignKey('user.id'), nullable=False) + user = db.relationship('User', backref=db.backref('tweets', lazy=True)) + + def __repr__(self): + return ''.format(self.text) diff --git a/module1-web-application-development-with-flask/web_app/routes/book_routes.py b/module1-web-application-development-with-flask/web_app/routes/book_routes.py new file mode 100644 index 00000000..b8dbb04d --- /dev/null +++ b/module1-web-application-development-with-flask/web_app/routes/book_routes.py @@ -0,0 +1,39 @@ +# web_app/routes/book_routes.py + +from flask import Blueprint, jsonify, request, render_template #, flash, redirect +from web_app.models import Book, db +book_routes = Blueprint("book_routes", __name__) + +@book_routes.route("/books.json") +def list_books(): + book_records = Book.query.all() + print(book_records) + books = parse_records(book_records) + + return jsonify(books) + +@book_routes.route("/books") +def list_books_for_humans(): + book_records = Book.query.all() + print(book_records) + books = parse_records(book_records) + return render_template("books.html", message="Find books below", books=books) + +@book_routes.route("/books/new") +def new_book(): + return render_template("new_book.html") + +@book_routes.route("/books/create", methods=["POST"]) +def create_book(): + print("FORM DATA:", dict(request.form)) + new_book = Book(title=request.form["title"], author_id=request.form["author_name"]) + db.session.add(new_book) + db.session.commit() + + + return jsonify({ + "message": "BOOK CREATED OK (TODO)", + "book": dict(request.form) + }) + #flash(f"Book '{new_book.title}' created successfully!", "success") + #return redirect(f"/books") \ No newline at end of file diff --git a/module1-web-application-development-with-flask/web_app/routes/home_routes.py b/module1-web-application-development-with-flask/web_app/routes/home_routes.py new file mode 100644 index 00000000..fd682be0 --- /dev/null +++ b/module1-web-application-development-with-flask/web_app/routes/home_routes.py @@ -0,0 +1,18 @@ +# web_app/routes/home_routes.py + +from flask import Blueprint, render_template + +home_routes = Blueprint("home_routes", __name__) + +@home_routes.route("/") +def index(): + return render_template("prediction_form.html") + +@home_routes.route("/") +def index(): + x = 2 + 2 + return f"Hello World! {x}" + +@home_routes.route("/about") +def about(): + return "About me" \ No newline at end of file diff --git a/module1-web-application-development-with-flask/web_app/routes/twitter_routes.py b/module1-web-application-development-with-flask/web_app/routes/twitter_routes.py new file mode 100644 index 00000000..6cf741d4 --- /dev/null +++ b/module1-web-application-development-with-flask/web_app/routes/twitter_routes.py @@ -0,0 +1,53 @@ +pifrom flask import Blueprint, render_template, jsonify +from web_app.services.twitter_service import api as twitter_api_client +from web_app.models import db, User, Tweet, parse_records + +twitter_routes = Blueprint("twitter_routes", __name__) + +@twitter_routes.route("/users//fetch") +def fetch_user(screen_name=None): + print(screen_name) + + twitter_user = twitter_api_client.get_user(screen_name) + tweets = api.user_timeline(screen_name, tweet_mode="extended", count=150, exclude_replies=True, include_rts=False) + print("TWEETS COUNT:", len(tweets)) + #return jsonify({"user": user._json, "tweets": [s._json for s in statuses]}) + + + # get existing user from the db or initialize a new one: + db_user = User.query.get(twitter_user.id) or User(id=twitter_user.id) + db_user.screen_name = twitter_user.screen_name + db_user.name = twitter_user.name + db_user.location = twitter_user.location + db_user.followers_count = twitter_user.followers_count + db.session.add(db_user) + db.session.commit() + #return "OK" + breakpoint() + + basilica_api = basilica_api_client() + + #all_tweet_texts = [status.full_text for status in statuses] + embeddings = list(basilica_api_client.embed_sentences(all_tweet_texts, model="twitter")) + print("NUMBER OF EMBEDDINGS", len(embeddings)) + + # TODO: explore using the zip() function maybe... + #counter = 0 + for index, status in enumerate(tweets): + print(index) + print(status.full_text) + print("----") + + embedding = embeddings[index] + #print(dir(status)) + # get existing tweet from the db or initialize a new one: + db_tweet = Tweet.query.get(status.id) or Tweet(id=status.id) + db_tweet.user_id = status.author.id # or db_user.id + db_tweet.full_text = status.full_text + db_tweet.embedding = embedding + db.session.add(db_tweet) + + db.session.commit() + #breakpoint() + return "OK" + #return render_template("user.html", user=db_user, tweets=statuses) # tweets=db_tweets \ No newline at end of file diff --git a/module1-web-application-development-with-flask/web_app/services/basilica_service.py b/module1-web-application-development-with-flask/web_app/services/basilica_service.py new file mode 100644 index 00000000..efc939af --- /dev/null +++ b/module1-web-application-development-with-flask/web_app/services/basilica_service.py @@ -0,0 +1,27 @@ +from basilica import Connection +import os +from dotenv import load_dotenv + + +load_dotenv() + +API_KEY = os.getenv("BASILICA_API_KEY") + +connection = Connection(API_KEY) +print("CONNECTION", type(connection)) + +if __name__ == "__main__": + sentences = [ + "This is a sentence!", + "This is a similar sentence!", + "I don't think this sentence is very similar at all...", + ] + embeddings = list(connection.embed_sentences(sentences)) + print(embeddings) + + embedding = list(connection.embed_sentence("Hello world!", model="twitter")) + print(type(embedding)) + print(type(embedding[0])) + print(len(embedding)) + + breakpoint() \ No newline at end of file diff --git a/module1-web-application-development-with-flask/web_app/services/twitter_service.py b/module1-web-application-development-with-flask/web_app/services/twitter_service.py new file mode 100644 index 00000000..892f1cbe --- /dev/null +++ b/module1-web-application-development-with-flask/web_app/services/twitter_service.py @@ -0,0 +1,31 @@ +import os +from dotenv import load_dotenv +from tweepy import OAuthHandler, API + +load_dotenv() + +TWITTER_API_KEY = os.getenv("TWITTER_API_KEY") +TWITTER_API_SECRET = os.getenv("TWITTER_API_SECRET") +TWITTER_ACCESS_TOKEN = os.getenv("TWITTER_ACCESS_TOKEN") +TWITTER_ACCESS_TOKEN_SECRET = os.getenv("TWITTER_ACCESS_TOKEN_SECRET") + +auth = OAuthHandler(TWITTER_API_KEY, TWITTER_API_SECRET) +auth.set_acess_token(TWITTER_ACCESS_TOKEN, TWITTER_ACCESS_TOKEN_SECRET) + +api = API(auth) +print("API CLIENT:", api) + +user = api.get_user("britnelikecafe") +print("TWITTER USER:", type(user)) +print(user.id) +print(user.screen_name) +print(user.name) + +tweets = api.user_timeline("britnelikecafe") +print("TWEETS", type(tweets)) +print(type(tweets[0])) + +breakpoint() +tweet = tweets[0] +print(tweet.id) +print(tweet.text) \ No newline at end of file diff --git a/module1-web-application-development-with-flask/web_app/templates/books.html b/module1-web-application-development-with-flask/web_app/templates/books.html new file mode 100644 index 00000000..2cd0a171 --- /dev/null +++ b/module1-web-application-development-with-flask/web_app/templates/books.html @@ -0,0 +1,28 @@ + + + + + + + + Ny webapp + + +

Welcome to Bookdom!

+ +

{{ message }}

+ + {% if books %} +
    + {% for book in books %} +
  • {{ book["title"] }}
  • + {% endfor %} +
+ + {% else %} +

Books not found.

+ {% endif %} + + + + diff --git a/module1-web-application-development-with-flask/web_app/templates/new_book.html b/module1-web-application-development-with-flask/web_app/templates/new_book.html new file mode 100644 index 00000000..ed91093e --- /dev/null +++ b/module1-web-application-development-with-flask/web_app/templates/new_book.html @@ -0,0 +1,31 @@ + + + + + + + + My webapp + + +

New Book Page

+ +

Please fill out the form and submit to create a new book!

+ +
+ + + + + + + + +
+ + +