Add files via upload

This commit is contained in:
Eduard Prigoana 2025-01-02 01:08:58 +02:00 committed by GitHub
parent 8e53f0038d
commit f216cf05c5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
27 changed files with 29565 additions and 0 deletions

15
api/Dockerfile Normal file
View file

@ -0,0 +1,15 @@
FROM python:3.12.4-alpine
RUN apk add --no-cache --update git make gcc python3-dev musl-dev && \
set -ex && \
pip install --no-cache-dir pipenv==2023.12.1
ADD Pipfile Pipfile
ADD Pipfile.lock Pipfile.lock
RUN set -ex && \
pipenv install --dev --system --deploy
ADD app app
CMD exec gunicorn app.main:app

18
api/Makefile Normal file
View file

@ -0,0 +1,18 @@
init:
pip install pipenv
pipenv install --dev
run:
pipenv run gunicorn app.main:app --workers=4 --bind 0.0.0.0:5000 --reload
test:
pipenv run pytest tests/unit
integration-test:
pipenv run pytest tests/integration
coverage:
pipenv run pytest tests/unit --doctest-modules --junitxml=junit/test-results.xml --cov=app --cov-report=xml --cov-report=html
lint:
pipenv run pylint app

20
api/Pipfile Normal file
View file

@ -0,0 +1,20 @@
[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"
[dev-packages]
pylint = "*"
"autopep8" = "*"
pytest = "*"
faker = "*"
pytest-cov = "*"
[packages]
flask = "==2.3.3"
gunicorn = "==23.0.0"
flask-cors = "*"
requests = "*"
[requires]
python_version = "3.10"

537
api/Pipfile.lock generated Normal file
View file

@ -0,0 +1,537 @@
{
"_meta": {
"hash": {
"sha256": "f6f64f98b5a43dd63c066229dd8866534e3be090d684e4275703374980436cf7"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.10"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.python.org/simple",
"verify_ssl": true
}
]
},
"default": {
"blinker": {
"hashes": [
"sha256:1779309f71bf239144b9399d06ae925637cf6634cf6bd131104184531bf67c01",
"sha256:8f77b09d3bf7c795e969e9486f39c2c5e9c39d4ee07424be2bc594ece9642d83"
],
"markers": "python_version >= '3.8'",
"version": "==1.8.2"
},
"certifi": {
"hashes": [
"sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b",
"sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"
],
"markers": "python_version >= '3.6'",
"version": "==2024.7.4"
},
"charset-normalizer": {
"hashes": [
"sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027",
"sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087",
"sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786",
"sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8",
"sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09",
"sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185",
"sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574",
"sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e",
"sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519",
"sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898",
"sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269",
"sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3",
"sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f",
"sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6",
"sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8",
"sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a",
"sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73",
"sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc",
"sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714",
"sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2",
"sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc",
"sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce",
"sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d",
"sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e",
"sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6",
"sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269",
"sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96",
"sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d",
"sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a",
"sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4",
"sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77",
"sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d",
"sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0",
"sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed",
"sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068",
"sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac",
"sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25",
"sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8",
"sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab",
"sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26",
"sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2",
"sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db",
"sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f",
"sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5",
"sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99",
"sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c",
"sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d",
"sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811",
"sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa",
"sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a",
"sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03",
"sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b",
"sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04",
"sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c",
"sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001",
"sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458",
"sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389",
"sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99",
"sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985",
"sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537",
"sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238",
"sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f",
"sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d",
"sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796",
"sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a",
"sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143",
"sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8",
"sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c",
"sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5",
"sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5",
"sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711",
"sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4",
"sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6",
"sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c",
"sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7",
"sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4",
"sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b",
"sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae",
"sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12",
"sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c",
"sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae",
"sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8",
"sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887",
"sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b",
"sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4",
"sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f",
"sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5",
"sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33",
"sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519",
"sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"
],
"markers": "python_full_version >= '3.7.0'",
"version": "==3.3.2"
},
"click": {
"hashes": [
"sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28",
"sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"
],
"markers": "python_version >= '3.7'",
"version": "==8.1.7"
},
"flask": {
"hashes": [
"sha256:09c347a92aa7ff4a8e7f3206795f30d826654baf38b873d0744cd571ca609efc",
"sha256:f69fcd559dc907ed196ab9df0e48471709175e696d6e698dd4dbe940f96ce66b"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==2.3.3"
},
"flask-cors": {
"hashes": [
"sha256:eeb69b342142fdbf4766ad99357a7f3876a2ceb77689dc10ff912aac06c389e4",
"sha256:f2a704e4458665580c074b714c4627dd5a306b333deb9074d0b1794dfa2fb677"
],
"index": "pypi",
"version": "==4.0.1"
},
"gunicorn": {
"hashes": [
"sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d",
"sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==23.0.0"
},
"idna": {
"hashes": [
"sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc",
"sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"
],
"markers": "python_version >= '3.5'",
"version": "==3.7"
},
"itsdangerous": {
"hashes": [
"sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef",
"sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"
],
"markers": "python_version >= '3.8'",
"version": "==2.2.0"
},
"jinja2": {
"hashes": [
"sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369",
"sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"
],
"markers": "python_version >= '3.7'",
"version": "==3.1.4"
},
"markupsafe": {
"hashes": [
"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.5"
},
"packaging": {
"hashes": [
"sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002",
"sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"
],
"markers": "python_version >= '3.8'",
"version": "==24.1"
},
"requests": {
"hashes": [
"sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760",
"sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==2.32.3"
},
"urllib3": {
"hashes": [
"sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472",
"sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"
],
"markers": "python_version >= '3.8'",
"version": "==2.2.2"
},
"werkzeug": {
"hashes": [
"sha256:097e5bfda9f0aba8da6b8545146def481d06aa7d3266e7448e2cccf67dd8bd18",
"sha256:fc9645dc43e03e4d630d23143a04a7f947a9a3b5727cd535fdfe155a17cc48c8"
],
"markers": "python_version >= '3.8'",
"version": "==3.0.3"
}
},
"develop": {
"astroid": {
"hashes": [
"sha256:0e14202810b30da1b735827f78f5157be2bbd4a7a59b7707ca0bfc2fb4c0063a",
"sha256:413658a61eeca6202a59231abb473f932038fbcbf1666587f66d482083413a25"
],
"markers": "python_full_version >= '3.8.0'",
"version": "==3.2.4"
},
"autopep8": {
"hashes": [
"sha256:8d6c87eba648fdcfc83e29b788910b8643171c395d9c4bcf115ece035b9c9dda",
"sha256:a203fe0fcad7939987422140ab17a930f684763bf7335bdb6709991dd7ef6c2d"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==2.3.1"
},
"coverage": {
"extras": [
"toml"
],
"hashes": [
"sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca",
"sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d",
"sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6",
"sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989",
"sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c",
"sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b",
"sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223",
"sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f",
"sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56",
"sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3",
"sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8",
"sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb",
"sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388",
"sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0",
"sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a",
"sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8",
"sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f",
"sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a",
"sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962",
"sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8",
"sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391",
"sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc",
"sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2",
"sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155",
"sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb",
"sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0",
"sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c",
"sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a",
"sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004",
"sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060",
"sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232",
"sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93",
"sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129",
"sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163",
"sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de",
"sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6",
"sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23",
"sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569",
"sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d",
"sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778",
"sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d",
"sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36",
"sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a",
"sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6",
"sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34",
"sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704",
"sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106",
"sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9",
"sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862",
"sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b",
"sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255",
"sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16",
"sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3",
"sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133",
"sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb",
"sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657",
"sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d",
"sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca",
"sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36",
"sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c",
"sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e",
"sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff",
"sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7",
"sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5",
"sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02",
"sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c",
"sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df",
"sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3",
"sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a",
"sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959",
"sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234",
"sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc"
],
"markers": "python_version >= '3.8'",
"version": "==7.6.1"
},
"dill": {
"hashes": [
"sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca",
"sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7"
],
"markers": "python_version < '3.11'",
"version": "==0.3.8"
},
"exceptiongroup": {
"hashes": [
"sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b",
"sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"
],
"markers": "python_version < '3.11'",
"version": "==1.2.2"
},
"faker": {
"hashes": [
"sha256:7c10ebdf74aaa0cc4fe6ec6db5a71e8598ec33503524bd4b5f4494785a5670dd",
"sha256:97fe1e7e953dd640ca2cd4dfac4db7c4d2432dd1b7a244a3313517707f3b54e9"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==26.3.0"
},
"iniconfig": {
"hashes": [
"sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3",
"sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"
],
"markers": "python_version >= '3.7'",
"version": "==2.0.0"
},
"isort": {
"hashes": [
"sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109",
"sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"
],
"markers": "python_full_version >= '3.8.0'",
"version": "==5.13.2"
},
"mccabe": {
"hashes": [
"sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325",
"sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"
],
"markers": "python_version >= '3.6'",
"version": "==0.7.0"
},
"packaging": {
"hashes": [
"sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002",
"sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"
],
"markers": "python_version >= '3.8'",
"version": "==24.1"
},
"platformdirs": {
"hashes": [
"sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee",
"sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"
],
"markers": "python_version >= '3.8'",
"version": "==4.2.2"
},
"pluggy": {
"hashes": [
"sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1",
"sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"
],
"markers": "python_version >= '3.8'",
"version": "==1.5.0"
},
"pycodestyle": {
"hashes": [
"sha256:46f0fb92069a7c28ab7bb558f05bfc0110dac69a0cd23c61ea0040283a9d78b3",
"sha256:6838eae08bbce4f6accd5d5572075c63626a15ee3e6f842df996bf62f6d73521"
],
"markers": "python_version >= '3.8'",
"version": "==2.12.1"
},
"pylint": {
"hashes": [
"sha256:03c8e3baa1d9fb995b12c1dbe00aa6c4bcef210c2a2634374aedeb22fb4a8f8f",
"sha256:a5d01678349454806cff6d886fb072294f56a58c4761278c97fb557d708e1eb3"
],
"index": "pypi",
"markers": "python_full_version >= '3.8.0'",
"version": "==3.2.6"
},
"pytest": {
"hashes": [
"sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5",
"sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==8.3.2"
},
"pytest-cov": {
"hashes": [
"sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652",
"sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==5.0.0"
},
"python-dateutil": {
"hashes": [
"sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3",
"sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.9.0.post0"
},
"six": {
"hashes": [
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.16.0"
},
"tomli": {
"hashes": [
"sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
"sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"
],
"markers": "python_version < '3.11'",
"version": "==2.0.1"
},
"tomlkit": {
"hashes": [
"sha256:08ad192699734149f5b97b45f1f18dad7eb1b6d16bc72ad0c2335772650d7b72",
"sha256:7075d3042d03b80f603482d69bf0c8f345c2b30e41699fd8883227f89972b264"
],
"markers": "python_version >= '3.8'",
"version": "==0.13.0"
},
"typing-extensions": {
"hashes": [
"sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d",
"sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"
],
"markers": "python_version < '3.11'",
"version": "==4.12.2"
}
}
}

0
api/app/__init__.py Normal file
View file

View file

View file

@ -0,0 +1,12 @@
"""app.healthcheck.blueprint
Module that deals with Blueprint-related stuff."""
from flask import Blueprint
from app.healthcheck import healthcheck
def create_blueprint():
"""Creates a Blueprint"""
blueprint = Blueprint('Health Check Blueprint', __name__)
blueprint.route('/')(healthcheck.route)
return blueprint

View file

@ -0,0 +1,16 @@
"""app.healthcheck.healthcheck
Module that deals with HealthCheck route."""
import logging
from flask import jsonify
log = logging.getLogger(__name__)
def route():
"""Returns health information"""
log.info("Healthcheck was requested")
return jsonify({
"message": "type shit"
})

23
api/app/main.py Normal file
View file

@ -0,0 +1,23 @@
"""app.main
Module that starts the Flask application
"""
import os
import logging
from flask import Flask
from flask_cors import CORS
from app.healthcheck import blueprint as health_check_blueprint
from app.songs import blueprint as songs_blueprint
LOG_FORMAT = ("%(levelname) -10s %(asctime)s %(name) "
"-30s %(funcName) -35s %(lineno) -5d: %(message)s")
logging.basicConfig(level=os.environ.get(
'LOG_LEVEL', 'INFO'), format=LOG_FORMAT)
# pylint: disable=C0103
app = Flask(__name__)
CORS(app)
app.register_blueprint(health_check_blueprint.create_blueprint())
app.register_blueprint(songs_blueprint.create_blueprint())

View file

View file

@ -0,0 +1,7 @@
from flask import Blueprint
from app.songs import latest_songs
def create_blueprint():
bp = Blueprint('Songs Blueprint', __name__)
bp.route('/<user>/latest-song', methods=['GET'])(latest_songs.route)
return bp

View file

@ -0,0 +1,24 @@
import os
import requests
from flask import jsonify, request
BASE_URL = 'https://ws.audioscrobbler.com/2.0/'
RECENT_TRACKS_PARAMS = 'method=user.getrecenttracks&limit=1&format=json'
TIMEOUT = 10
def route(user):
api_key = os.environ.get('LASTFM_API_KEY')
if not api_key:
return jsonify({"message": "INTERNAL_ERROR"}), 500
try:
req = requests.get(f"{BASE_URL}?{RECENT_TRACKS_PARAMS}&user={user}&api_key={api_key}", timeout=TIMEOUT)
lastfm_response = req.json()
recent_tracks = lastfm_response.get('recenttracks', {})
if 'track' not in recent_tracks or not recent_tracks['track']:
return jsonify({'message': 'NO_TRACKS_FOUND'}), 200
track = recent_tracks['track'][0]
if request.args.get('format') == 'shields.io':
return jsonify({'schemaVersion': 1, 'label': 'Last.FM Last Played Song', 'message': f"{track['name']} - {track['artist']['#text']}"}), 200
return jsonify({'track': track}), req.status_code
except Exception:
return jsonify({'message': 'INTERNAL_ERROR'}), 500

28535
api/get-pip.py Normal file

File diff suppressed because it is too large Load diff

116
api/pylint.conf Normal file
View file

@ -0,0 +1,116 @@
[MAIN]
extension-pkg-whitelist=
ignore=CVS
ignore-patterns=
jobs=1
load-plugins=
persistent=yes
unsafe-load-any-extension=no
[MESSAGES CONTROL]
confidence=
disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call
enable=
[REPORTS]
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
output-format=text
reports=no
score=yes
[REFACTORING]
max-nested-blocks=5
[MISCELLANEOUS]
notes=FIXME,XXX,TODO
[VARIABLES]
additional-builtins=
allow-global-unused-variables=yes
callbacks=cb_,_cb
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
ignored-argument-names=_.*|^ignored_|^unused_
init-import=no
redefining-builtins-modules=six.moves,future.builtins
[SPELLING]
spelling-dict=
spelling-ignore-words=
spelling-private-dict-file=
spelling-store-unknown-words=no
[BASIC]
argument-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
attr-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
bad-names=foo,bar,baz,toto,tutu,tata
class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
class-name-hint=[A-Z_][a-zA-Z0-9]+$
class-rgx=[A-Z_][a-zA-Z0-9]+$
const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
docstring-min-length=-1
function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
good-names=i,j,k,ex,Run,_
include-naming-hint=no
inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
name-group=
no-docstring-rgx=^_
property-classes=abc.abstractproperty
variable-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
[SIMILARITIES]
ignore-comments=yes
ignore-docstrings=yes
ignore-imports=no
min-similarity-lines=4
[LOGGING]
logging-modules=logging
[TYPECHECK]
contextmanager-decorators=contextlib.contextmanager
generated-members=
ignore-mixin-members=yes
ignore-on-opaque-inference=yes
ignored-classes=optparse.Values,thread._local,_thread._local
ignored-modules=
missing-member-hint=yes
missing-member-hint-distance=1
missing-member-max-choices=1
[FORMAT]
expected-line-ending-format=
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
indent-after-paren=4
indent-string=' '
max-line-length=100
max-module-lines=1000
no-space-check=trailing-comma,dict-separator
single-line-class-stmt=no
single-line-if-stmt=no
[CLASSES]
defining-attr-methods=__init__,__new__,setUp
exclude-protected=_asdict,_fields,_replace,_source,_make
valid-classmethod-first-arg=cls
valid-metaclass-classmethod-first-arg=mcs
[DESIGN]
max-args=5
max-attributes=7
max-bool-expr=5
max-branches=12
max-locals=15
max-parents=7
max-public-methods=20
max-returns=6
max-statements=50
min-public-methods=2
[IMPORTS]
allow-wildcard-with-all=no
analyse-fallback-blocks=no
deprecated-modules=regsub,TERMIOS,Bastion,rexec
ext-import-graph=
import-graph=
int-import-graph=
known-standard-library=
known-third-party=enchant
[EXCEPTIONS]
overgeneral-exceptions=Exception

0
api/setup.py Normal file
View file

0
api/tests/__init__.py Normal file
View file

View file

View file

@ -0,0 +1,20 @@
import pytest
import faker
import os
import tempfile
from app.main import app as flask_app
@pytest.fixture
def fake():
return faker.Faker()
@pytest.fixture
def client():
flask_app.config['TESTING'] = True
with flask_app.test_client() as client:
yield client

View file

View file

@ -0,0 +1,4 @@
def test_get_lastest_songs(client):
rv = client.get('/biahll/latest-song')
assert rv.status_code == 200
assert len(rv.json['track']) != None

View file

127
api/tests/unit/conftest.py Normal file
View file

@ -0,0 +1,127 @@
import pytest
import faker
import os
import tempfile
from app.main import app as flask_app
@pytest.fixture
def fake():
return faker.Faker()
@pytest.fixture
def client():
flask_app.config['TESTING'] = True
with flask_app.test_client() as client:
yield client
@pytest.fixture
def lastfm_response():
return {
"recenttracks": {
"@attr": {
"page": "1",
"perPage": "1",
"total": "229279",
"totalPages": "229279",
"user": "biahll"
},
"track": [
{
"@attr": {
"nowplaying": "true"
},
"album": {
"#text": "My My My!",
"mbid": ""
},
"artist": {
"#text": "Mother's Daughter",
"mbid": ""
},
"image": [
{
"#text": "https: //lastfm.freetls.fastly.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png",
"size": "small"
},
{
"#text": "https: //lastfm.freetls.fastly.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png",
"size": "medium"
},
{
"#text": "https://lastfm.freetls.fastly.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png",
"size": "large"
},
{
"#text": "https: //lastfm.freetls.fastly.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png",
"size": "extralarge"
}
],
"mbid": "",
"name": "My My My!",
"streamable": "0",
"url": "https: //www.last.fm/music/Mother%27s+Daughter/_/My+My+My!"
},
{
"album": {
"#text": "Glory Days (Japan Edition)",
"mbid": ""
},
"artist": {
"#text": "Little Mix",
"mbid": "38f59974-2f4d-4bfa-b2e3-d2696de1b675"
},
"date": {
"#text": "16 Jul 2020, 22: 30",
"uts": "1594938632"
},
"image": [
{
"#text": "https: //lastfm.freetls.fastly.net/i/u/34s/9e824c0b80bbf5c24807f22d081566c4.jpg",
"size": "small"
},
{
"#text": "https://lastfm.freetls.fastly.net/i/u/64s/9e824c0b80bbf5c24807f22d081566c4.jpg",
"size": "medium"
},
{
"#text": "https://lastfm.freetls.fastly.net/i/u/174s/9e824c0b80bbf5c24807f22d081566c4.jpg",
"size": "large"
},
{
"#text": "https: //lastfm.freetls.fastly.net/i/u/300x300/9e824c0b80bbf5c24807f22d081566c4.jpg",
"size": "extralarge"
}
],
"mbid": "02930d7b-3e67-41c5-9d6e-ad593228d441",
"name": "Shout Out to My Ex",
"streamable": "0",
"url": "https://www.last.fm/music/Little+Mix/_/Shout+Out+to+My+Ex"
}
]
}
}
@pytest.fixture
def lastfm_empty_response():
return {
"recenttracks": {
"@attr": {
"page": "1",
"perPage": "1",
"total": "1",
"totalPages": "1",
"user": "biahll"
},
"track": []
}
}
@pytest.fixture
def lastfm_no_recent_tracks_response():
return {}

View file

View file

@ -0,0 +1,8 @@
import os
from unittest.mock import patch
def test_get_healthcheck(client):
rv = client.get('/')
assert rv.status_code == 200

View file

View file

@ -0,0 +1,69 @@
import os
from unittest.mock import patch
@patch.dict(os.environ, {"LASTFM_API_KEY": ''})
def test_without_api_key(client):
rv = client.get('/user/latest-song')
assert rv.json['message'] == 'INTERNAL_ERROR'
assert rv.status_code == 500
@patch.dict(os.environ, {"LASTFM_API_KEY": 'something new'})
@patch('requests.get', side_effect=[Exception()])
def test_get_with_exception(requests, client):
rv = client.get('/user/latest-song')
assert rv.json['message'] == 'INTERNAL_ERROR'
assert rv.status_code == 500
@patch.dict(os.environ, {"LASTFM_API_KEY": 'something old'})
@patch('requests.get')
def test_get_with_success(mock_get, client, lastfm_response):
mock_get.return_value.status_code = 500
mock_get.return_value.json.return_value = lastfm_response
rv = client.get('/user/latest-song')
assert rv.json == {'track': lastfm_response['recenttracks']['track'][0]}
assert rv.status_code == mock_get.return_value.status_code
@patch.dict(os.environ, {"LASTFM_API_KEY": 'something old'})
@patch('requests.get')
def test_get_with_success_and_different_format(mock_get, client, lastfm_response):
mock_get.return_value.status_code = 200
mock_get.return_value.json.return_value = lastfm_response
rv = client.get('/user/latest-song?format=shields.io')
song = lastfm_response['recenttracks']['track'][0]['name']
artist = lastfm_response['recenttracks']['track'][0]['artist']['#text']
assert rv.json == {
'schemaVersion': 1,
'label': 'Last.FM Last Played Song',
'message': f"{song} - {artist}"
}
assert rv.status_code == mock_get.return_value.status_code
@patch.dict(os.environ, {"LASTFM_API_KEY": 'something old'})
@patch('requests.get')
def test_get_with_success_no_tracks(mock_get, client, lastfm_empty_response):
mock_get.return_value.status_code = 200
mock_get.return_value.json.return_value = lastfm_empty_response
rv = client.get('/user/latest-song')
assert rv.status_code == 200
assert rv.json == {
'message': 'NO_TRACKS_FOUND'
}
@patch.dict(os.environ, {"LASTFM_API_KEY": 'something old'})
@patch('requests.get')
def test_get_with_error_user_not_found_tracks(mock_get, client, lastfm_no_recent_tracks_response):
mock_get.return_value.status_code = 200
mock_get.return_value.json.return_value = lastfm_no_recent_tracks_response
rv = client.get('/user/latest-song')
assert rv.status_code == 404
assert rv.json == {
'message': 'USER_LIKELY_DOESNT_EXIST'
}

14
docker-compose.yml Normal file
View file

@ -0,0 +1,14 @@
version: "3"
services:
api:
build:
context: ./api
command: gunicorn --reload --bind 0.0.0.0:5000 app.main:app
ports:
- "5000:5000"
volumes:
- ./api/app:/usr/src/app
env_file:
- ./api/.env
working_dir: /usr/src/app