From 3f1a7d9a9dc99b00e83524f5319e45cd28f3e735 Mon Sep 17 00:00:00 2001 From: Christopher Charbonneau Wells Date: Wed, 2 Dec 2020 20:15:22 -0800 Subject: [PATCH] Refactor to remove pandas dependency (#177) * Use regular dicts for sleep pattern (WIP) * Remove dataframes code from sleep pattern graph * Reimplement UTC offset change handling * Move label formatting in to a function * Remove pandas! * Fix linting issue * Add dev requirements to generated requirements.txt * Stop committing Pipfile.lock Pipenv is designed to pin to a specific version of Python. Including the lock file can lead to failed builds or broken package configurations on different system architectures and/or Python versions. --- .gitignore | 6 + Dockerfile | 1 - Pipfile | 1 - Pipfile.lock | 571 -------------------------------- README.md | 6 - bin/pre_compile | 2 +- reports/graphs/sleep_pattern.py | 118 ++++--- requirements.txt | 65 ++-- 8 files changed, 100 insertions(+), 670 deletions(-) delete mode 100644 Pipfile.lock diff --git a/.gitignore b/.gitignore index 1e44891f..4cca7669 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,9 @@ docker-compose.yml # Django media root directory. /media + +# Pipfile.lock. +# Committing this file makes it difficult to support multiple Python versions as +# requirements can different between versions, but the Pipfile only supports +# locking to one version. +Pipfile.lock diff --git a/Dockerfile b/Dockerfile index c2904de9..08ccab30 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,6 @@ ENV PYTHONUNBUFFERED 1 RUN pip install --upgrade pipenv gunicorn WORKDIR /app COPY Pipfile /app/ -COPY Pipfile.lock /app/ RUN pipenv install --deploy --system ADD manage.py /app/ ADD api /app/api diff --git a/Pipfile b/Pipfile index 6a126e00..14851a96 100644 --- a/Pipfile +++ b/Pipfile @@ -8,7 +8,6 @@ djangorestframework = "*" django-filter = "*" django-widget-tweaks = "*" plotly = "*" -pandas = "*" faker = "*" dj-database-url = "*" gunicorn = "*" diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index 0657db7c..00000000 --- a/Pipfile.lock +++ /dev/null @@ -1,571 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "b4b3273cf82cabd1475cec47c4b7b5139e28e054527f5ce00e70635560f8bb4c" - }, - "pipfile-spec": 6, - "requires": {}, - "sources": [ - { - "url": "https://pypi.python.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "asgiref": { - "hashes": [ - "sha256:7e51911ee147dd685c3c8b805c0ad0cb58d360987b56953878f8c06d2d1c6f1a", - "sha256:9fc6fb5d39b8af147ba40765234fa822b39818b12cc80b35ad9b0cef3a476aed" - ], - "markers": "python_version >= '3.5'", - "version": "==3.2.10" - }, - "boto3": { - "hashes": [ - "sha256:60c78f96c690974cd388270e4c82e4807f5034c5544f8a26ec3c3844df726cff", - "sha256:8611d07488bb36b509d9a79a4ab593cf1c96f9c0d177733007568cbfa1079914" - ], - "version": "==1.16.4" - }, - "botocore": { - "hashes": [ - "sha256:c78fe2fb4790e9f06dc40a28402893f12088c4aa88b739475827d9674972f1c4", - "sha256:cd5d2fceef451ee28b149a0c7de848710daab52d8273330e092ccc316d42b2c7" - ], - "version": "==1.19.4" - }, - "defusedxml": { - "hashes": [ - "sha256:6687150770438374ab581bb7a1b327a847dd9c5749e396102de3fad4e8a3ef93", - "sha256:f684034d135af4c6cbb949b8a4d2ed61634515257a67299e5f940fbaa34377f5" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==0.6.0" - }, - "diff-match-patch": { - "hashes": [ - "sha256:8bf9d9c4e059d917b5c6312bac0c137971a32815ddbda9c682b949f2986b4d34", - "sha256:da6f5a01aa586df23dfc89f3827e1cafbb5420be9d87769eeb079ddfd9477a18" - ], - "markers": "python_version >= '2.7'", - "version": "==20200713" - }, - "dj-database-url": { - "hashes": [ - "sha256:4aeaeb1f573c74835b0686a2b46b85990571159ffc21aa57ecd4d1e1cb334163", - "sha256:851785365761ebe4994a921b433062309eb882fedd318e1b0fcecc607ed02da9" - ], - "version": "==0.5.0" - }, - "django": { - "hashes": [ - "sha256:a2127ad0150ec6966655bedf15dbbff9697cc86d61653db2da1afa506c0b04cc", - "sha256:c93c28ccf1d094cbd00d860e83128a39e45d2c571d3b54361713aaaf9a94cac4" - ], - "version": "==3.1.2" - }, - "django-filter": { - "hashes": [ - "sha256:84e9d5bb93f237e451db814ed422a3a625751cbc9968b484ecc74964a8696b06", - "sha256:e00d32cebdb3d54273c48f4f878f898dced8d5dfaad009438fe61ebdf535ace1" - ], - "version": "==2.4.0" - }, - "django-import-export": { - "hashes": [ - "sha256:401d76eca0a5c6cf43bffed16c06e509b9044ce8f6bcff264b776e3952830f1a", - "sha256:7610f6efff797d65f56c03ba34444507c0b0ccdffe9346c168b9894fc349c55e" - ], - "version": "==2.4.0" - }, - "django-storages": { - "hashes": [ - "sha256:12de8fb2605b9b57bfaf54b075280d7cbb3b3ee1ca4bc9b9add147af87fe3a2c", - "sha256:652275ab7844538c462b62810276c0244866f345878256a9e0e86f5b1283ae18" - ], - "version": "==1.10.1" - }, - "django-widget-tweaks": { - "hashes": [ - "sha256:9f91ca4217199b7671971d3c1f323a2bec71a0c27dec6260b3c006fa541bc489", - "sha256:f80bff4a8a59b278bb277a405a76a8b9a884e4bae7a6c70e78a39c626cd1c836" - ], - "version": "==1.4.8" - }, - "djangorestframework": { - "hashes": [ - "sha256:5c5071fcbad6dce16f566d492015c829ddb0df42965d488b878594aabc3aed21", - "sha256:d54452aedebb4b650254ca092f9f4f5df947cb1de6ab245d817b08b4f4156249" - ], - "version": "==3.12.1" - }, - "easy-thumbnails": { - "hashes": [ - "sha256:e4e7a0dd4001f56bfd4058428f2c91eafe27d33ef3b8b33ac4e013b159b9ff91" - ], - "version": "==2.7" - }, - "et-xmlfile": { - "hashes": [ - "sha256:614d9722d572f6246302c4491846d2c393c199cfa4edc9af593437691683335b" - ], - "version": "==1.0.1" - }, - "faker": { - "hashes": [ - "sha256:30afa8f564350770373f299d2d267bff42aaba699a7ae0a3b6f378b2a8170569", - "sha256:a7a36c3c657f06bd1e3e3821b9480f2a92017d8a26e150e464ab6b97743cbc92" - ], - "version": "==4.14.0" - }, - "gunicorn": { - "hashes": [ - "sha256:1904bb2b8a43658807108d59c3f3d56c2b6121a701161de0ddf9ad140073c626", - "sha256:cd4a810dd51bf497552cf3f863b575dabd73d6ad6a91075b65936b151cbf4f9c" - ], - "version": "==20.0.4" - }, - "jdcal": { - "hashes": [ - "sha256:1abf1305fce18b4e8aa248cf8fe0c56ce2032392bc64bbd61b5dff2a19ec8bba", - "sha256:472872e096eb8df219c23f2689fc336668bdb43d194094b5cc1707e1640acfc8" - ], - "version": "==1.4.1" - }, - "jmespath": { - "hashes": [ - "sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9", - "sha256:cdf6525904cc597730141d61b36f2e4b8ecc257c420fa2f4549bac2c2d0cb72f" - ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'", - "version": "==0.10.0" - }, - "markuppy": { - "hashes": [ - "sha256:1adee2c0a542af378fe84548ff6f6b0168f3cb7f426b46961038a2bcfaad0d5f" - ], - "version": "==1.14" - }, - "numpy": { - "hashes": [ - "sha256:04c7d4ebc5ff93d9822075ddb1751ff392a4375e5885299445fcebf877f179d5", - "sha256:0bfd85053d1e9f60234f28f63d4a5147ada7f432943c113a11afcf3e65d9d4c8", - "sha256:0c66da1d202c52051625e55a249da35b31f65a81cb56e4c69af0dfb8fb0125bf", - "sha256:0d310730e1e793527065ad7dde736197b705d0e4c9999775f212b03c44a8484c", - "sha256:1669ec8e42f169ff715a904c9b2105b6640f3f2a4c4c2cb4920ae8b2785dac65", - "sha256:2117536e968abb7357d34d754e3733b0d7113d4c9f1d921f21a3d96dec5ff716", - "sha256:3733640466733441295b0d6d3dcbf8e1ffa7e897d4d82903169529fd3386919a", - "sha256:4339741994c775396e1a274dba3609c69ab0f16056c1077f18979bec2a2c2e6e", - "sha256:51ee93e1fac3fe08ef54ff1c7f329db64d8a9c5557e6c8e908be9497ac76374b", - "sha256:54045b198aebf41bf6bf4088012777c1d11703bf74461d70cd350c0af2182e45", - "sha256:58d66a6b3b55178a1f8a5fe98df26ace76260a70de694d99577ddeab7eaa9a9d", - "sha256:59f3d687faea7a4f7f93bd9665e5b102f32f3fa28514f15b126f099b7997203d", - "sha256:62139af94728d22350a571b7c82795b9d59be77fc162414ada6c8b6a10ef5d02", - "sha256:7118f0a9f2f617f921ec7d278d981244ba83c85eea197be7c5a4f84af80a9c3c", - "sha256:7c6646314291d8f5ea900a7ea9c4261f834b5b62159ba2abe3836f4fa6705526", - "sha256:967c92435f0b3ba37a4257c48b8715b76741410467e2bdb1097e8391fccfae15", - "sha256:9a3001248b9231ed73894c773142658bab914645261275f675d86c290c37f66d", - "sha256:aba1d5daf1144b956bc87ffb87966791f5e9f3e1f6fab3d7f581db1f5b598f7a", - "sha256:addaa551b298052c16885fc70408d3848d4e2e7352de4e7a1e13e691abc734c1", - "sha256:b594f76771bc7fc8a044c5ba303427ee67c17a09b36e1fa32bde82f5c419d17a", - "sha256:c35a01777f81e7333bcf276b605f39c872e28295441c265cd0c860f4b40148c1", - "sha256:cebd4f4e64cfe87f2039e4725781f6326a61f095bc77b3716502bed812b385a9", - "sha256:d526fa58ae4aead839161535d59ea9565863bb0b0bdb3cc63214613fb16aced4", - "sha256:d7ac33585e1f09e7345aa902c281bd777fdb792432d27fca857f39b70e5dd31c", - "sha256:e6ddbdc5113628f15de7e4911c02aed74a4ccff531842c583e5032f6e5a179bd", - "sha256:eb25c381d168daf351147713f49c626030dcff7a393d5caa62515d415a6071d8" - ], - "markers": "python_version >= '3.6'", - "version": "==1.19.2" - }, - "odfpy": { - "hashes": [ - "sha256:db766a6e59c5103212f3cc92ec8dd50a0f3a02790233ed0b52148b70d3c438ec", - "sha256:fc3b8d1bc098eba4a0fda865a76d9d1e577c4ceec771426bcb169a82c5e9dfe0" - ], - "version": "==1.4.1" - }, - "openpyxl": { - "hashes": [ - "sha256:18e11f9a650128a12580a58e3daba14e00a11d9e907c554a17ea016bf1a2c71b", - "sha256:f7d666b569f729257082cf7ddc56262431878f602dcc2bc3980775c59439cdab" - ], - "version": "==3.0.5" - }, - "pandas": { - "hashes": [ - "sha256:206d7c3e5356dcadf082e64dc25c24bc8541718045826074f96346e9d6d05a20", - "sha256:24f61f40febe47edac271eda45d683e42838b7db2bd0f82574d9800259d2b182", - "sha256:3a038cd5da602b955d335aa80cbaa0e5774f68501ff47b9c21509906981478da", - "sha256:427be9938b2f79ab298de84f87693914cda238a27cf10580da96caf3dff64115", - "sha256:54f5f564058b0280d588c3758abde82e280702c440db5faf0c686b80336096f9", - "sha256:5a8a84b75ca3a29bb4263b35d5ed9fcaae2b062f014feed8c5daa897339c7d85", - "sha256:84a4ffe668df357e31f98c829536e3a7142c3036c82f996e639f644c5d32eda1", - "sha256:882012763668af54b48f1412bab95c5cc0a7ccce5a2a8221cfc3839a6e3394ef", - "sha256:920d30fdff65a079f071db635d282b4f583c2b26f2b58d5dca218aac7c59974d", - "sha256:a605054fbca71ed1d08bb2aef6f73c84a579bbac956bfe8f9718d5e84cb41248", - "sha256:b11b496c317dbe007898de699fd59eaf687d0fe8c1b7dad109db6010155d28ae", - "sha256:babbeda2f83b0686c9ad38d93b10516e68cdcd5771007eb80a763e98aaf44613", - "sha256:c22e40f1b4d162ca18eb6b2c572e63eef220dbc9cc3de0241cefb77972621bb7", - "sha256:ca31ac8578d48da354cf66a473d4d5ff99277ca71d321dc7ea4e6fad3c6bb0fd", - "sha256:ca71a5aa9eeb3ef5b31feca7d9b6369d6b3d0b2e9c85d7a89abe3ecb013f1e86", - "sha256:d6b1f9d506dc23da2915bcae5c5968990049c9cec44108bd9855d2c7c89d91dc", - "sha256:d89dbc58aec1544722a8d5046f880b597c497ef8a82c5fe695b4b2effafac5ec", - "sha256:df43ea0e9fd9f9672b0de9cac26d01255ad50481994bf3cb4687c21eec2d7bbc", - "sha256:fd6f05b6101d0e76f3e5c26a47be5be7be96ed84ef3981dc1852e76898e73594" - ], - "version": "==1.1.3" - }, - "pillow": { - "hashes": [ - "sha256:006de60d7580d81f4a1a7e9f0173dc90a932e3905cc4d47ea909bc946302311a", - "sha256:0a2e8d03787ec7ad71dc18aec9367c946ef8ef50e1e78c71f743bc3a770f9fae", - "sha256:0eeeae397e5a79dc088d8297a4c2c6f901f8fb30db47795113a4a605d0f1e5ce", - "sha256:11c5c6e9b02c9dac08af04f093eb5a2f84857df70a7d4a6a6ad461aca803fb9e", - "sha256:2fb113757a369a6cdb189f8df3226e995acfed0a8919a72416626af1a0a71140", - "sha256:4b0ef2470c4979e345e4e0cc1bbac65fda11d0d7b789dbac035e4c6ce3f98adb", - "sha256:59e903ca800c8cfd1ebe482349ec7c35687b95e98cefae213e271c8c7fffa021", - "sha256:5abd653a23c35d980b332bc0431d39663b1709d64142e3652890df4c9b6970f6", - "sha256:5f9403af9c790cc18411ea398a6950ee2def2a830ad0cfe6dc9122e6d528b302", - "sha256:6b4a8fd632b4ebee28282a9fef4c341835a1aa8671e2770b6f89adc8e8c2703c", - "sha256:6c1aca8231625115104a06e4389fcd9ec88f0c9befbabd80dc206c35561be271", - "sha256:795e91a60f291e75de2e20e6bdd67770f793c8605b553cb6e4387ce0cb302e09", - "sha256:7ba0ba61252ab23052e642abdb17fd08fdcfdbbf3b74c969a30c58ac1ade7cd3", - "sha256:7c9401e68730d6c4245b8e361d3d13e1035cbc94db86b49dc7da8bec235d0015", - "sha256:81f812d8f5e8a09b246515fac141e9d10113229bc33ea073fec11403b016bcf3", - "sha256:895d54c0ddc78a478c80f9c438579ac15f3e27bf442c2a9aa74d41d0e4d12544", - "sha256:8de332053707c80963b589b22f8e0229f1be1f3ca862a932c1bcd48dafb18dd8", - "sha256:92c882b70a40c79de9f5294dc99390671e07fc0b0113d472cbea3fde15db1792", - "sha256:95edb1ed513e68bddc2aee3de66ceaf743590bf16c023fb9977adc4be15bd3f0", - "sha256:b63d4ff734263ae4ce6593798bcfee6dbfb00523c82753a3a03cbc05555a9cc3", - "sha256:bd7bf289e05470b1bc74889d1466d9ad4a56d201f24397557b6f65c24a6844b8", - "sha256:cc3ea6b23954da84dbee8025c616040d9aa5eaf34ea6895a0a762ee9d3e12e11", - "sha256:cc9ec588c6ef3a1325fa032ec14d97b7309db493782ea8c304666fb10c3bd9a7", - "sha256:d3d07c86d4efa1facdf32aa878bd508c0dc4f87c48125cc16b937baa4e5b5e11", - "sha256:d8a96747df78cda35980905bf26e72960cba6d355ace4780d4bdde3b217cdf1e", - "sha256:e38d58d9138ef972fceb7aeec4be02e3f01d383723965bfcef14d174c8ccd039", - "sha256:eb472586374dc66b31e36e14720747595c2b265ae962987261f044e5cce644b5", - "sha256:fbd922f702582cb0d71ef94442bfca57624352622d75e3be7a1e7e9360b07e72" - ], - "markers": "python_version >= '3.6'", - "version": "==8.0.1" - }, - "plotly": { - "hashes": [ - "sha256:9ec2c9f4cceac7c595ebb77c98cbeb6566a97bef777508584d9bb7d9bcb8854c", - "sha256:c50babbb4f8ad12e2a4f004df5d80c1dbf10c38e9325b5ffb1146b383687ef52" - ], - "version": "==4.12.0" - }, - "psycopg2-binary": { - "hashes": [ - "sha256:0deac2af1a587ae12836aa07970f5cb91964f05a7c6cdb69d8425ff4c15d4e2c", - "sha256:0e4dc3d5996760104746e6cfcdb519d9d2cd27c738296525d5867ea695774e67", - "sha256:11b9c0ebce097180129e422379b824ae21c8f2a6596b159c7659e2e5a00e1aa0", - "sha256:1fabed9ea2acc4efe4671b92c669a213db744d2af8a9fc5d69a8e9bc14b7a9db", - "sha256:2dac98e85565d5688e8ab7bdea5446674a83a3945a8f416ad0110018d1501b94", - "sha256:42ec1035841b389e8cc3692277a0bd81cdfe0b65d575a2c8862cec7a80e62e52", - "sha256:6a32f3a4cb2f6e1a0b15215f448e8ce2da192fd4ff35084d80d5e39da683e79b", - "sha256:7312e931b90fe14f925729cde58022f5d034241918a5c4f9797cac62f6b3a9dd", - "sha256:7d92a09b788cbb1aec325af5fcba9fed7203897bbd9269d5691bb1e3bce29550", - "sha256:833709a5c66ca52f1d21d41865a637223b368c0ee76ea54ca5bad6f2526c7679", - "sha256:89705f45ce07b2dfa806ee84439ec67c5d9a0ef20154e0e475e2b2ed392a5b83", - "sha256:8cd0fb36c7412996859cb4606a35969dd01f4ea34d9812a141cd920c3b18be77", - "sha256:950bc22bb56ee6ff142a2cb9ee980b571dd0912b0334aa3fe0fe3788d860bea2", - "sha256:a0c50db33c32594305b0ef9abc0cb7db13de7621d2cadf8392a1d9b3c437ef77", - "sha256:a0eb43a07386c3f1f1ebb4dc7aafb13f67188eab896e7397aa1ee95a9c884eb2", - "sha256:aaa4213c862f0ef00022751161df35804127b78adf4a2755b9f991a507e425fd", - "sha256:ac0c682111fbf404525dfc0f18a8b5f11be52657d4f96e9fcb75daf4f3984859", - "sha256:ad20d2eb875aaa1ea6d0f2916949f5c08a19c74d05b16ce6ebf6d24f2c9f75d1", - "sha256:b4afc542c0ac0db720cf516dd20c0846f71c248d2b3d21013aa0d4ef9c71ca25", - "sha256:b8a3715b3c4e604bcc94c90a825cd7f5635417453b253499664f784fc4da0152", - "sha256:ba28584e6bca48c59eecbf7efb1576ca214b47f05194646b081717fa628dfddf", - "sha256:ba381aec3a5dc29634f20692349d73f2d21f17653bda1decf0b52b11d694541f", - "sha256:bd1be66dde2b82f80afb9459fc618216753f67109b859a361cf7def5c7968729", - "sha256:c2507d796fca339c8fb03216364cca68d87e037c1f774977c8fc377627d01c71", - "sha256:cec7e622ebc545dbb4564e483dd20e4e404da17ae07e06f3e780b2dacd5cee66", - "sha256:d14b140a4439d816e3b1229a4a525df917d6ea22a0771a2a78332273fd9528a4", - "sha256:d1b4ab59e02d9008efe10ceabd0b31e79519da6fb67f7d8e8977118832d0f449", - "sha256:d5227b229005a696cc67676e24c214740efd90b148de5733419ac9aaba3773da", - "sha256:e1f57aa70d3f7cc6947fd88636a481638263ba04a742b4a37dd25c373e41491a", - "sha256:e74a55f6bad0e7d3968399deb50f61f4db1926acf4a6d83beaaa7df986f48b1c", - "sha256:e82aba2188b9ba309fd8e271702bd0d0fc9148ae3150532bbb474f4590039ffb", - "sha256:ee69dad2c7155756ad114c02db06002f4cded41132cc51378e57aad79cc8e4f4", - "sha256:f5ab93a2cb2d8338b1674be43b442a7f544a0971da062a5da774ed40587f18f5" - ], - "version": "==2.8.6" - }, - "python-dateutil": { - "hashes": [ - "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", - "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", - "version": "==2.8.1" - }, - "python-dotenv": { - "hashes": [ - "sha256:8c10c99a1b25d9a68058a1ad6f90381a62ba68230ca93966882a4dbc3bc9c33d", - "sha256:c10863aee750ad720f4f43436565e4c1698798d763b63234fb5021b6c616e423" - ], - "version": "==0.14.0" - }, - "pytz": { - "hashes": [ - "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed", - "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048" - ], - "version": "==2020.1" - }, - "pyyaml": { - "hashes": [ - "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97", - "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76", - "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2", - "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648", - "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf", - "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f", - "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2", - "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee", - "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d", - "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c", - "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a" - ], - "version": "==5.3.1" - }, - "retrying": { - "hashes": [ - "sha256:08c039560a6da2fe4f2c426d0766e284d3b736e355f8dd24b37367b0bb41973b" - ], - "version": "==1.3.3" - }, - "s3transfer": { - "hashes": [ - "sha256:2482b4259524933a022d59da830f51bd746db62f047d6eb213f2f8855dcb8a13", - "sha256:921a37e2aefc64145e7b73d50c71bb4f26f46e4c9f414dc648c6245ff92cf7db" - ], - "version": "==0.3.3" - }, - "six": { - "hashes": [ - "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", - "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", - "version": "==1.15.0" - }, - "sqlparse": { - "hashes": [ - "sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0", - "sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8" - ], - "markers": "python_version >= '3.5'", - "version": "==0.4.1" - }, - "tablib": { - "extras": [ - "html", - "ods", - "xls", - "xlsx", - "yaml" - ], - "hashes": [ - "sha256:8cc2fa10bc37219ac5e76850eb7fbd50de313c7a1a7895c44af2a8dd206b7be7", - "sha256:c5a77c96ad306d5b380def1309d521ad5e98b4f83726f84857ad87e142d13279" - ], - "markers": "python_version >= '3.5'", - "version": "==2.0.0" - }, - "text-unidecode": { - "hashes": [ - "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", - "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93" - ], - "version": "==1.3" - }, - "uritemplate": { - "hashes": [ - "sha256:07620c3f3f8eed1f12600845892b0e036a2420acf513c53f7de0abd911a5894f", - "sha256:5af8ad10cec94f215e3f48112de2022e1d5a37ed427fbd88652fa908f2ab7cae" - ], - "version": "==3.0.1" - }, - "urllib3": { - "hashes": [ - "sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2", - "sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e" - ], - "markers": "python_version != '3.4'", - "version": "==1.25.11" - }, - "whitenoise": { - "hashes": [ - "sha256:05ce0be39ad85740a78750c86a93485c40f08ad8c62a6006de0233765996e5c7", - "sha256:05d00198c777028d72d8b0bbd234db605ef6d60e9410125124002518a48e515d" - ], - "version": "==5.2.0" - }, - "xlrd": { - "hashes": [ - "sha256:546eb36cee8db40c3eaa46c351e67ffee6eeb5fa2650b71bc4c758a29a1b29b2", - "sha256:e551fb498759fa3a5384a94ccd4c3c02eb7c00ea424426e212ac0c57be9dfbde" - ], - "version": "==1.2.0" - }, - "xlwt": { - "hashes": [ - "sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e", - "sha256:c59912717a9b28f1a3c2a98fd60741014b06b043936dcecbc113eaaada156c88" - ], - "version": "==1.3.0" - } - }, - "develop": { - "certifi": { - "hashes": [ - "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3", - "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41" - ], - "version": "==2020.6.20" - }, - "chardet": { - "hashes": [ - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" - ], - "version": "==3.0.4" - }, - "coverage": { - "hashes": [ - "sha256:0203acd33d2298e19b57451ebb0bed0ab0c602e5cf5a818591b4918b1f97d516", - "sha256:0f313707cdecd5cd3e217fc68c78a960b616604b559e9ea60cc16795c4304259", - "sha256:1c6703094c81fa55b816f5ae542c6ffc625fec769f22b053adb42ad712d086c9", - "sha256:1d44bb3a652fed01f1f2c10d5477956116e9b391320c94d36c6bf13b088a1097", - "sha256:280baa8ec489c4f542f8940f9c4c2181f0306a8ee1a54eceba071a449fb870a0", - "sha256:29a6272fec10623fcbe158fdf9abc7a5fa032048ac1d8631f14b50fbfc10d17f", - "sha256:2b31f46bf7b31e6aa690d4c7a3d51bb262438c6dcb0d528adde446531d0d3bb7", - "sha256:2d43af2be93ffbad25dd959899b5b809618a496926146ce98ee0b23683f8c51c", - "sha256:381ead10b9b9af5f64646cd27107fb27b614ee7040bb1226f9c07ba96625cbb5", - "sha256:47a11bdbd8ada9b7ee628596f9d97fbd3851bd9999d398e9436bd67376dbece7", - "sha256:4d6a42744139a7fa5b46a264874a781e8694bb32f1d76d8137b68138686f1729", - "sha256:50691e744714856f03a86df3e2bff847c2acede4c191f9a1da38f088df342978", - "sha256:530cc8aaf11cc2ac7430f3614b04645662ef20c348dce4167c22d99bec3480e9", - "sha256:582ddfbe712025448206a5bc45855d16c2e491c2dd102ee9a2841418ac1c629f", - "sha256:63808c30b41f3bbf65e29f7280bf793c79f54fb807057de7e5238ffc7cc4d7b9", - "sha256:71b69bd716698fa62cd97137d6f2fdf49f534decb23a2c6fc80813e8b7be6822", - "sha256:7858847f2d84bf6e64c7f66498e851c54de8ea06a6f96a32a1d192d846734418", - "sha256:78e93cc3571fd928a39c0b26767c986188a4118edc67bc0695bc7a284da22e82", - "sha256:7f43286f13d91a34fadf61ae252a51a130223c52bfefb50310d5b2deb062cf0f", - "sha256:86e9f8cd4b0cdd57b4ae71a9c186717daa4c5a99f3238a8723f416256e0b064d", - "sha256:8f264ba2701b8c9f815b272ad568d555ef98dfe1576802ab3149c3629a9f2221", - "sha256:9342dd70a1e151684727c9c91ea003b2fb33523bf19385d4554f7897ca0141d4", - "sha256:9361de40701666b034c59ad9e317bae95c973b9ff92513dd0eced11c6adf2e21", - "sha256:9669179786254a2e7e57f0ecf224e978471491d660aaca833f845b72a2df3709", - "sha256:aac1ba0a253e17889550ddb1b60a2063f7474155465577caa2a3b131224cfd54", - "sha256:aef72eae10b5e3116bac6957de1df4d75909fc76d1499a53fb6387434b6bcd8d", - "sha256:bd3166bb3b111e76a4f8e2980fa1addf2920a4ca9b2b8ca36a3bc3dedc618270", - "sha256:c1b78fb9700fc961f53386ad2fd86d87091e06ede5d118b8a50dea285a071c24", - "sha256:c3888a051226e676e383de03bf49eb633cd39fc829516e5334e69b8d81aae751", - "sha256:c5f17ad25d2c1286436761b462e22b5020d83316f8e8fcb5deb2b3151f8f1d3a", - "sha256:c851b35fc078389bc16b915a0a7c1d5923e12e2c5aeec58c52f4aa8085ac8237", - "sha256:cb7df71de0af56000115eafd000b867d1261f786b5eebd88a0ca6360cccfaca7", - "sha256:cedb2f9e1f990918ea061f28a0f0077a07702e3819602d3507e2ff98c8d20636", - "sha256:e8caf961e1b1a945db76f1b5fa9c91498d15f545ac0ababbe575cfab185d3bd8" - ], - "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": "==5.3" - }, - "coveralls": { - "hashes": [ - "sha256:4430b862baabb3cf090d36d84d331966615e4288d8a8c5957e0fd456d0dd8bd6", - "sha256:b3b60c17b03a0dee61952a91aed6f131e0b2ac8bd5da909389c53137811409e1" - ], - "version": "==2.1.2" - }, - "docopt": { - "hashes": [ - "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491" - ], - "version": "==0.6.2" - }, - "flake8": { - "hashes": [ - "sha256:749dbbd6bfd0cf1318af27bf97a14e28e5ff548ef8e5b1566ccfb25a11e7c839", - "sha256:aadae8761ec651813c24be05c6f7b4680857ef6afaae4651a4eccaef97ce6c3b" - ], - "version": "==3.8.4" - }, - "idna": { - "hashes": [ - "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", - "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.10" - }, - "importlib-metadata": { - "hashes": [ - "sha256:77a540690e24b0305878c37ffd421785a6f7e53c8b5720d211b211de8d0e95da", - "sha256:cefa1a2f919b866c5beb7c9f7b0ebb4061f30a8a9bf16d609b000e2dfaceb9c3" - ], - "markers": "python_version < '3.8'", - "version": "==2.0.0" - }, - "ipaddress": { - "hashes": [ - "sha256:6e0f4a39e66cb5bb9a137b00276a2eff74f93b71dcbdad6f10ff7df9d3557fcc", - "sha256:b7f8e0369580bb4a24d5ba1d7cc29660a4a6987763faf1d8a8046830e020e7e2" - ], - "version": "==1.0.23" - }, - "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" - }, - "requests": { - "hashes": [ - "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b", - "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==2.24.0" - }, - "urllib3": { - "hashes": [ - "sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2", - "sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e" - ], - "markers": "python_version != '3.4'", - "version": "==1.25.11" - }, - "zipp": { - "hashes": [ - "sha256:102c24ef8f171fd729d46599845e95c7ab894a4cf45f5de11a44cc7444fb1108", - "sha256:ed5eee1974372595f9e416cc7bbeeb12335201d8081ca8a0743c954d4446e5cb" - ], - "markers": "python_version >= '3.6'", - "version": "==3.4.0" - } - } -} diff --git a/README.md b/README.md index 71af6e68..bc53af53 100644 --- a/README.md +++ b/README.md @@ -190,12 +190,6 @@ Python 3.6+, nginx, uwsgi and sqlite and should be sufficient for a few users pipenv install --three pipenv shell - - **Note:** Python dependencies are locked on x86-64 architecture. Installs - on other architectures (like Raspberry Pi's ARM) may result in a - ``THESE PACKAGES DO NOT MATCH THE HASHES FROM Pipfile.lock!`` error. Add - the ``--skip-lock`` flag to the above command to suppress this error - (i.e.: ``pipenv install --three --dev --skip-lock``). 1. Create a production settings file and set the ``SECRET_KEY`` and ``ALLOWED_HOSTS`` values diff --git a/bin/pre_compile b/bin/pre_compile index 63622046..e74783b3 100644 --- a/bin/pre_compile +++ b/bin/pre_compile @@ -6,4 +6,4 @@ set -euo pipefail # Prevent heroku-buildpack-python from using pipenv instead of pip and requirements.txt. # https://github.com/heroku/heroku-buildpack-python/issues/704 -rm Pipfile Pipfile.lock \ No newline at end of file +rm Pipfile \ No newline at end of file diff --git a/reports/graphs/sleep_pattern.py b/reports/graphs/sleep_pattern.py index f38ccd20..e7e67295 100644 --- a/reports/graphs/sleep_pattern.py +++ b/reports/graphs/sleep_pattern.py @@ -4,7 +4,6 @@ from collections import OrderedDict from django.utils import timezone from django.utils.translation import gettext as _ -import pandas as pd import plotly.offline as plotly import plotly.graph_objs as go @@ -19,36 +18,35 @@ def sleep_pattern(instances): :param instances: a QuerySet of Sleep instances. :returns: a tuple of the the graph's html and javascript. """ - # TODO: Simplify this using the bar charts "base" property. - y_df = pd.DataFrame() - text_df = pd.DataFrame() + times = {} + labels = {} last_end_time = None adjustment = None - df_index = 0 for instance in instances: start_time = timezone.localtime(instance.start) end_time = timezone.localtime(instance.end) start_date = start_time.date().isoformat() duration = instance.duration + if start_date not in times: + times[start_date] = [] + if start_date not in labels: + labels[start_date] = [] + # Check if the previous entry crossed midnight (see below). if adjustment: # Fake (0) entry to keep the color switching logic working. - df_index = _add_sleep_entry( - y_df, text_df, 0, adjustment['column'], 0) + times[adjustment['column']].append(0) + labels[adjustment['column']].append(0) + # Real adjustment entry. - df_index = _add_sleep_entry( - y_df, - text_df, - df_index, - adjustment['column'], - adjustment['duration'].seconds/60, - 'Asleep {} ({} to {})'.format( - duration_string(adjustment['duration']), - adjustment['start_time'].strftime('%I:%M %p'), - adjustment['end_time'].strftime('%I:%M %p') - ) - ) + times[adjustment['column']].append( + adjustment['duration'].seconds/60) + labels[adjustment['column']].append(_format_label( + adjustment['duration'], + adjustment['start_time'], + adjustment['end_time'])) + last_end_time = timezone.localtime(adjustment['end_time']) adjustment = None @@ -68,49 +66,53 @@ def sleep_pattern(instances): day=start_time.day, hour=23, minute=59, second=0) duration = end_time - start_time - if start_date not in y_df: + if not last_end_time: last_end_time = start_time.replace(hour=0, minute=0, second=0) # Awake time. - df_index = _add_sleep_entry( - y_df, - text_df, - df_index, - start_date, - (start_time - last_end_time).seconds/60 - ) + times[start_date].append((start_time - last_end_time).seconds/60) + labels[start_date].append(None) # Asleep time. - df_index = _add_sleep_entry( - y_df, - text_df, - df_index, - start_date, - duration.seconds/60, - 'Asleep {} ({} to {})'.format( - duration_string(duration), - start_time.strftime('%I:%M %p'), - end_time.strftime('%I:%M %p') - ) - ) + times[start_date].append(duration.seconds/60) + labels[start_date].append(_format_label(duration, start_time, + end_time)) # Update the previous entry duration if an offset change occurred. # This can happen when an entry crosses a daylight savings time change. if start_time.utcoffset() != end_time.utcoffset(): diff = start_time.utcoffset() - end_time.utcoffset() duration -= timezone.timedelta(seconds=diff.seconds) - y_df.at[df_index - 1, start_date] = duration.seconds/60 + times[len(times) - 1] = duration.seconds/60 + labels[len(labels) - 1] = _format_label(duration, start_time, + end_time) last_end_time = end_time - dates = list(y_df) + dates = list(times.keys()) traces = [] color = 'rgba(255, 255, 255, 0)' - for index, row in y_df.iterrows(): + + # Set iterator and determine maximum iteration for dates. + i = 0 + max_i = 0 + for date_times in times.values(): + max_i = max(len(date_times), max_i) + while i < max_i: + y = {} + text = {} + for date in times.keys(): + try: + y[date] = times[date][i] + text[date] = labels[date][i] + except IndexError: + y[date] = None + text[date] = None + i += 1 traces.append(go.Bar( x=dates, - y=row, - text=text_df.iloc[index], + y=list(y.values()), + text=list(text.values()), hoverinfo='text', marker={'color': color}, marker_line_width=0, @@ -155,23 +157,15 @@ def sleep_pattern(instances): return utils.split_graph_output(output) -def _add_sleep_entry(y_df, text_df, index, column, duration, text=''): +def _format_label(duration, start_time, end_time): """ - Create a duration and text description entry in a DataFrame and return - the next index on success. - :param y_df: the y values DataFrame. - :param text_df: the text values DataFrame. - :param index: the index to target in both y_df and text_df. - :param column: the column (date) to make the entry in. - :param duration: the duration of the entry. - :param text: text to go with the entry (displays on graph hover). - :return: the next index of the DataFrames. + Formats a time block label. + :param duration: Duration. + :param start_time: Start time. + :param end_time: End time. + :return: Formatted string with duration, start, and end time. """ - if column not in y_df: - y_df.assign(**{column: 0 in range(0, len(y_df.index))}) - text_df.assign(**{column: 0 in range(0, len(text_df.index))}) - index = 0 - - y_df.at[index, column] = duration - text_df.at[index, column] = text - return index + 1 + return 'Asleep {} ({} to {})'.format( + duration_string(duration), + start_time.strftime('%I:%M %p'), + end_time.strftime('%I:%M %p')) diff --git a/requirements.txt b/requirements.txt index 4b081304..66a7021f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,43 +1,52 @@ -i https://pypi.python.org/simple -asgiref==3.2.10 -boto3==1.14.25 -botocore==1.17.25 -defusedxml==0.6.0 -diff-match-patch==20200713 +asgiref==3.3.1; python_version >= '3.5' +boto3==1.16.28 +botocore==1.19.28 +certifi==2020.11.8 +chardet==3.0.4 +coverage==5.3; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4' +coveralls==2.2.0 +defusedxml==0.6.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' +diff-match-patch==20200713; python_version >= '2.7' dj-database-url==0.5.0 -django-filter==2.3.0 -django-import-export==2.3.0 -django-storages==1.9.1 +django-filter==2.4.0 +django-import-export==2.4.0 +django-storages==1.10.1 django-widget-tweaks==1.4.8 -django==3.0.8 -djangorestframework==3.11.0 -docutils==0.15.2 -easy-thumbnails==2.7 +django==3.1.4 +djangorestframework==3.12.2 +docopt==0.6.2 +easy-thumbnails==2.7.1 et-xmlfile==1.0.1 -faker==4.1.1 +faker==4.18.0 +flake8==3.8.4 gunicorn==20.0.4 +idna==2.10; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' +ipaddress==1.0.23 jdcal==1.4.1 -jmespath==0.10.0 +jmespath==0.10.0; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2' markuppy==1.14 -numpy==1.19.1 +mccabe==0.6.1 odfpy==1.4.1 -openpyxl==3.0.4 -pandas==1.0.5 -pillow==7.2.0 -plotly==4.9.0 -psycopg2-binary==2.8.5 -python-dateutil==2.8.1 -python-dotenv==0.14.0 -pytz==2020.1 +openpyxl==3.0.5 +pillow==8.0.1; python_version >= '3.6' +plotly==4.13.0 +psycopg2-binary==2.8.6 +pycodestyle==2.6.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' +pyflakes==2.2.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' +python-dateutil==2.8.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2' +python-dotenv==0.15.0 +pytz==2020.4 pyyaml==5.3.1 +requests==2.25.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' retrying==1.3.3 s3transfer==0.3.3 -six==1.15.0 -sqlparse==0.3.1 -tablib[html,ods,xls,xlsx,yaml]==2.0.0 +six==1.15.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2' +sqlparse==0.4.1; python_version >= '3.5' +tablib[html,ods,xls,xlsx,yaml]==2.0.0; python_version >= '3.5' text-unidecode==1.3 uritemplate==3.0.1 -urllib3==1.25.9 ; python_version != '3.4' -whitenoise==5.1.0 +urllib3==1.26.2; python_version != '3.4' +whitenoise==5.2.0 xlrd==1.2.0 xlwt==1.3.0