From af7ef08f63f6c5fbf2c85ee54fc6935cca9004bc Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Fri, 26 Mar 2021 21:11:22 +0000 Subject: [PATCH 01/15] Move away from poetry More or less everything is now done by setup.py Pipfile simply installs the module in editable mode, which recursively resolves dependencies as defined in setup.py. --- Pipfile | 20 + Pipfile.lock | 620 ++++++++++++++++++++++++++++++ openflexure_microscope/api/app.py | 8 +- pyproject.toml | 66 +--- setup.py | 161 ++++++++ 5 files changed, 810 insertions(+), 65 deletions(-) create mode 100644 Pipfile create mode 100644 Pipfile.lock create mode 100644 setup.py diff --git a/Pipfile b/Pipfile new file mode 100644 index 00000000..346dc7bd --- /dev/null +++ b/Pipfile @@ -0,0 +1,20 @@ +[[source]] +url = "https://pypi.python.org/simple" +verify_ssl = true +name = "pypi" + +[[source]] +url = "https://www.piwheels.org/simple" +verify_ssl = true +name = "piwheels" + +[requires] +python_version = '3.7' + +[packages] +#openflexure-microscope-server = {path = "."} +#TODO: decide if we want dev dependencies here or in setup.py +openflexure-microscope-server = {editable = true, path = "."} + +[dev-packages] +#openflexure-microscope-server = {path = ".", editable=true, extras=["dev"]} diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 00000000..4e099b2f --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,620 @@ +{ + "_meta": { + "hash": { + "sha256": "eca50a11558f3212f61977ffa8512de91020af9a5126bad5be62e9286c7cbae5" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.7" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.python.org/simple", + "verify_ssl": true + }, + { + "name": "piwheels", + "url": "https://www.piwheels.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "apispec": { + "extras": [ + "yaml" + ], + "hashes": [ + "sha256:5ec0fe72f1422a1198973fcbb48d0eb5c7390f4b0fbe55474fce999ad6826a9b", + "sha256:83e4d30edce987f4791f950c847d2b8cbe91e55af3d1ac7e3a35011a5c6fdbdd" + ], + "markers": "python_version >= '3.6'", + "version": "==4.3.0" + }, + "apispec-webframeworks": { + "hashes": [ + "sha256:0db35b267914b3f8c562aca0261957dbcb4176f255eacc22520277010818dcf3", + "sha256:482c563abbcc2a261439476cb3f1a7c7284cc997c322c574d48c111643e9c04e" + ], + "markers": "python_version >= '3.6'", + "version": "==0.5.2" + }, + "atomicwrites": { + "hashes": [ + "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197", + "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a" + ], + "markers": "sys_platform == 'win32'", + "version": "==1.4.0" + }, + "attrs": { + "hashes": [ + "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6", + "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==20.3.0" + }, + "camera-stage-mapping": { + "hashes": [ + "sha256:02a409bd2cb193b20d9eb015ca31400bd3e1721ec5d702e1b96de54608ff5a8f", + "sha256:d39c3afebb59ec865fb1247dfd951d7090c159ab0cf3e4291e0869d3be33776c" + ], + "markers": "python_version >= '3.6' and python_version < '4'", + "version": "==0.1.4" + }, + "click": { + "hashes": [ + "sha256:a3747c864f8e400a3664f5f4fd6dae11b4605bf6b727dae7b6f22ba9bd0a194a", + "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" + }, + "colorama": { + "hashes": [ + "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b", + "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2" + ], + "markers": "sys_platform == 'win32'", + "version": "==0.4.4" + }, + "colorzero": { + "hashes": [ + "sha256:0e60d743a6b8071498a56465f7719c96a5e92928f858bab1be2a0d606c9aa0f8", + "sha256:e7d5a5c26cd0dc37b164ebefc609f388de24f8593b659191e12d85f8f9d5eb58" + ], + "version": "==2.0" + }, + "coverage": { + "hashes": [ + "sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c", + "sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6", + "sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45", + "sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a", + "sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03", + "sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529", + "sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a", + "sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a", + "sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2", + "sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6", + "sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759", + "sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53", + "sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a", + "sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4", + "sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff", + "sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502", + "sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793", + "sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb", + "sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905", + "sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821", + "sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b", + "sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81", + "sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0", + "sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b", + "sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3", + "sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184", + "sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701", + "sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a", + "sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82", + "sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638", + "sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5", + "sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083", + "sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6", + "sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90", + "sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465", + "sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a", + "sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3", + "sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e", + "sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066", + "sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf", + "sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b", + "sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae", + "sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669", + "sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873", + "sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b", + "sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6", + "sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb", + "sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160", + "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c", + "sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079", + "sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d", + "sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6" + ], + "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.5" + }, + "expiringdict": { + "hashes": [ + "sha256:3eb293ca7ff15ed283d8e3ae9bbc5b1cbd2d60c906b08b38c7437380e8a2f697", + "sha256:fe2ba427220425c3c8a3d29f6d2e2985bcee323f8bcd4021e68ebefbd90d8250" + ], + "version": "==1.2.1" + }, + "flask": { + "hashes": [ + "sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060", + "sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==1.1.2" + }, + "flask-cors": { + "hashes": [ + "sha256:74efc975af1194fc7891ff5cd85b0f7478be4f7f59fe158102e91abb72bb4438", + "sha256:b60839393f3b84a0f3746f6cdca56c1ad7426aa738b70d6c61375857823181de" + ], + "version": "==3.0.10" + }, + "future": { + "hashes": [ + "sha256:83c4f8cec14cd08179d8b4bfe8c5e48724efadac8add187f385c68d6ae2345e6", + "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.18.2" + }, + "ifaddr": { + "hashes": [ + "sha256:1f9e8a6ca6f16db5a37d3356f07b6e52344f6f9f7e806d618537731669eb1a94", + "sha256:d1f603952f0a71c9ab4e705754511e4e03b02565bc4cec7188ad6415ff534cd3" + ], + "version": "==0.1.7" + }, + "importlib-metadata": { + "hashes": [ + "sha256:742add720a20d0467df2f444ae41704000f50e1234f46174b51f9c6031a1bd71", + "sha256:b74159469b464a99cb8cc3e21973e4d96e05d3024d337313fedb618a6e86e6f4" + ], + "markers": "python_version < '3.8'", + "version": "==3.7.3" + }, + "iniconfig": { + "hashes": [ + "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3", + "sha256:8647b85c03813b8680f4ae9c9db2fd7293f8591ea536a10d73d90f6eb4b10aac", + "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32" + ], + "version": "==1.1.1" + }, + "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:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419", + "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.11.3" + }, + "labthings": { + "hashes": [ + "sha256:4f286ea585e596aeb67a02d5bd822b2c89828693026085829e15e415a2d2d287", + "sha256:970bb6a81f0e007b55e575e6eafe6bba10974d671f2767b91631f001ff53cf0e" + ], + "markers": "python_version >= '3.6' and python_version < '4'", + "version": "==1.2.4" + }, + "markupsafe": { + "hashes": [ + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:19536834abffb3fa155017053c607cb835b2ecc6a3a2554a88043d991dffb736", + "sha256:195d7d2c4fbb0ee8139a6cf67194f3973a6b3042d742ebe0a9ed36d8b6f0c07f", + "sha256:22c178a091fc6630d0d045bdb5992d2dfe14e3259760e713c490da5323866c39", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:2beec1e0de6924ea551859edb9e7679da6e4870d32cb766240ce17e0a0ba2014", + "sha256:3b8a6499709d29c2e2399569d96719a1b21dcd94410a586a18526b143ec8470f", + "sha256:3d61f15e39611aacd91b7e71d903787da86d9e80896e683c0103fced9add7834", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:6f1e273a344928347c1290119b493a1f0303c52f5a5eae5f16d74f48c15d4a85", + "sha256:6fffc775d90dcc9aed1b89219549b329a9250d918fd0b8fa8d93d154918422e1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:7952deddf24b85c88dab48f6ec366ac6e39d2761b5280f2f9594911e03fcd064", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:7fed13866cf14bba33e7176717346713881f56d9d2bcebab207f7a036f41b850", + "sha256:84dee80c15f1b560d55bcfe6d47b27d070b4681c699c572af2e3c7cc90a3b8e0", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98bae9582248d6cf62321dcb52aaf5d9adf0bad3b40582925ef7c7f0ed85fceb", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:a6a744282b7718a2a62d2ed9d993cad6f5f585605ad352c11de459f4108df0a1", + "sha256:acf08ac40292838b3cbbb06cfe9b2cb9ec78fce8baca31ddb87aaac2e2dc3bc2", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b1dba4527182c95a0db8b6060cc98ac49b9e2f5e64320e2b56e47cb2831978c7", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:b7d644ddb4dbd407d31ffb699f1d140bc35478da613b441c582aeb7c43838dd8", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:bf5aa3cbcfdf57fa2ee9cd1822c862ef23037f5c832ad09cfea57fa846dec193", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:caabedc8323f1e93231b52fc32bdcde6db817623d33e100708d9a68e1f53b26b", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:d53bc011414228441014aa71dbec320c66468c1030aae3a6e29778a3382d96e5", + "sha256:d73a845f227b0bfe8a7455ee623525ee656a9e2e749e4742706d80a6065d5e2c", + "sha256:d9be0ba6c527163cbed5e0857c451fcd092ce83947944d6c14bc95441203f032", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be", + "sha256:feb7b34d6325451ef96bc0e36e1a6c0c1c64bc1fbec4b854f4529e51887b1621" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.1.1" + }, + "marshmallow": { + "hashes": [ + "sha256:4ab2fdb7f36eb61c3665da67a7ce281c8900db08d72ba6bf0e695828253581f7", + "sha256:eca81d53aa4aafbc0e20566973d0d2e50ce8bf0ee15165bb799bec0df1e50177" + ], + "markers": "python_version >= '3.5'", + "version": "==3.10.0" + }, + "numpy": { + "hashes": [ + "sha256:032be656d89bbf786d743fee11d01ef318b0781281241997558fa7950028dd29", + "sha256:104f5e90b143dbf298361a99ac1af4cf59131218a045ebf4ee5990b83cff5fab", + "sha256:125a0e10ddd99a874fd357bfa1b636cd58deb78ba4a30b5ddb09f645c3512e04", + "sha256:12e4ba5c6420917571f1a5becc9338abbde71dd811ce40b37ba62dec7b39af6d", + "sha256:13adf545732bb23a796914fe5f891a12bd74cf3d2986eed7b7eba2941eea1590", + "sha256:23d6802e7f2ceb9a1572f375470478251e821bdb4babbbbf3f2420c858d5dbde", + "sha256:2d7e27442599104ee08f4faed56bb87c55f8b10a5494ac2ead5c98a4b289e61f", + "sha256:3bc63486a870294683980d76ec1e3efc786295ae00128f9ea38e2c6e74d5a60a", + "sha256:3d3087e24e354c18fb35c454026af3ed8997cfd4997765266897c68d724e4845", + "sha256:4ed8e96dc146e12c1c5cdd6fb9fd0757f2ba66048bf94c5126b7efebd12d0090", + "sha256:60759ab15c94dd0e1ed88241fd4fa3312db4e91d2c8f5a2d4cf3863fad83d65b", + "sha256:65410c7f4398a0047eea5cca9b74009ea61178efd78d1be9847fac1d6716ec1e", + "sha256:66b467adfcf628f66ea4ac6430ded0614f5cc06ba530d09571ea404789064adc", + "sha256:7199109fa46277be503393be9250b983f325880766f847885607d9b13848f257", + "sha256:72251e43ac426ff98ea802a931922c79b8d7596480300eb9f1b1e45e0543571e", + "sha256:89e5336f2bec0c726ac7e7cdae181b325a9c0ee24e604704ed830d241c5e47ff", + "sha256:89f937b13b8dd17b0099c7c2e22066883c86ca1575a975f754babc8fbf8d69a9", + "sha256:9c94cab5054bad82a70b2e77741271790304651d584e2cdfe2041488e753863b", + "sha256:9eb551d122fadca7774b97db8a112b77231dcccda8e91a5bc99e79890797175e", + "sha256:a1d7995d1023335e67fb070b2fae6f5968f5be3802b15ad6d79d81ecaa014fe0", + "sha256:ae61f02b84a0211abb56462a3b6cd1e7ec39d466d3160eb4e1da8bf6717cdbeb", + "sha256:b9410c0b6fed4a22554f072a86c361e417f0258838957b78bd063bde2c7f841f", + "sha256:c26287dfc888cf1e65181f39ea75e11f42ffc4f4529e5bd19add57ad458996e2", + "sha256:c91ec9569facd4757ade0888371eced2ecf49e7982ce5634cc2cf4e7331a4b14", + "sha256:ecb5b74c702358cdc21268ff4c37f7466357871f53a30e6f84c686952bef16a9" + ], + "markers": "python_version >= '3.7'", + "version": "==1.20.1" + }, + "opencv-python-headless": { + "hashes": [ + "sha256:0e02809db2968e54f3c23340be6ff9a1428b3f03f5dca7cd5aceda66e319ce86", + "sha256:1f7c14f5d4e5af4dc4669fc6b4a983b36072a934c439ac11266b930496da8255", + "sha256:243aea91cc1e36a47c46da4cc408071af39444a48df1fe1539ea8d7990500fd2", + "sha256:2560dcf3c1158226b066302f777bfe0f65282410b8d90871dd872306c967d1f1", + "sha256:2e6a9a88617a0ef7219cff24ba78a58416670a77e6ac63975f9009af3319ab63", + "sha256:372149d007e20bf556b7687591d22b58b56b3c225f492da051d81587e5dc7411", + "sha256:522f12dd994e064a30562adfd63b9439099bd7c80819f5261c37ebe593283c9e", + "sha256:526b9e19cf6300f0891d8f427eac1048091912332bb781eb4957a4994bfbe608", + "sha256:5f0c7d34fa9953706c2a1a6d2760a91dc5a68cab3df16af61609894c6c8586f1", + "sha256:657cdd9fbbbbb7e898ae3d9b0649b367d0e440d429c714104d069c5612d578bb", + "sha256:65c9ea57be5ebcaed009b3fee14fe59f3b6aa1e573fe08c5039ff057ad593c53", + "sha256:777fb596e04331f73ef5b0c1faa4d33348f29ca58216d9286355c16f5489c939", + "sha256:7c75680ffdf32d7044415a215d1fc60dbec14a7f2f0b59a85f0f74ef5efcb6ad", + "sha256:924aa4c34ead0b817309f42291dc526b2a7755476afe3009d1e275fc3090d92d", + "sha256:96d1da6ad061d8f3509668d398d14dd8265e529d6407f87eb26e7f4ddf043cc0", + "sha256:9aa04a491c534531029fbac61da961fae0bf4abb1786eed9c91befde4ca7bd81", + "sha256:a322d4df14c3a5f19701a023b3da91e9b8af8653b0d2ee0c50b0b341212f7343", + "sha256:aa562c520f46283423ba8fac29099458e42deab697a9abd0491622e421c5c454", + "sha256:ba2f0bd46e9534f29969e39f7895cbea9764173102b0c04b7818b8a9910d66e4", + "sha256:d16825755e7b5a6d8737f93e116670229e1510199e0af9213004e187ae0dbcc5", + "sha256:e3027e0d1b71b68b5cfe1ea9c627e323dff71112c854ba19805258d8fc6c630e", + "sha256:e61c8df818d79c6bd62a5a18a9b3bfdf389502798e3c22f95c67f8dcd09ce97b", + "sha256:f2011ecb3980bbed283d17d43e0f1221bac88c0cac1a6fb59a056544de2df2f7", + "sha256:f5e40a06116460ef2fd2d1c24be3b65f8bfb5fcdfe433f3fc01bcb4c2eb485bf", + "sha256:f7f8e4f7c63c8e95eb210f4cba88d0069a0a964d6335d7a35b07f0d0baa13558", + "sha256:fe02a943b1a28b505e954fbce24e867119a3eb4351f93adad55c6cfe81a70484" + ], + "markers": "python_version >= '3.6'", + "version": "==4.5.1.48" + }, + "openflexure-microscope-server": { + "editable": true, + "path": "." + }, + "packaging": { + "hashes": [ + "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5", + "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==20.9" + }, + "picamerax": { + "hashes": [ + "sha256:8dc45542644ed9c67e3b331e90bcffa04098e8b056a42d0fedb25769b0b1f17e", + "sha256:fccb201ad9e2ab67946111d6bf875289c141ef900fd5875de6d435d219c59440" + ], + "version": "==20.9.1" + }, + "piexif": { + "hashes": [ + "sha256:3bc435d171720150b81b15d27e05e54b8abbde7b4242cddd81ef160d283108b6", + "sha256:83cb35c606bf3a1ea1a8f0a25cb42cf17e24353fd82e87ae3884e74a302a5f1b" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==1.1.3" + }, + "pillow": { + "hashes": [ + "sha256:0295442429645fa16d05bd567ef5cff178482439c9aad0411d3f0ce9b88b3a6f", + "sha256:06aba4169e78c439d528fdeb34762c3b61a70813527a2c57f0540541e9f433a8", + "sha256:09d7f9e64289cb40c2c8d7ad674b2ed6105f55dc3b09aa8e4918e20a0311e7ad", + "sha256:0a80dd307a5d8440b0a08bd7b81617e04d870e40a3e46a32d9c246e54705e86f", + "sha256:1ca594126d3c4def54babee699c055a913efb01e106c309fa6b04405d474d5ae", + "sha256:25930fadde8019f374400f7986e8404c8b781ce519da27792cbe46eabec00c4d", + "sha256:39b8830992872e00605ec6eb0d83efad488553f10d79066b8b47c8be38e126b3", + "sha256:431b15cffbf949e89df2f7b48528be18b78bfa5177cb3036284a5508159492b5", + "sha256:52125833b070791fcb5710fabc640fc1df07d087fc0c0f02d3661f76c23c5b8b", + "sha256:5e51ee2b8114def244384eda1c82b10e307ad9778dac5c83fb0943775a653cd8", + "sha256:612cfda94e9c8346f239bf1a4b082fdd5c8143cf82d685ba2dba76e7adeeb233", + "sha256:6d7741e65835716ceea0fd13a7d0192961212fd59e741a46bbed7a473c634ed6", + "sha256:6edb5446f44d901e8683ffb25ebdfc26988ee813da3bf91e12252b57ac163727", + "sha256:725aa6cfc66ce2857d585f06e9519a1cc0ef6d13f186ff3447ab6dff0a09bc7f", + "sha256:8dad18b69f710bf3a001d2bf3afab7c432785d94fcf819c16b5207b1cfd17d38", + "sha256:94cf49723928eb6070a892cb39d6c156f7b5a2db4e8971cb958f7b6b104fb4c4", + "sha256:97f9e7953a77d5a70f49b9a48da7776dc51e9b738151b22dacf101641594a626", + "sha256:9ad7f865eebde135d526bb3163d0b23ffff365cf87e767c649550964ad72785d", + "sha256:9c87ef410a58dd54b92424ffd7e28fd2ec65d2f7fc02b76f5e9b2067e355ebf6", + "sha256:a060cf8aa332052df2158e5a119303965be92c3da6f2d93b6878f0ebca80b2f6", + "sha256:c79f9c5fb846285f943aafeafda3358992d64f0ef58566e23484132ecd8d7d63", + "sha256:c92302a33138409e8f1ad16731568c55c9053eee71bb05b6b744067e1b62380f", + "sha256:d08b23fdb388c0715990cbc06866db554e1822c4bdcf6d4166cf30ac82df8c41", + "sha256:d350f0f2c2421e65fbc62690f26b59b0bcda1b614beb318c81e38647e0f673a1", + "sha256:e6d08a4d39b8a3a503c6e97e53ee2cc1dcd4fd05c4f87e8991f53e979608d0f6", + "sha256:e901964262a56d9ea3c2693df68bc9860b8bdda2b04768821e4c44ae797de117", + "sha256:ec29604081f10f16a7aea809ad42e27764188fc258b02259a03a8ff7ded3808d", + "sha256:edf31f1150778abd4322444c393ab9c7bd2af271dd4dafb4208fb613b1f3cdc9", + "sha256:f7e30c27477dffc3e85c2463b3e649f751789e0f6c8456099eea7ddd53be4a8a", + "sha256:ffe538682dc19cc542ae7c3e504fdf54ca7f86fb8a135e59dd6bc8627eae6cce" + ], + "markers": "python_version >= '3.5'", + "version": "==7.2.0" + }, + "pluggy": { + "hashes": [ + "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", + "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.13.1" + }, + "psutil": { + "hashes": [ + "sha256:094f899ac3ef72422b7e00411b4ed174e3c5a2e04c267db6643937ddba67a05b", + "sha256:10b7f75cc8bd676cfc6fa40cd7d5c25b3f45a0e06d43becd7c2d2871cbb5e806", + "sha256:1b1575240ca9a90b437e5a40db662acd87bbf181f6aa02f0204978737b913c6b", + "sha256:21231ef1c1a89728e29b98a885b8e0a8e00d09018f6da5cdc1f43f988471a995", + "sha256:28f771129bfee9fc6b63d83a15d857663bbdcae3828e1cb926e91320a9b5b5cd", + "sha256:70387772f84fa5c3bb6a106915a2445e20ac8f9821c5914d7cbde148f4d7ff73", + "sha256:891e24ec41be15a99c00b0f3a378d3d439876fe18793f874a4f8e796fec77458", + "sha256:a9340f6b9ff887d77aed72a51d101ca0f21b8d82edc6c85105d1d9f027544365", + "sha256:b560f5cd86cf8df7bcd258a851ca1ad98f0d5b8b98748e877a0aec4e9032b465", + "sha256:b74b43fecce384a57094a83d2778cdfc2e2d9a6afaadd1ebecb2e75e0d34e10d", + "sha256:e85f727ffb21539849e6012f47b12f6dd4c44965e56591d8dec6e8bc9ab96f4a", + "sha256:fd2e09bb593ad9bdd7429e779699d2d47c1268cbde4dda95fcd1bd17544a0217", + "sha256:ffad8eb2ac614518bbe3c0b8eb9dffdb3a8d2e3a7d5da51c5b974fb723a5c5aa" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==5.6.7" + }, + "py": { + "hashes": [ + "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3", + "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.10.0" + }, + "pyparsing": { + "hashes": [ + "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", + "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.4.7" + }, + "pyserial": { + "hashes": [ + "sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb", + "sha256:c4451db6ba391ca6ca299fb3ec7bae67a5c55dde170964c7a14ceefec02f2cf0" + ], + "version": "==3.5" + }, + "pytest": { + "hashes": [ + "sha256:9d1edf9e7d0b84d72ea3dbcdfd22b35fb543a5e8f2a60092dd578936bf63d7f9", + "sha256:b574b57423e818210672e07ca1fa90aaf194a4f63f3ab909a2c67ebb22913839" + ], + "markers": "python_version >= '3.6'", + "version": "==6.2.2" + }, + "pytest-cov": { + "hashes": [ + "sha256:45ec2d5182f89a81fc3eb29e3d1ed3113b9e9a873bcddb2a71faaab066110191", + "sha256:47bd0ce14056fdd79f93e1713f88fad7bdcc583dcd7783da86ef2f085a0bb88e" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.10.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" + }, + "pyyaml": { + "hashes": [ + "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf", + "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696", + "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393", + "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77", + "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922", + "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5", + "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8", + "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10", + "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc", + "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018", + "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e", + "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253", + "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347", + "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183", + "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541", + "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb", + "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185", + "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc", + "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db", + "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa", + "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46", + "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122", + "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b", + "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63", + "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df", + "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc", + "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247", + "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6", + "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0" + ], + "version": "==5.4.1" + }, + "sangaboard": { + "hashes": [ + "sha256:3791159d57a749571f89acdce70aa9c1de82afef71f5186d5e2845c7be44698c", + "sha256:ed0c5a9864f5901d11bed0ed2387da3b5555f75fef72a9f35997304447f9b08c" + ], + "version": "==0.2.3" + }, + "scipy": { + "hashes": [ + "sha256:0c8a51d33556bf70367452d4d601d1742c0e806cd0194785914daf19775f0e67", + "sha256:0e5b0ccf63155d90da576edd2768b66fb276446c371b73841e3503be1d63fb5d", + "sha256:2481efbb3740977e3c831edfd0bd9867be26387cacf24eb5e366a6a374d3d00d", + "sha256:33d6b7df40d197bdd3049d64e8e680227151673465e5d85723b3b8f6b15a6ced", + "sha256:5da5471aed911fe7e52b86bf9ea32fb55ae93e2f0fac66c32e58897cfb02fa07", + "sha256:5f331eeed0297232d2e6eea51b54e8278ed8bb10b099f69c44e2558c090d06bf", + "sha256:5fa9c6530b1661f1370bcd332a1e62ca7881785cc0f80c0d559b636567fab63c", + "sha256:6725e3fbb47da428794f243864f2297462e9ee448297c93ed1dcbc44335feb78", + "sha256:68cb4c424112cd4be886b4d979c5497fba190714085f46b8ae67a5e4416c32b4", + "sha256:794e768cc5f779736593046c9714e0f3a5940bc6dcc1dba885ad64cbfb28e9f0", + "sha256:83bf7c16245c15bc58ee76c5418e46ea1811edcc2e2b03041b804e46084ab627", + "sha256:8e403a337749ed40af60e537cc4d4c03febddcc56cd26e774c9b1b600a70d3e4", + "sha256:a15a1f3fc0abff33e792d6049161b7795909b40b97c6cc2934ed54384017ab76", + "sha256:a423533c55fec61456dedee7b6ee7dce0bb6bfa395424ea374d25afa262be261", + "sha256:a5193a098ae9f29af283dcf0041f762601faf2e595c0db1da929875b7570353f", + "sha256:bd50daf727f7c195e26f27467c85ce653d41df4358a25b32434a50d8870fc519", + "sha256:c4fceb864890b6168e79b0e714c585dbe2fd4222768ee90bc1aa0f8218691b11", + "sha256:e3a56a9a68a3ad4a9d72ecc8570bf83106dd42237271460dd74079b449b9f6ea", + "sha256:e79570979ccdc3d165456dd62041d9556fb9733b86b4b6d818af7a0afc15f092", + "sha256:f46dd15335e8a320b0fb4685f58b7471702234cba8bb3442b69a3e1dc329c345" + ], + "markers": "python_version >= '3.7'", + "version": "==1.6.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" + }, + "toml": { + "hashes": [ + "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", + "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.10.2" + }, + "typing-extensions": { + "hashes": [ + "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918", + "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c", + "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f" + ], + "markers": "python_version < '3.8'", + "version": "==3.7.4.3" + }, + "webargs": { + "hashes": [ + "sha256:2f3d883ce9f348fa884889440fcc1b207e7c67b04be5e90be00a5be73e2cd91d", + "sha256:ce8c565789ece1584be7edba41617319eb75de59b2987958bee3f3fdb3669e60" + ], + "markers": "python_version >= '3.6'", + "version": "==7.0.1" + }, + "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" + }, + "zeroconf": { + "hashes": [ + "sha256:3608be2db58f6f0dc70665e02ab420fb8bf428016f2c78403d879e066ecc9bff", + "sha256:4be24a10aa9c73406f48d42a8b3b077c217b0e8d7ed1e57639630da520c25959" + ], + "version": "==0.28.8" + }, + "zipp": { + "hashes": [ + "sha256:3607921face881ba3e026887d8150cca609d517579abe052ac81fc5aeffdbd76", + "sha256:51cb66cc54621609dd593d1787f286ee42a5c0adbb4b29abea5a63edc3e03098" + ], + "markers": "python_version >= '3.6'", + "version": "==3.4.1" + } + }, + "develop": {} +} diff --git a/openflexure_microscope/api/app.py b/openflexure_microscope/api/app.py index 44659886..2978f34f 100644 --- a/openflexure_microscope/api/app.py +++ b/openflexure_microscope/api/app.py @@ -218,10 +218,14 @@ def cleanup(): atexit.register(cleanup) -# Start the app -if __name__ == "__main__": +def ofm_serve(): + # Start a debug server from labthings import Server logging.info("Starting OpenFlexure Microscope Server...") server: Server = Server(app) server.run(host="0.0.0.0", port=5000, debug=debug_app, zeroconf=True) + +# Start the app if the module is run directly +if __name__ == "__main__": + ofm_serve() diff --git a/pyproject.toml b/pyproject.toml index d7bccc65..02d9cc3d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,70 +1,10 @@ [build-system] -requires = ["poetry>=0.12"] -build-backend = "poetry.masonry.api" +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" -[tool.poetry] -name = "openflexure-microscope-server" -version = "2.9.3" -description = "Python module, and Flask-based web API, to run the OpenFlexure Microscope." -authors = [ - "Joel Collins ", - "Richard Bowman " -] +#exclude = ["**/node_modules/"] # I've tried to put this in the "packages" key but not sure it works. -readme = 'README.md' - -repository = "https://gitlab.com/openflexure/openflexure-microscope-server" -homepage = "https://www.openflexure.org" - -keywords = ['raspberry pi', 'arduino', 'microscope'] - -license = "GPL-3.0" - -exclude = ["**/node_modules/"] - -packages = [ - { include = "openflexure_microscope" }, -] - -[tool.poetry.dependencies] -python = "^3.7.3" -Flask = "^1.0" -numpy = "1.19.2" # Exact version so we can guarantee a wheel -Pillow = "^7.2.0" -scipy = "1.5.3" # Exact version so we can guarantee a wheel -"RPi.GPIO" = { version = "^0.7.0", optional = true } -python-dateutil = "^2.8" -psutil = "^5.6.7" # Autostorage extension -opencv-python-headless = "4.4.0.44" -sangaboard = "^0.2" -expiringdict = "^1.2.1" -camera-stage-mapping = "0.1.4" -picamerax = ">=20.9.1" -pyyaml = "^5.3.1" -pytest-cov = "^2.10.1" -piexif = "^1.1.3" -labthings = "^1.2.2" -typing-extensions = "^3.7.4" # Needed for some type-hints in Python < 3.8 (e.g. Literal) -numpy-stubs = {git = "https://github.com/numpy/numpy-stubs.git"} # Needed for Numpy < 1.20 - -[tool.poetry.extras] -rpi = ["RPi.GPIO"] - -[tool.poetry.scripts] -rescue = 'openflexure_microscope.rescue.auto:main' - -[tool.poetry.dev-dependencies] -sphinxcontrib-httpdomain = "^1.7" -rope = "^0.14.0" -pylint = "^2.3" -black = {version = "^18.3-alpha.0",allow-prereleases = true} -pytest = "^6.1.2" -mypy = "^0.790" -poethepoet = "^0.9.0" -freezegun = "^1.0.0" -lxml = "^4.6.2" [tool.black] exclude = '(\.eggs|\.git|\.venv|\venv|node_modules/)' diff --git a/setup.py b/setup.py new file mode 100644 index 00000000..9f50b1e8 --- /dev/null +++ b/setup.py @@ -0,0 +1,161 @@ +"""A setuptools based setup module. +See: +https://packaging.python.org/guides/distributing-packages-using-setuptools/ +""" + +# Always prefer setuptools over distutils +from setuptools import setup, find_packages +from os import path + +here = path.abspath(path.dirname(__file__)) + +# Get the long description from the README file +with open(path.join(here, "README.md"), encoding="utf-8") as f: + long_description = f.read() + +# Arguments marked as "Required" below must be included for upload to PyPI. +# Fields marked as "Optional" may be commented out. + +setup( + name = "openflexure-microscope-server", + version = "2.9.3", + description = "Python module, and Flask-based web API, to run the OpenFlexure Microscope.", + long_description=long_description, # Optional, read from README.md + # Denotes that our long_description is in Markdown; valid values are + long_description_content_type="text/markdown", # Optional (see note above) + # This should be a valid link to your project's main homepage. + # + # This field corresponds to the "Home-Page" metadata field: + # https://packaging.python.org/specifications/core-metadata/#home-page-optional + url="https://www.openflexure.org", # Optional + # This should be your name or the name of the organization which owns the + # project. + author="Joel Collins, Richard Bowman, Julian Stirling", # Optional + # This should be a valid email address corresponding to the author listed + # above. + author_email="contact@openflexure.org", # Optional + # Classifiers help users find your project by categorizing it. + # + # For a list of valid classifiers, see https://pypi.org/classifiers/ + classifiers=[ # Optional +# # How mature is this project? Common values are +# # 3 - Alpha +# # 4 - Beta +# # 5 - Production/Stable +# "Development Status :: 3 - Alpha", +# # Indicate who your project is intended for +# "Intended Audience :: Developers", +# "Topic :: Software Development :: Build Tools", +# # Pick your license as you wish + "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", +# # Specify the Python versions you support here. In particular, ensure +# # that you indicate whether you support Python 2, Python 3 or both. +# # These classifiers are *not* checked by 'pip install'. See instead +# # 'python_requires' below. +# "Programming Language :: Python :: 2", +# "Programming Language :: Python :: 2.7", +# "Programming Language :: Python :: 3", +# "Programming Language :: Python :: 3.5", +# "Programming Language :: Python :: 3.6", +# "Programming Language :: Python :: 3.7", + ], + # This field adds keywords for your project which will appear on the + # project page. What does your project relate to? + # + # Note that this is a string of words separated by whitespace, not a list. + keywords="raspberry pi arduino microscope", # Optional + packages=find_packages(exclude=["contrib", "docs", "tests", "*node_modules*"]), # Required + # Specify which Python versions you support + python_requires="== 3.7.*", + # This field lists other packages that your project depends on to run. + # Any package you put here will be installed by pip when your project is + # installed, so they must be valid existing projects. + # + # For an analysis of "install_requires" vs pip's requirements files see: + # https://packaging.python.org/en/latest/requirements.html + install_requires=[ + "Flask ~= 1.0", + "Pillow ~= 7.2.0", + "numpy ~= 1.20", + "scipy ~= 1.6.1", + "python-dateutil ~= 2.8", + "psutil ~= 5.6.7", # Autostorage extension + "opencv-python-headless ~= 4.5.1", + "sangaboard ~= 0.2", + "expiringdict ~= 1.2.1", + "camera-stage-mapping == 0.1.4", + "picamerax ~= 20.9.1", + "pyyaml ~= 5.4.0", + "pytest-cov ~= 2.10.1", + "piexif ~= 1.1.3", + "labthings ~= 1.2.2", + "typing-extensions ~= 3.7.4", # Needed for some type-hints in Python < 3.8 (e.g. Literal) + "RPi.GPIO ~= 0.7.0; platform_machine == 'armv7l'", + ], # Optional + # List additional groups of dependencies here (e.g. development + # dependencies). Users will be able to install these using the "extras" + # syntax, for example: + # + # $ pip install sampleproject[dev] + # + # Similar to `install_requires` above, these must be valid existing + # projects. + extras_require={ + "dev": [ + "sphinxcontrib-httpdomain ~= 1.7", + "rope ~= 0.14.0", + "pylint ~= 2.3", + "pytest ~= 6.1.2", + "mypy ~= 0.790", + "poethepoet ~= 0.9.0", + "freezegun ~= 1.0.0", + "lxml ~= 4.6", + "black == 18.3a0", + ] + }, # Optional + # If there are data files included in your packages that need to be + # installed, specify them here. + # + # Sometimes you’ll want to use packages that are properly arranged with + # setuptools, but are not published to PyPI. In those cases, you can specify + # a list of one or more dependency_links URLs where the package can + # be downloaded, along with some additional hints, and setuptools + # will find and install the package correctly. + # see https://python-packaging.readthedocs.io/en/latest/dependencies.html#packages-not-on-pypi + # + dependency_links=[], + # If using Python 2.6 or earlier, then these have to be included in + # MANIFEST.in as well. + # package_data={"sample": ["package_data.dat"]}, # Optional + # Although 'package_data' is the preferred approach, in some case you may + # need to place data files outside of your packages. See: + # http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files + # + # In this case, 'data_file' will be installed into '/my_data' + # data_files=[("my_data", ["data/data_file"])], # Optional + # To provide executable scripts, use entry points in preference to the + # "scripts" keyword. Entry points provide cross-platform support and allow + # `pip` to create the appropriate form of executable for the target + # platform. + # + # For example, the following would provide a command called `sample` which + # executes the function `main` from this package when invoked: + entry_points={ + "console_scripts": [ + "ofm-serve=openflexure_microscope.api.app:ofm_serve", + "ofm-rescue=openflexure_microscope.rescue.auto:main", + ] + }, # Optional + # List additional URLs that are relevant to your project as a dict. + # + # This field corresponds to the "Project-URL" metadata fields: + # https://packaging.python.org/specifications/core-metadata/#project-url-multiple-use + # + # Examples listed include a pattern for specifying where the package tracks + # issues, where the source is hosted, where to say thanks to the package + # maintainers, and where to support the project financially. The key is + # what's used to render the link text on PyPI. + project_urls={ # Optional + "Source": "https://gitlab.com/openflexure/openflexure-microscope-server", + }, +) From 4c705626875257dbe6eb236b1c0cc53aed904fc9 Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Fri, 26 Mar 2021 21:13:16 +0000 Subject: [PATCH 02/15] Updated readme with new install instructions --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b2e81e54..72075a01 100644 --- a/README.md +++ b/README.md @@ -52,10 +52,11 @@ The Raspberry Pi image we use currently ships with Python 3.7.3. For local devel * `pyenv init` (this may or may not be required, depending on how you installed `pyenv`) * `pyenv install 3.7.3` * `pyenv local 3.7.3` -* Ensure you have a working installation of `poetry` (see the [Poetry website](https://python-poetry.org/)). -* We usually set up `poetry` to place virtual environments in the project directory, as this is more easily detected by editors, including VSCode. To do this, you can run: - * ``poetry config virtualenvs.in-project true`` will use a folder called ``.venv`` rather than keeping your environments in a central location. -* `poetry install` will install the server, and all dependencies, into the virtual environment. This step can take a while, especially on the Pi, bring a cup of tea! +* Create a virtual environment and activate it: + * `python -m venv .venv` + * `source .venv/bin/activate` (on Linux) or `.venv/Scripts/activate` (on Windows) + * `pip install pipenv` + * `pipenv install` * Finally, run the server: * You can use `ofm serve` or `ofm restart` on the Raspberry Pi to manage the server. * To run the server locally, with dummy hardware, you can use ``poetry run python -m openflexure_microscope.api.app`` to start a development-mode Flask server on ``localhost:5000`` From faa08f3aefe71f1c3f6ece39d73e0e2ab58d9e92 Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Mon, 29 Mar 2021 11:26:38 +0100 Subject: [PATCH 03/15] Switch CI to use poetry --- .gitlab-ci.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c737ad8b..64e74db9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,12 +6,12 @@ stages: - deploy # Re-usable block to install (and cache) Poetry and openflexure-microscope-server -.poetry-install-template: &poetry-install +.python-install-template: &python-install before_script: - - curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python - - source $HOME/.poetry/env - - poetry config virtualenvs.in-project true - - poetry install -vv + - python3 -m venv .venv # NB this does not overwrite an existing cached venv + - source .venv/bin/activate + - pip install pipenv # Should be cached after first run + - pipenv install # Should be cached after first run - will just check packages are present cache: key: "${CI_COMMIT_REF_SLUG}" paths: @@ -34,7 +34,7 @@ pylint: image: python:3.7 retry: 1 - <<: *poetry-install + <<: *python-install script: - poetry run poe pylint @@ -51,7 +51,7 @@ mypy: image: python:3.7 retry: 1 - <<: *poetry-install + <<: *python-install script: - poetry run poe mypy @@ -73,7 +73,7 @@ black: retry: 1 allow_failure: true - <<: *poetry-install + <<: *python-install script: # Run static build script @@ -91,7 +91,7 @@ pytest: image: python:3.7 retry: 1 - <<: *poetry-install + <<: *python-install script: - poetry run poe test From 3ca469cca633892fed04ec4ae117289727ed9070 Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Mon, 29 Mar 2021 14:57:18 +0100 Subject: [PATCH 04/15] Install dev dependencies We now install with --dev to make sure development dependencies are included. I've also removed "poetry run" from the "poe" commands, as we are already in an active virtual environment, so it's unnecessary (and also broken). Finally, I added a tarball of the vue app to the output distribution. --- .gitlab-ci.yml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 64e74db9..f60de1f5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -11,7 +11,7 @@ stages: - python3 -m venv .venv # NB this does not overwrite an existing cached venv - source .venv/bin/activate - pip install pipenv # Should be cached after first run - - pipenv install # Should be cached after first run - will just check packages are present + - pipenv install --dev # Should be cached after first run - will just check packages are present cache: key: "${CI_COMMIT_REF_SLUG}" paths: @@ -37,7 +37,7 @@ pylint: <<: *python-install script: - - poetry run poe pylint + - poe pylint only: - branches @@ -54,7 +54,7 @@ mypy: <<: *python-install script: - - poetry run poe mypy + - poe mypy artifacts: reports: @@ -77,7 +77,7 @@ black: script: # Run static build script - - poetry run poe black_check + - poe black_check only: - branches @@ -94,7 +94,7 @@ pytest: <<: *python-install script: - - poetry run poe test + - poe test only: - branches @@ -153,8 +153,10 @@ package: # Build distribution archive - mkdir -p dist - tar -c --exclude-vcs --exclude-from .tarignore -vzf dist/openflexure-microscope-server-${CI_COMMIT_REF_NAME}.tar.gz . + - tar -c --exclude-vcs --exclude-from .tarignore -vzf dist/openflexure-microscope-webapp-${CI_COMMIT_REF_NAME}.tar.gz ./openflexure_microscope/api/static/dist/ - cd dist/ - sha256sum openflexure-microscope-server-${CI_COMMIT_REF_NAME}.tar.gz > openflexure-microscope-server-${CI_COMMIT_REF_NAME}.tar.gz.sha256 + - sha256sum openflexure-microscope-webapp-${CI_COMMIT_REF_NAME}.tar.gz > openflexure-microscope-webapp-${CI_COMMIT_REF_NAME}.tar.gz.sha256 artifacts: name: "dist" @@ -162,6 +164,8 @@ package: paths: - "./dist/openflexure-microscope-server-${CI_COMMIT_REF_NAME}.tar.gz" - "./dist/openflexure-microscope-server-${CI_COMMIT_REF_NAME}.tar.gz.sha256" + - "./dist/openflexure-microscope-webapp-${CI_COMMIT_REF_NAME}.tar.gz" + - "./dist/openflexure-microscope-webapp-${CI_COMMIT_REF_NAME}.tar.gz.sha256" only: - merge_requests From 53876ee70d5a1bbfa38eb3f4bbb3f83548038acc Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Mon, 29 Mar 2021 16:59:00 +0100 Subject: [PATCH 05/15] Use pipenv to manage setup.py dependencies --- Pipfile | 4 +- Pipfile.lock | 1103 +++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 1045 insertions(+), 62 deletions(-) diff --git a/Pipfile b/Pipfile index 346dc7bd..41154045 100644 --- a/Pipfile +++ b/Pipfile @@ -12,9 +12,7 @@ name = "piwheels" python_version = '3.7' [packages] -#openflexure-microscope-server = {path = "."} -#TODO: decide if we want dev dependencies here or in setup.py openflexure-microscope-server = {editable = true, path = "."} [dev-packages] -#openflexure-microscope-server = {path = ".", editable=true, extras=["dev"]} +openflexure-microscope-server = {editable = true, path = ".", extras = ["dev"]} diff --git a/Pipfile.lock b/Pipfile.lock index 4e099b2f..292ab0eb 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "eca50a11558f3212f61977ffa8512de91020af9a5126bad5be62e9286c7cbae5" + "sha256": "d9e26ffd8878bb646a19ad3fbbd184b817225750a442ce5e858889415f011a41" }, "pipfile-spec": 6, "requires": { @@ -61,7 +61,7 @@ "sha256:02a409bd2cb193b20d9eb015ca31400bd3e1721ec5d702e1b96de54608ff5a8f", "sha256:d39c3afebb59ec865fb1247dfd951d7090c159ab0cf3e4291e0869d3be33776c" ], - "markers": "python_version >= '3.6' and python_version < '4'", + "markers": "python_version >= '3.6' and python_version < '4.0'", "version": "==0.1.4" }, "click": { @@ -143,7 +143,7 @@ "sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d", "sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4.0'", "version": "==5.5" }, "expiringdict": { @@ -185,11 +185,11 @@ }, "importlib-metadata": { "hashes": [ - "sha256:742add720a20d0467df2f444ae41704000f50e1234f46174b51f9c6031a1bd71", - "sha256:b74159469b464a99cb8cc3e21973e4d96e05d3024d337313fedb618a6e86e6f4" + "sha256:1cedf994a9b6885dcbb7ed40b24c332b1de3956319f4b1a0f07c0621d453accc", + "sha256:c9c1b6c7dbc62084f3e6a614a194eb16ded7947736c18e3300125d5c0a7a8b3c" ], "markers": "python_version < '3.8'", - "version": "==3.7.3" + "version": "==3.9.1" }, "iniconfig": { "hashes": [ @@ -220,7 +220,7 @@ "sha256:4f286ea585e596aeb67a02d5bd822b2c89828693026085829e15e415a2d2d287", "sha256:970bb6a81f0e007b55e575e6eafe6bba10974d671f2767b91631f001ff53cf0e" ], - "markers": "python_version >= '3.6' and python_version < '4'", + "markers": "python_version >= '3.6' and python_version < '4.0'", "version": "==1.2.4" }, "markupsafe": { @@ -286,42 +286,42 @@ }, "marshmallow": { "hashes": [ - "sha256:4ab2fdb7f36eb61c3665da67a7ce281c8900db08d72ba6bf0e695828253581f7", - "sha256:eca81d53aa4aafbc0e20566973d0d2e50ce8bf0ee15165bb799bec0df1e50177" + "sha256:1d3b0699117f4e90b974824581a3743acaf2627d066a5b56611fea64c51fe309", + "sha256:58a554073364beab1cdf6b29d6cf5d99129664808e042788f51a0323fd47514d" ], "markers": "python_version >= '3.5'", - "version": "==3.10.0" + "version": "==3.11.0" }, "numpy": { "hashes": [ - "sha256:032be656d89bbf786d743fee11d01ef318b0781281241997558fa7950028dd29", - "sha256:104f5e90b143dbf298361a99ac1af4cf59131218a045ebf4ee5990b83cff5fab", - "sha256:125a0e10ddd99a874fd357bfa1b636cd58deb78ba4a30b5ddb09f645c3512e04", - "sha256:12e4ba5c6420917571f1a5becc9338abbde71dd811ce40b37ba62dec7b39af6d", - "sha256:13adf545732bb23a796914fe5f891a12bd74cf3d2986eed7b7eba2941eea1590", - "sha256:23d6802e7f2ceb9a1572f375470478251e821bdb4babbbbf3f2420c858d5dbde", - "sha256:2d7e27442599104ee08f4faed56bb87c55f8b10a5494ac2ead5c98a4b289e61f", - "sha256:3bc63486a870294683980d76ec1e3efc786295ae00128f9ea38e2c6e74d5a60a", - "sha256:3d3087e24e354c18fb35c454026af3ed8997cfd4997765266897c68d724e4845", - "sha256:4ed8e96dc146e12c1c5cdd6fb9fd0757f2ba66048bf94c5126b7efebd12d0090", - "sha256:60759ab15c94dd0e1ed88241fd4fa3312db4e91d2c8f5a2d4cf3863fad83d65b", - "sha256:65410c7f4398a0047eea5cca9b74009ea61178efd78d1be9847fac1d6716ec1e", - "sha256:66b467adfcf628f66ea4ac6430ded0614f5cc06ba530d09571ea404789064adc", - "sha256:7199109fa46277be503393be9250b983f325880766f847885607d9b13848f257", - "sha256:72251e43ac426ff98ea802a931922c79b8d7596480300eb9f1b1e45e0543571e", - "sha256:89e5336f2bec0c726ac7e7cdae181b325a9c0ee24e604704ed830d241c5e47ff", - "sha256:89f937b13b8dd17b0099c7c2e22066883c86ca1575a975f754babc8fbf8d69a9", - "sha256:9c94cab5054bad82a70b2e77741271790304651d584e2cdfe2041488e753863b", - "sha256:9eb551d122fadca7774b97db8a112b77231dcccda8e91a5bc99e79890797175e", - "sha256:a1d7995d1023335e67fb070b2fae6f5968f5be3802b15ad6d79d81ecaa014fe0", - "sha256:ae61f02b84a0211abb56462a3b6cd1e7ec39d466d3160eb4e1da8bf6717cdbeb", - "sha256:b9410c0b6fed4a22554f072a86c361e417f0258838957b78bd063bde2c7f841f", - "sha256:c26287dfc888cf1e65181f39ea75e11f42ffc4f4529e5bd19add57ad458996e2", - "sha256:c91ec9569facd4757ade0888371eced2ecf49e7982ce5634cc2cf4e7331a4b14", - "sha256:ecb5b74c702358cdc21268ff4c37f7466357871f53a30e6f84c686952bef16a9" + "sha256:2428b109306075d89d21135bdd6b785f132a1f5a3260c371cee1fae427e12727", + "sha256:377751954da04d4a6950191b20539066b4e19e3b559d4695399c5e8e3e683bf6", + "sha256:4703b9e937df83f5b6b7447ca5912b5f5f297aba45f91dbbbc63ff9278c7aa98", + "sha256:471c0571d0895c68da309dacee4e95a0811d0a9f9f532a48dc1bea5f3b7ad2b7", + "sha256:4b5a485d5aeed9b403d475dd3db750ae52f085f56f15c19a56b00ddf99597de5", + "sha256:61d5b4cf73622e4d0c6b83408a16631b670fc045afd6540679aa35591a17fe6d", + "sha256:6c915ee7dba1071554e70a3664a839fbc033e1d6528199d4621eeaaa5487ccd2", + "sha256:6e51e417d9ae2e7848314994e6fc3832c9d426abce9328cf7571eefceb43e6c9", + "sha256:719656636c48be22c23641859ff2419b27b6bdf844b36a2447cb39caceb00935", + "sha256:780ae5284cb770ade51d4b4a7dce4faa554eb1d88a56d0e8b9f35fca9b0270ff", + "sha256:878922bf5ad7550aa044aa9301d417e2d3ae50f0f577de92051d739ac6096cee", + "sha256:924dc3f83de20437de95a73516f36e09918e9c9c18d5eac520062c49191025fb", + "sha256:97ce8b8ace7d3b9288d88177e66ee75480fb79b9cf745e91ecfe65d91a856042", + "sha256:9c0fab855ae790ca74b27e55240fe4f2a36a364a3f1ebcfd1fb5ac4088f1cec3", + "sha256:9cab23439eb1ebfed1aaec9cd42b7dc50fc96d5cd3147da348d9161f0501ada5", + "sha256:a8e6859913ec8eeef3dbe9aed3bf475347642d1cdd6217c30f28dee8903528e6", + "sha256:aa046527c04688af680217fffac61eec2350ef3f3d7320c07fd33f5c6e7b4d5f", + "sha256:abc81829c4039e7e4c30f7897938fa5d4916a09c2c7eb9b244b7a35ddc9656f4", + "sha256:bad70051de2c50b1a6259a6df1daaafe8c480ca98132da98976d8591c412e737", + "sha256:c73a7975d77f15f7f68dacfb2bca3d3f479f158313642e8ea9058eea06637931", + "sha256:d15007f857d6995db15195217afdbddfcd203dfaa0ba6878a2f580eaf810ecd6", + "sha256:d76061ae5cab49b83a8cf3feacefc2053fac672728802ac137dd8c4123397677", + "sha256:e8e4fbbb7e7634f263c5b0150a629342cc19b47c5eba8d1cd4363ab3455ab576", + "sha256:e9459f40244bb02b2f14f6af0cd0732791d72232bbb0dc4bab57ef88e75f6935", + "sha256:edb1f041a9146dcf02cd7df7187db46ab524b9af2515f392f337c7cbbf5b52cd" ], "markers": "python_version >= '3.7'", - "version": "==1.20.1" + "version": "==1.20.2" }, "opencv-python-headless": { "hashes": [ @@ -535,29 +535,29 @@ }, "scipy": { "hashes": [ - "sha256:0c8a51d33556bf70367452d4d601d1742c0e806cd0194785914daf19775f0e67", - "sha256:0e5b0ccf63155d90da576edd2768b66fb276446c371b73841e3503be1d63fb5d", - "sha256:2481efbb3740977e3c831edfd0bd9867be26387cacf24eb5e366a6a374d3d00d", - "sha256:33d6b7df40d197bdd3049d64e8e680227151673465e5d85723b3b8f6b15a6ced", - "sha256:5da5471aed911fe7e52b86bf9ea32fb55ae93e2f0fac66c32e58897cfb02fa07", - "sha256:5f331eeed0297232d2e6eea51b54e8278ed8bb10b099f69c44e2558c090d06bf", - "sha256:5fa9c6530b1661f1370bcd332a1e62ca7881785cc0f80c0d559b636567fab63c", - "sha256:6725e3fbb47da428794f243864f2297462e9ee448297c93ed1dcbc44335feb78", - "sha256:68cb4c424112cd4be886b4d979c5497fba190714085f46b8ae67a5e4416c32b4", - "sha256:794e768cc5f779736593046c9714e0f3a5940bc6dcc1dba885ad64cbfb28e9f0", - "sha256:83bf7c16245c15bc58ee76c5418e46ea1811edcc2e2b03041b804e46084ab627", - "sha256:8e403a337749ed40af60e537cc4d4c03febddcc56cd26e774c9b1b600a70d3e4", - "sha256:a15a1f3fc0abff33e792d6049161b7795909b40b97c6cc2934ed54384017ab76", - "sha256:a423533c55fec61456dedee7b6ee7dce0bb6bfa395424ea374d25afa262be261", - "sha256:a5193a098ae9f29af283dcf0041f762601faf2e595c0db1da929875b7570353f", - "sha256:bd50daf727f7c195e26f27467c85ce653d41df4358a25b32434a50d8870fc519", - "sha256:c4fceb864890b6168e79b0e714c585dbe2fd4222768ee90bc1aa0f8218691b11", - "sha256:e3a56a9a68a3ad4a9d72ecc8570bf83106dd42237271460dd74079b449b9f6ea", - "sha256:e79570979ccdc3d165456dd62041d9556fb9733b86b4b6d818af7a0afc15f092", - "sha256:f46dd15335e8a320b0fb4685f58b7471702234cba8bb3442b69a3e1dc329c345" + "sha256:03f1fd3574d544456325dae502facdf5c9f81cbfe12808a5e67a737613b7ba8c", + "sha256:0c81ea1a95b4c9e0a8424cf9484b7b8fa7ef57169d7bcc0dfcfc23e3d7c81a12", + "sha256:1fba8a214c89b995e3721670e66f7053da82e7e5d0fe6b31d8e4b19922a9315e", + "sha256:37f4c2fb904c0ba54163e03993ce3544c9c5cde104bcf90614f17d85bdfbb431", + "sha256:50e5bcd9d45262725e652611bb104ac0919fd25ecb78c22f5282afabd0b2e189", + "sha256:6ca1058cb5bd45388041a7c3c11c4b2bd58867ac9db71db912501df77be2c4a4", + "sha256:77f7a057724545b7e097bfdca5c6006bed8580768cd6621bb1330aedf49afba5", + "sha256:816951e73d253a41fa2fd5f956f8e8d9ac94148a9a2039e7db56994520582bf2", + "sha256:96620240b393d155097618bcd6935d7578e85959e55e3105490bbbf2f594c7ad", + "sha256:993c86513272bc84c451349b10ee4376652ab21f312b0554fdee831d593b6c02", + "sha256:a9bc820c3df735fdd29f9a405cfc5347e1d53f0d420f8010b13502b6a33c0b57", + "sha256:adf7cee8e5c92b05f2252af498f77c7214a2296d009fc5478fc432c2f8fb953b", + "sha256:bc52d4d70863141bb7e2f8fd4d98e41d77375606cde50af65f1243ce2d7853e8", + "sha256:c1d3f771c19af00e1a36f749bd0a0690cc64632783383bc68f77587358feb5a4", + "sha256:d744657c27c128e357de2f0fd532c09c84cd6e4933e8232895a872e67059ac37", + "sha256:e3e9742bad925c421d39e699daa8d396c57535582cba90017d17f926b61c1552", + "sha256:e547f84cd52343ac2d56df0ab08d3e9cc202338e7d09fafe286d6c069ddacb31", + "sha256:e89091e6a8e211269e23f049473b2fde0c0e5ae0dd5bd276c3fc91b97da83480", + "sha256:e9da33e21c9bc1b92c20b5328adb13e5f193b924c9b969cd700c8908f315aa59", + "sha256:ffdfb09315896c6e9ac739bb6e13a19255b698c24e6b28314426fd40a1180822" ], - "markers": "python_version >= '3.7'", - "version": "==1.6.1" + "markers": "python_version < '3.10' and python_version >= '3.7'", + "version": "==1.6.2" }, "six": { "hashes": [ @@ -616,5 +616,990 @@ "version": "==3.4.1" } }, - "develop": {} + "develop": { + "alabaster": { + "hashes": [ + "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", + "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02" + ], + "version": "==0.7.12" + }, + "apispec": { + "extras": [ + "yaml" + ], + "hashes": [ + "sha256:5ec0fe72f1422a1198973fcbb48d0eb5c7390f4b0fbe55474fce999ad6826a9b", + "sha256:83e4d30edce987f4791f950c847d2b8cbe91e55af3d1ac7e3a35011a5c6fdbdd" + ], + "markers": "python_version >= '3.6'", + "version": "==4.3.0" + }, + "apispec-webframeworks": { + "hashes": [ + "sha256:0db35b267914b3f8c562aca0261957dbcb4176f255eacc22520277010818dcf3", + "sha256:482c563abbcc2a261439476cb3f1a7c7284cc997c322c574d48c111643e9c04e" + ], + "markers": "python_version >= '3.6'", + "version": "==0.5.2" + }, + "astroid": { + "hashes": [ + "sha256:6b0ed1af831570e500e2437625979eaa3b36011f66ddfc4ce930128610258ca9", + "sha256:cd80bf957c49765dce6d92c43163ff9d2abc43132ce64d4b1b47717c6d2522df" + ], + "markers": "python_version >= '3.6'", + "version": "==2.5.2" + }, + "atomicwrites": { + "hashes": [ + "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197", + "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a" + ], + "markers": "sys_platform == 'win32'", + "version": "==1.4.0" + }, + "attrs": { + "hashes": [ + "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6", + "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==20.3.0" + }, + "babel": { + "hashes": [ + "sha256:9d35c22fcc79893c3ecc85ac4a56cde1ecf3f19c540bba0922308a6c06ca6fa5", + "sha256:da031ab54472314f210b0adcff1588ee5d1d1d0ba4dbd07b94dba82bde791e05" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.9.0" + }, + "black": { + "hashes": [ + "sha256:0461c7a52b5beb378936bf642753dec7a45305c96c6129d540b9c53227121a5a", + "sha256:7183263650ba3071034e90b40a1ea74abccbd32cf525cef6d7914479dbe7f2fb" + ], + "markers": "python_version >= '3.6'", + "version": "==18.3a0" + }, + "camera-stage-mapping": { + "hashes": [ + "sha256:02a409bd2cb193b20d9eb015ca31400bd3e1721ec5d702e1b96de54608ff5a8f", + "sha256:d39c3afebb59ec865fb1247dfd951d7090c159ab0cf3e4291e0869d3be33776c" + ], + "markers": "python_version >= '3.6' and python_version < '4.0'", + "version": "==0.1.4" + }, + "certifi": { + "hashes": [ + "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c", + "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830" + ], + "version": "==2020.12.5" + }, + "chardet": { + "hashes": [ + "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa", + "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==4.0.0" + }, + "click": { + "hashes": [ + "sha256:a3747c864f8e400a3664f5f4fd6dae11b4605bf6b727dae7b6f22ba9bd0a194a", + "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" + }, + "colorama": { + "hashes": [ + "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b", + "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2" + ], + "markers": "sys_platform == 'win32'", + "version": "==0.4.4" + }, + "colorzero": { + "hashes": [ + "sha256:0e60d743a6b8071498a56465f7719c96a5e92928f858bab1be2a0d606c9aa0f8", + "sha256:e7d5a5c26cd0dc37b164ebefc609f388de24f8593b659191e12d85f8f9d5eb58" + ], + "version": "==2.0" + }, + "coverage": { + "hashes": [ + "sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c", + "sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6", + "sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45", + "sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a", + "sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03", + "sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529", + "sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a", + "sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a", + "sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2", + "sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6", + "sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759", + "sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53", + "sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a", + "sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4", + "sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff", + "sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502", + "sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793", + "sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb", + "sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905", + "sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821", + "sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b", + "sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81", + "sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0", + "sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b", + "sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3", + "sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184", + "sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701", + "sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a", + "sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82", + "sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638", + "sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5", + "sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083", + "sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6", + "sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90", + "sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465", + "sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a", + "sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3", + "sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e", + "sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066", + "sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf", + "sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b", + "sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae", + "sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669", + "sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873", + "sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b", + "sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6", + "sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb", + "sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160", + "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c", + "sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079", + "sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d", + "sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4.0'", + "version": "==5.5" + }, + "docutils": { + "hashes": [ + "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", + "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.16" + }, + "expiringdict": { + "hashes": [ + "sha256:3eb293ca7ff15ed283d8e3ae9bbc5b1cbd2d60c906b08b38c7437380e8a2f697", + "sha256:fe2ba427220425c3c8a3d29f6d2e2985bcee323f8bcd4021e68ebefbd90d8250" + ], + "version": "==1.2.1" + }, + "flask": { + "hashes": [ + "sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060", + "sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==1.1.2" + }, + "flask-cors": { + "hashes": [ + "sha256:74efc975af1194fc7891ff5cd85b0f7478be4f7f59fe158102e91abb72bb4438", + "sha256:b60839393f3b84a0f3746f6cdca56c1ad7426aa738b70d6c61375857823181de" + ], + "version": "==3.0.10" + }, + "freezegun": { + "hashes": [ + "sha256:02b35de52f4699a78f6ac4518e4cd3390dddc43b0aeb978335a8f270a2d9668b", + "sha256:1cf08e441f913ff5e59b19cc065a8faa9dd1ddc442eaf0375294f344581a0643" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.0" + }, + "future": { + "hashes": [ + "sha256:83c4f8cec14cd08179d8b4bfe8c5e48724efadac8add187f385c68d6ae2345e6", + "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.18.2" + }, + "idna": { + "hashes": [ + "sha256:4a57a6379512ade94fa99e2fa46d3cd0f2f553040548d0e2958c6ed90ee48226", + "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" + }, + "ifaddr": { + "hashes": [ + "sha256:1f9e8a6ca6f16db5a37d3356f07b6e52344f6f9f7e806d618537731669eb1a94", + "sha256:d1f603952f0a71c9ab4e705754511e4e03b02565bc4cec7188ad6415ff534cd3" + ], + "version": "==0.1.7" + }, + "imagesize": { + "hashes": [ + "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1", + "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.2.0" + }, + "importlib-metadata": { + "hashes": [ + "sha256:1cedf994a9b6885dcbb7ed40b24c332b1de3956319f4b1a0f07c0621d453accc", + "sha256:c9c1b6c7dbc62084f3e6a614a194eb16ded7947736c18e3300125d5c0a7a8b3c" + ], + "markers": "python_version < '3.8'", + "version": "==3.9.1" + }, + "iniconfig": { + "hashes": [ + "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3", + "sha256:8647b85c03813b8680f4ae9c9db2fd7293f8591ea536a10d73d90f6eb4b10aac", + "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32" + ], + "version": "==1.1.1" + }, + "isort": { + "hashes": [ + "sha256:0a943902919f65c5684ac4e0154b1ad4fac6dcaa5d9f3426b732f1c8b5419be6", + "sha256:2bb1680aad211e3c9944dbce1d4ba09a989f04e238296c87fe2139faa26d655d" + ], + "markers": "python_version >= '3.6' and python_version < '4.0'", + "version": "==5.8.0" + }, + "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:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419", + "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.11.3" + }, + "labthings": { + "hashes": [ + "sha256:4f286ea585e596aeb67a02d5bd822b2c89828693026085829e15e415a2d2d287", + "sha256:970bb6a81f0e007b55e575e6eafe6bba10974d671f2767b91631f001ff53cf0e" + ], + "markers": "python_version >= '3.6' and python_version < '4.0'", + "version": "==1.2.4" + }, + "lazy-object-proxy": { + "hashes": [ + "sha256:17e0967ba374fc24141738c69736da90e94419338fd4c7c7bef01ee26b339653", + "sha256:1fee665d2638491f4d6e55bd483e15ef21f6c8c2095f235fef72601021e64f61", + "sha256:22ddd618cefe54305df49e4c069fa65715be4ad0e78e8d252a33debf00f6ede2", + "sha256:24a5045889cc2729033b3e604d496c2b6f588c754f7a62027ad4437a7ecc4837", + "sha256:410283732af311b51b837894fa2f24f2c0039aa7f220135192b38fcc42bd43d3", + "sha256:4732c765372bd78a2d6b2150a6e99d00a78ec963375f236979c0626b97ed8e43", + "sha256:489000d368377571c6f982fba6497f2aa13c6d1facc40660963da62f5c379726", + "sha256:4f60460e9f1eb632584c9685bccea152f4ac2130e299784dbaf9fae9f49891b3", + "sha256:5743a5ab42ae40caa8421b320ebf3a998f89c85cdc8376d6b2e00bd12bd1b587", + "sha256:85fb7608121fd5621cc4377a8961d0b32ccf84a7285b4f1d21988b2eae2868e8", + "sha256:9698110e36e2df951c7c36b6729e96429c9c32b3331989ef19976592c5f3c77a", + "sha256:9d397bf41caad3f489e10774667310d73cb9c4258e9aed94b9ec734b34b495fd", + "sha256:b579f8acbf2bdd9ea200b1d5dea36abd93cabf56cf626ab9c744a432e15c815f", + "sha256:b5d6701905045a9c852a63ab2b5afe528668cf1cde0c1911472b16d75c891862", + "sha256:b865b01a2e7f96db0c5d12cfea590f98d8c5ba64ad222300d93ce6ff9138bcad", + "sha256:bf34e368e8dd976423396555078def5cfc3039ebc6fc06d1ae2c5a65eebbcde4", + "sha256:c6938967f8528b3668622a9ed3b31d145fab161a32f5891ea7b84f6b790be05b", + "sha256:d1c2676e3d840852a2de7c7d5d76407c772927addff8d742b9808fe0afccebdf", + "sha256:d7124f52f3bd259f510651450e18e0fd081ed82f3c08541dffc7b94b883aa981", + "sha256:d900d949b707778696fdf01036f58c9876a0d8bfe116e8d220cfd4b15f14e741", + "sha256:ebfd274dcd5133e0afae738e6d9da4323c3eb021b3e13052d8cbd0e457b1256e", + "sha256:ed361bb83436f117f9917d282a456f9e5009ea12fd6de8742d1a4752c3017e93", + "sha256:f5144c75445ae3ca2057faac03fda5a902eff196702b0a24daf1d6ce0650514b" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==1.6.0" + }, + "lxml": { + "hashes": [ + "sha256:079f3ae844f38982d156efce585bc540c16a926d4436712cf4baee0cce487a3d", + "sha256:0fbcf5565ac01dff87cbfc0ff323515c823081c5777a9fc7703ff58388c258c3", + "sha256:122fba10466c7bd4178b07dba427aa516286b846b2cbd6f6169141917283aae2", + "sha256:1822d16e5ac9061749955d099ff50c6cbc068f8cbfde28dfbeea845f7fbe6e09", + "sha256:1b7584d421d254ab86d4f0b13ec662a9014397678a7c4265a02a6d7c2b18a75f", + "sha256:26e761ab5b07adf5f555ee82fb4bfc35bf93750499c6c7614bd64d12aaa67927", + "sha256:289e9ca1a9287f08daaf796d96e06cb2bc2958891d7911ac7cae1c5f9e1e0ee3", + "sha256:2a9d50e69aac3ebee695424f7dbd7b8c6d6eb7de2a2eb6b0f6c7db6aa41e02b7", + "sha256:33bb934a044cf32157c12bfcfbb6649807da20aa92c062ef51903415c704704f", + "sha256:3439c71103ef0e904ea0a1901611863e51f50b5cd5e8654a151740fde5e1cade", + "sha256:39b78571b3b30645ac77b95f7c69d1bffc4cf8c3b157c435a34da72e78c82468", + "sha256:4289728b5e2000a4ad4ab8da6e1db2e093c63c08bdc0414799ee776a3f78da4b", + "sha256:4bff24dfeea62f2e56f5bab929b4428ae6caba2d1eea0c2d6eb618e30a71e6d4", + "sha256:542d454665a3e277f76954418124d67516c5f88e51a900365ed54a9806122b83", + "sha256:5a0a14e264069c03e46f926be0d8919f4105c1623d620e7ec0e612a2e9bf1c04", + "sha256:66e575c62792c3f9ca47cb8b6fab9e35bab91360c783d1606f758761810c9791", + "sha256:74f69060f98a70e3654de3021cd8162859e0f30b9e69aed76ef2b7a2e3b84212", + "sha256:74f7d8d439b18fa4c385f3f5dfd11144bb87c1da034a466c5b5577d23a1d9b51", + "sha256:7610b8c31688f0b1be0ef882889817939490a36d0ee880ea562a4e1399c447a1", + "sha256:76fa7b1362d19f8fbd3e75fe2fb7c79359b0af8747e6f7141c338f0bee2f871a", + "sha256:7728e05c35412ba36d3e9795ae8995e3c86958179c9770e65558ec3fdfd3724f", + "sha256:8157dadbb09a34a6bd95a50690595e1fa0af1a99445e2744110e3dca7831c4ee", + "sha256:820628b7b3135403540202e60551e741f9b6d3304371712521be939470b454ec", + "sha256:884ab9b29feaca361f7f88d811b1eea9bfca36cf3da27768d28ad45c3ee6f969", + "sha256:89b8b22a5ff72d89d48d0e62abb14340d9e99fd637d046c27b8b257a01ffbe28", + "sha256:92e821e43ad382332eade6812e298dc9701c75fe289f2a2d39c7960b43d1e92a", + "sha256:b007cbb845b28db4fb8b6a5cdcbf65bacb16a8bd328b53cbc0698688a68e1caa", + "sha256:bc4313cbeb0e7a416a488d72f9680fffffc645f8a838bd2193809881c67dd106", + "sha256:bccbfc27563652de7dc9bdc595cb25e90b59c5f8e23e806ed0fd623755b6565d", + "sha256:c4f05c5a7c49d2fb70223d0d5bcfbe474cf928310ac9fa6a7c6dddc831d0b1d4", + "sha256:ce256aaa50f6cc9a649c51be3cd4ff142d67295bfc4f490c9134d0f9f6d58ef0", + "sha256:d2e35d7bf1c1ac8c538f88d26b396e73dd81440d59c1ef8522e1ea77b345ede4", + "sha256:df7c53783a46febb0e70f6b05df2ba104610f2fb0d27023409734a3ecbb78fb2", + "sha256:efac139c3f0bf4f0939f9375af4b02c5ad83a622de52d6dfa8e438e8e01d0eb0", + "sha256:efd7a09678fd8b53117f6bae4fa3825e0a22b03ef0a932e070c0bdbb3a35e654", + "sha256:f2380a6376dfa090227b663f9678150ef27543483055cc327555fb592c5967e2", + "sha256:f8380c03e45cf09f8557bdaa41e1fa7c81f3ae22828e1db470ab2a6c96d8bc23", + "sha256:f90ba11136bfdd25cae3951af8da2e95121c9b9b93727b1b896e3fa105b2f586" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==4.6.3" + }, + "markupsafe": { + "hashes": [ + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:19536834abffb3fa155017053c607cb835b2ecc6a3a2554a88043d991dffb736", + "sha256:195d7d2c4fbb0ee8139a6cf67194f3973a6b3042d742ebe0a9ed36d8b6f0c07f", + "sha256:22c178a091fc6630d0d045bdb5992d2dfe14e3259760e713c490da5323866c39", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:2beec1e0de6924ea551859edb9e7679da6e4870d32cb766240ce17e0a0ba2014", + "sha256:3b8a6499709d29c2e2399569d96719a1b21dcd94410a586a18526b143ec8470f", + "sha256:3d61f15e39611aacd91b7e71d903787da86d9e80896e683c0103fced9add7834", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:6f1e273a344928347c1290119b493a1f0303c52f5a5eae5f16d74f48c15d4a85", + "sha256:6fffc775d90dcc9aed1b89219549b329a9250d918fd0b8fa8d93d154918422e1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:7952deddf24b85c88dab48f6ec366ac6e39d2761b5280f2f9594911e03fcd064", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:7fed13866cf14bba33e7176717346713881f56d9d2bcebab207f7a036f41b850", + "sha256:84dee80c15f1b560d55bcfe6d47b27d070b4681c699c572af2e3c7cc90a3b8e0", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98bae9582248d6cf62321dcb52aaf5d9adf0bad3b40582925ef7c7f0ed85fceb", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:a6a744282b7718a2a62d2ed9d993cad6f5f585605ad352c11de459f4108df0a1", + "sha256:acf08ac40292838b3cbbb06cfe9b2cb9ec78fce8baca31ddb87aaac2e2dc3bc2", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b1dba4527182c95a0db8b6060cc98ac49b9e2f5e64320e2b56e47cb2831978c7", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:b7d644ddb4dbd407d31ffb699f1d140bc35478da613b441c582aeb7c43838dd8", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:bf5aa3cbcfdf57fa2ee9cd1822c862ef23037f5c832ad09cfea57fa846dec193", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:caabedc8323f1e93231b52fc32bdcde6db817623d33e100708d9a68e1f53b26b", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:d53bc011414228441014aa71dbec320c66468c1030aae3a6e29778a3382d96e5", + "sha256:d73a845f227b0bfe8a7455ee623525ee656a9e2e749e4742706d80a6065d5e2c", + "sha256:d9be0ba6c527163cbed5e0857c451fcd092ce83947944d6c14bc95441203f032", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be", + "sha256:feb7b34d6325451ef96bc0e36e1a6c0c1c64bc1fbec4b854f4529e51887b1621" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.1.1" + }, + "marshmallow": { + "hashes": [ + "sha256:1d3b0699117f4e90b974824581a3743acaf2627d066a5b56611fea64c51fe309", + "sha256:58a554073364beab1cdf6b29d6cf5d99129664808e042788f51a0323fd47514d" + ], + "markers": "python_version >= '3.5'", + "version": "==3.11.0" + }, + "mccabe": { + "hashes": [ + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + ], + "version": "==0.6.1" + }, + "mypy": { + "hashes": [ + "sha256:0d0a87c0e7e3a9becdfbe936c981d32e5ee0ccda3e0f07e1ef2c3d1a817cf73e", + "sha256:25adde9b862f8f9aac9d2d11971f226bd4c8fbaa89fb76bdadb267ef22d10064", + "sha256:28fb5479c494b1bab244620685e2eb3c3f988d71fd5d64cc753195e8ed53df7c", + "sha256:2f9b3407c58347a452fc0736861593e105139b905cca7d097e413453a1d650b4", + "sha256:33f159443db0829d16f0a8d83d94df3109bb6dd801975fe86bacb9bf71628e97", + "sha256:3f2aca7f68580dc2508289c729bd49ee929a436208d2b2b6aab15745a70a57df", + "sha256:499c798053cdebcaa916eef8cd733e5584b5909f789de856b482cd7d069bdad8", + "sha256:4eec37370483331d13514c3f55f446fc5248d6373e7029a29ecb7b7494851e7a", + "sha256:552a815579aa1e995f39fd05dde6cd378e191b063f031f2acfe73ce9fb7f9e56", + "sha256:5873888fff1c7cf5b71efbe80e0e73153fe9212fafdf8e44adfe4c20ec9f82d7", + "sha256:61a3d5b97955422964be6b3baf05ff2ce7f26f52c85dd88db11d5e03e146a3a6", + "sha256:674e822aa665b9fd75130c6c5f5ed9564a38c6cea6a6432ce47eafb68ee578c5", + "sha256:7ce3175801d0ae5fdfa79b4f0cfed08807af4d075b402b7e294e6aa72af9aa2a", + "sha256:9743c91088d396c1a5a3c9978354b61b0382b4e3c440ce83cf77994a43e8c521", + "sha256:9f94aac67a2045ec719ffe6111df543bac7874cee01f41928f6969756e030564", + "sha256:a26f8ec704e5a7423c8824d425086705e381b4f1dfdef6e3a1edab7ba174ec49", + "sha256:abf7e0c3cf117c44d9285cc6128856106183938c68fd4944763003decdcfeb66", + "sha256:b09669bcda124e83708f34a94606e01b614fa71931d356c1f1a5297ba11f110a", + "sha256:cd07039aa5df222037005b08fbbfd69b3ab0b0bd7a07d7906de75ae52c4e3119", + "sha256:d23e0ea196702d918b60c8288561e722bf437d82cb7ef2edcd98cfa38905d506", + "sha256:d65cc1df038ef55a99e617431f0553cd77763869eebdf9042403e16089fe746c", + "sha256:d7da2e1d5f558c37d6e8c1246f1aec1e7349e4913d8fb3cb289a35de573fe2eb" + ], + "markers": "python_version >= '3.5'", + "version": "==0.812" + }, + "mypy-extensions": { + "hashes": [ + "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", + "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" + ], + "version": "==0.4.3" + }, + "numpy": { + "hashes": [ + "sha256:2428b109306075d89d21135bdd6b785f132a1f5a3260c371cee1fae427e12727", + "sha256:377751954da04d4a6950191b20539066b4e19e3b559d4695399c5e8e3e683bf6", + "sha256:4703b9e937df83f5b6b7447ca5912b5f5f297aba45f91dbbbc63ff9278c7aa98", + "sha256:471c0571d0895c68da309dacee4e95a0811d0a9f9f532a48dc1bea5f3b7ad2b7", + "sha256:4b5a485d5aeed9b403d475dd3db750ae52f085f56f15c19a56b00ddf99597de5", + "sha256:61d5b4cf73622e4d0c6b83408a16631b670fc045afd6540679aa35591a17fe6d", + "sha256:6c915ee7dba1071554e70a3664a839fbc033e1d6528199d4621eeaaa5487ccd2", + "sha256:6e51e417d9ae2e7848314994e6fc3832c9d426abce9328cf7571eefceb43e6c9", + "sha256:719656636c48be22c23641859ff2419b27b6bdf844b36a2447cb39caceb00935", + "sha256:780ae5284cb770ade51d4b4a7dce4faa554eb1d88a56d0e8b9f35fca9b0270ff", + "sha256:878922bf5ad7550aa044aa9301d417e2d3ae50f0f577de92051d739ac6096cee", + "sha256:924dc3f83de20437de95a73516f36e09918e9c9c18d5eac520062c49191025fb", + "sha256:97ce8b8ace7d3b9288d88177e66ee75480fb79b9cf745e91ecfe65d91a856042", + "sha256:9c0fab855ae790ca74b27e55240fe4f2a36a364a3f1ebcfd1fb5ac4088f1cec3", + "sha256:9cab23439eb1ebfed1aaec9cd42b7dc50fc96d5cd3147da348d9161f0501ada5", + "sha256:a8e6859913ec8eeef3dbe9aed3bf475347642d1cdd6217c30f28dee8903528e6", + "sha256:aa046527c04688af680217fffac61eec2350ef3f3d7320c07fd33f5c6e7b4d5f", + "sha256:abc81829c4039e7e4c30f7897938fa5d4916a09c2c7eb9b244b7a35ddc9656f4", + "sha256:bad70051de2c50b1a6259a6df1daaafe8c480ca98132da98976d8591c412e737", + "sha256:c73a7975d77f15f7f68dacfb2bca3d3f479f158313642e8ea9058eea06637931", + "sha256:d15007f857d6995db15195217afdbddfcd203dfaa0ba6878a2f580eaf810ecd6", + "sha256:d76061ae5cab49b83a8cf3feacefc2053fac672728802ac137dd8c4123397677", + "sha256:e8e4fbbb7e7634f263c5b0150a629342cc19b47c5eba8d1cd4363ab3455ab576", + "sha256:e9459f40244bb02b2f14f6af0cd0732791d72232bbb0dc4bab57ef88e75f6935", + "sha256:edb1f041a9146dcf02cd7df7187db46ab524b9af2515f392f337c7cbbf5b52cd" + ], + "markers": "python_version >= '3.7'", + "version": "==1.20.2" + }, + "opencv-python-headless": { + "hashes": [ + "sha256:0e02809db2968e54f3c23340be6ff9a1428b3f03f5dca7cd5aceda66e319ce86", + "sha256:1f7c14f5d4e5af4dc4669fc6b4a983b36072a934c439ac11266b930496da8255", + "sha256:243aea91cc1e36a47c46da4cc408071af39444a48df1fe1539ea8d7990500fd2", + "sha256:2560dcf3c1158226b066302f777bfe0f65282410b8d90871dd872306c967d1f1", + "sha256:2e6a9a88617a0ef7219cff24ba78a58416670a77e6ac63975f9009af3319ab63", + "sha256:372149d007e20bf556b7687591d22b58b56b3c225f492da051d81587e5dc7411", + "sha256:522f12dd994e064a30562adfd63b9439099bd7c80819f5261c37ebe593283c9e", + "sha256:526b9e19cf6300f0891d8f427eac1048091912332bb781eb4957a4994bfbe608", + "sha256:5f0c7d34fa9953706c2a1a6d2760a91dc5a68cab3df16af61609894c6c8586f1", + "sha256:657cdd9fbbbbb7e898ae3d9b0649b367d0e440d429c714104d069c5612d578bb", + "sha256:65c9ea57be5ebcaed009b3fee14fe59f3b6aa1e573fe08c5039ff057ad593c53", + "sha256:777fb596e04331f73ef5b0c1faa4d33348f29ca58216d9286355c16f5489c939", + "sha256:7c75680ffdf32d7044415a215d1fc60dbec14a7f2f0b59a85f0f74ef5efcb6ad", + "sha256:924aa4c34ead0b817309f42291dc526b2a7755476afe3009d1e275fc3090d92d", + "sha256:96d1da6ad061d8f3509668d398d14dd8265e529d6407f87eb26e7f4ddf043cc0", + "sha256:9aa04a491c534531029fbac61da961fae0bf4abb1786eed9c91befde4ca7bd81", + "sha256:a322d4df14c3a5f19701a023b3da91e9b8af8653b0d2ee0c50b0b341212f7343", + "sha256:aa562c520f46283423ba8fac29099458e42deab697a9abd0491622e421c5c454", + "sha256:ba2f0bd46e9534f29969e39f7895cbea9764173102b0c04b7818b8a9910d66e4", + "sha256:d16825755e7b5a6d8737f93e116670229e1510199e0af9213004e187ae0dbcc5", + "sha256:e3027e0d1b71b68b5cfe1ea9c627e323dff71112c854ba19805258d8fc6c630e", + "sha256:e61c8df818d79c6bd62a5a18a9b3bfdf389502798e3c22f95c67f8dcd09ce97b", + "sha256:f2011ecb3980bbed283d17d43e0f1221bac88c0cac1a6fb59a056544de2df2f7", + "sha256:f5e40a06116460ef2fd2d1c24be3b65f8bfb5fcdfe433f3fc01bcb4c2eb485bf", + "sha256:f7f8e4f7c63c8e95eb210f4cba88d0069a0a964d6335d7a35b07f0d0baa13558", + "sha256:fe02a943b1a28b505e954fbce24e867119a3eb4351f93adad55c6cfe81a70484" + ], + "markers": "python_version >= '3.6'", + "version": "==4.5.1.48" + }, + "openflexure-microscope-server": { + "editable": true, + "path": "." + }, + "packaging": { + "hashes": [ + "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5", + "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==20.9" + }, + "pastel": { + "hashes": [ + "sha256:4349225fcdf6c2bb34d483e523475de5bb04a5c10ef711263452cb37d7dd4364", + "sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.2.1" + }, + "picamerax": { + "hashes": [ + "sha256:8dc45542644ed9c67e3b331e90bcffa04098e8b056a42d0fedb25769b0b1f17e", + "sha256:fccb201ad9e2ab67946111d6bf875289c141ef900fd5875de6d435d219c59440" + ], + "version": "==20.9.1" + }, + "piexif": { + "hashes": [ + "sha256:3bc435d171720150b81b15d27e05e54b8abbde7b4242cddd81ef160d283108b6", + "sha256:83cb35c606bf3a1ea1a8f0a25cb42cf17e24353fd82e87ae3884e74a302a5f1b" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==1.1.3" + }, + "pillow": { + "hashes": [ + "sha256:0295442429645fa16d05bd567ef5cff178482439c9aad0411d3f0ce9b88b3a6f", + "sha256:06aba4169e78c439d528fdeb34762c3b61a70813527a2c57f0540541e9f433a8", + "sha256:09d7f9e64289cb40c2c8d7ad674b2ed6105f55dc3b09aa8e4918e20a0311e7ad", + "sha256:0a80dd307a5d8440b0a08bd7b81617e04d870e40a3e46a32d9c246e54705e86f", + "sha256:1ca594126d3c4def54babee699c055a913efb01e106c309fa6b04405d474d5ae", + "sha256:25930fadde8019f374400f7986e8404c8b781ce519da27792cbe46eabec00c4d", + "sha256:39b8830992872e00605ec6eb0d83efad488553f10d79066b8b47c8be38e126b3", + "sha256:431b15cffbf949e89df2f7b48528be18b78bfa5177cb3036284a5508159492b5", + "sha256:52125833b070791fcb5710fabc640fc1df07d087fc0c0f02d3661f76c23c5b8b", + "sha256:5e51ee2b8114def244384eda1c82b10e307ad9778dac5c83fb0943775a653cd8", + "sha256:612cfda94e9c8346f239bf1a4b082fdd5c8143cf82d685ba2dba76e7adeeb233", + "sha256:6d7741e65835716ceea0fd13a7d0192961212fd59e741a46bbed7a473c634ed6", + "sha256:6edb5446f44d901e8683ffb25ebdfc26988ee813da3bf91e12252b57ac163727", + "sha256:725aa6cfc66ce2857d585f06e9519a1cc0ef6d13f186ff3447ab6dff0a09bc7f", + "sha256:8dad18b69f710bf3a001d2bf3afab7c432785d94fcf819c16b5207b1cfd17d38", + "sha256:94cf49723928eb6070a892cb39d6c156f7b5a2db4e8971cb958f7b6b104fb4c4", + "sha256:97f9e7953a77d5a70f49b9a48da7776dc51e9b738151b22dacf101641594a626", + "sha256:9ad7f865eebde135d526bb3163d0b23ffff365cf87e767c649550964ad72785d", + "sha256:9c87ef410a58dd54b92424ffd7e28fd2ec65d2f7fc02b76f5e9b2067e355ebf6", + "sha256:a060cf8aa332052df2158e5a119303965be92c3da6f2d93b6878f0ebca80b2f6", + "sha256:c79f9c5fb846285f943aafeafda3358992d64f0ef58566e23484132ecd8d7d63", + "sha256:c92302a33138409e8f1ad16731568c55c9053eee71bb05b6b744067e1b62380f", + "sha256:d08b23fdb388c0715990cbc06866db554e1822c4bdcf6d4166cf30ac82df8c41", + "sha256:d350f0f2c2421e65fbc62690f26b59b0bcda1b614beb318c81e38647e0f673a1", + "sha256:e6d08a4d39b8a3a503c6e97e53ee2cc1dcd4fd05c4f87e8991f53e979608d0f6", + "sha256:e901964262a56d9ea3c2693df68bc9860b8bdda2b04768821e4c44ae797de117", + "sha256:ec29604081f10f16a7aea809ad42e27764188fc258b02259a03a8ff7ded3808d", + "sha256:edf31f1150778abd4322444c393ab9c7bd2af271dd4dafb4208fb613b1f3cdc9", + "sha256:f7e30c27477dffc3e85c2463b3e649f751789e0f6c8456099eea7ddd53be4a8a", + "sha256:ffe538682dc19cc542ae7c3e504fdf54ca7f86fb8a135e59dd6bc8627eae6cce" + ], + "markers": "python_version >= '3.5'", + "version": "==7.2.0" + }, + "pluggy": { + "hashes": [ + "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", + "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.13.1" + }, + "poethepoet": { + "hashes": [ + "sha256:6fb3021603d4421c6fcc40072bbcf150a6c52ef70ff4d3be089b8b04e015ef5a", + "sha256:70b97cb194b978dc464c70793e85e6f746cddf82b84a38bfb135946ad71ae19c" + ], + "markers": "python_version >= '3.6' and python_version < '4.0'", + "version": "==0.10.0" + }, + "psutil": { + "hashes": [ + "sha256:094f899ac3ef72422b7e00411b4ed174e3c5a2e04c267db6643937ddba67a05b", + "sha256:10b7f75cc8bd676cfc6fa40cd7d5c25b3f45a0e06d43becd7c2d2871cbb5e806", + "sha256:1b1575240ca9a90b437e5a40db662acd87bbf181f6aa02f0204978737b913c6b", + "sha256:21231ef1c1a89728e29b98a885b8e0a8e00d09018f6da5cdc1f43f988471a995", + "sha256:28f771129bfee9fc6b63d83a15d857663bbdcae3828e1cb926e91320a9b5b5cd", + "sha256:70387772f84fa5c3bb6a106915a2445e20ac8f9821c5914d7cbde148f4d7ff73", + "sha256:891e24ec41be15a99c00b0f3a378d3d439876fe18793f874a4f8e796fec77458", + "sha256:a9340f6b9ff887d77aed72a51d101ca0f21b8d82edc6c85105d1d9f027544365", + "sha256:b560f5cd86cf8df7bcd258a851ca1ad98f0d5b8b98748e877a0aec4e9032b465", + "sha256:b74b43fecce384a57094a83d2778cdfc2e2d9a6afaadd1ebecb2e75e0d34e10d", + "sha256:e85f727ffb21539849e6012f47b12f6dd4c44965e56591d8dec6e8bc9ab96f4a", + "sha256:fd2e09bb593ad9bdd7429e779699d2d47c1268cbde4dda95fcd1bd17544a0217", + "sha256:ffad8eb2ac614518bbe3c0b8eb9dffdb3a8d2e3a7d5da51c5b974fb723a5c5aa" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==5.6.7" + }, + "py": { + "hashes": [ + "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3", + "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.10.0" + }, + "pygments": { + "hashes": [ + "sha256:2656e1a6edcdabf4275f9a3640db59fd5de107d88e8663c5d4e9a0fa62f77f94", + "sha256:534ef71d539ae97d4c3a4cf7d6f110f214b0e687e92f9cb9d2a3b0d3101289c8" + ], + "markers": "python_version >= '3.5'", + "version": "==2.8.1" + }, + "pylint": { + "hashes": [ + "sha256:0e21d3b80b96740909d77206d741aa3ce0b06b41be375d92e1f3244a274c1f8a", + "sha256:d09b0b07ba06bcdff463958f53f23df25e740ecd81895f7d2699ec04bbd8dc3b" + ], + "markers": "python_version ~= '3.6'", + "version": "==2.7.2" + }, + "pyparsing": { + "hashes": [ + "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", + "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.4.7" + }, + "pyserial": { + "hashes": [ + "sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb", + "sha256:c4451db6ba391ca6ca299fb3ec7bae67a5c55dde170964c7a14ceefec02f2cf0" + ], + "version": "==3.5" + }, + "pytest": { + "hashes": [ + "sha256:9d1edf9e7d0b84d72ea3dbcdfd22b35fb543a5e8f2a60092dd578936bf63d7f9", + "sha256:b574b57423e818210672e07ca1fa90aaf194a4f63f3ab909a2c67ebb22913839" + ], + "markers": "python_version >= '3.6'", + "version": "==6.2.2" + }, + "pytest-cov": { + "hashes": [ + "sha256:45ec2d5182f89a81fc3eb29e3d1ed3113b9e9a873bcddb2a71faaab066110191", + "sha256:47bd0ce14056fdd79f93e1713f88fad7bdcc583dcd7783da86ef2f085a0bb88e" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.10.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" + }, + "pytz": { + "hashes": [ + "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da", + "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798" + ], + "version": "==2021.1" + }, + "pyyaml": { + "hashes": [ + "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf", + "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696", + "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393", + "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77", + "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922", + "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5", + "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8", + "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10", + "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc", + "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018", + "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e", + "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253", + "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347", + "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183", + "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541", + "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb", + "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185", + "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc", + "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db", + "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa", + "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46", + "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122", + "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b", + "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63", + "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df", + "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc", + "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247", + "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6", + "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0" + ], + "version": "==5.4.1" + }, + "requests": { + "hashes": [ + "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804", + "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.25.1" + }, + "rope": { + "hashes": [ + "sha256:6b728fdc3e98a83446c27a91fc5d56808a004f8beab7a31ab1d7224cecc7d969", + "sha256:c5c5a6a87f7b1a2095fb311135e2a3d1f194f5ecb96900fdd0a9100881f48aaf", + "sha256:f0dcf719b63200d492b85535ebe5ea9b29e0d0b8aebeb87fe03fc1a65924fdaf" + ], + "version": "==0.14.0" + }, + "sangaboard": { + "hashes": [ + "sha256:3791159d57a749571f89acdce70aa9c1de82afef71f5186d5e2845c7be44698c", + "sha256:ed0c5a9864f5901d11bed0ed2387da3b5555f75fef72a9f35997304447f9b08c" + ], + "version": "==0.2.3" + }, + "scipy": { + "hashes": [ + "sha256:03f1fd3574d544456325dae502facdf5c9f81cbfe12808a5e67a737613b7ba8c", + "sha256:0c81ea1a95b4c9e0a8424cf9484b7b8fa7ef57169d7bcc0dfcfc23e3d7c81a12", + "sha256:1fba8a214c89b995e3721670e66f7053da82e7e5d0fe6b31d8e4b19922a9315e", + "sha256:37f4c2fb904c0ba54163e03993ce3544c9c5cde104bcf90614f17d85bdfbb431", + "sha256:50e5bcd9d45262725e652611bb104ac0919fd25ecb78c22f5282afabd0b2e189", + "sha256:6ca1058cb5bd45388041a7c3c11c4b2bd58867ac9db71db912501df77be2c4a4", + "sha256:77f7a057724545b7e097bfdca5c6006bed8580768cd6621bb1330aedf49afba5", + "sha256:816951e73d253a41fa2fd5f956f8e8d9ac94148a9a2039e7db56994520582bf2", + "sha256:96620240b393d155097618bcd6935d7578e85959e55e3105490bbbf2f594c7ad", + "sha256:993c86513272bc84c451349b10ee4376652ab21f312b0554fdee831d593b6c02", + "sha256:a9bc820c3df735fdd29f9a405cfc5347e1d53f0d420f8010b13502b6a33c0b57", + "sha256:adf7cee8e5c92b05f2252af498f77c7214a2296d009fc5478fc432c2f8fb953b", + "sha256:bc52d4d70863141bb7e2f8fd4d98e41d77375606cde50af65f1243ce2d7853e8", + "sha256:c1d3f771c19af00e1a36f749bd0a0690cc64632783383bc68f77587358feb5a4", + "sha256:d744657c27c128e357de2f0fd532c09c84cd6e4933e8232895a872e67059ac37", + "sha256:e3e9742bad925c421d39e699daa8d396c57535582cba90017d17f926b61c1552", + "sha256:e547f84cd52343ac2d56df0ab08d3e9cc202338e7d09fafe286d6c069ddacb31", + "sha256:e89091e6a8e211269e23f049473b2fde0c0e5ae0dd5bd276c3fc91b97da83480", + "sha256:e9da33e21c9bc1b92c20b5328adb13e5f193b924c9b969cd700c8908f315aa59", + "sha256:ffdfb09315896c6e9ac739bb6e13a19255b698c24e6b28314426fd40a1180822" + ], + "markers": "python_version < '3.10' and python_version >= '3.7'", + "version": "==1.6.2" + }, + "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" + }, + "snowballstemmer": { + "hashes": [ + "sha256:b51b447bea85f9968c13b650126a888aabd4cb4463fca868ec596826325dedc2", + "sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914" + ], + "version": "==2.1.0" + }, + "sphinx": { + "hashes": [ + "sha256:3f01732296465648da43dec8fb40dc451ba79eb3e2cc5c6d79005fd98197107d", + "sha256:ce9c228456131bab09a3d7d10ae58474de562a6f79abb3dc811ae401cf8c1abc" + ], + "markers": "python_version >= '3.5'", + "version": "==3.5.3" + }, + "sphinxcontrib-applehelp": { + "hashes": [ + "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a", + "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.2" + }, + "sphinxcontrib-devhelp": { + "hashes": [ + "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e", + "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.2" + }, + "sphinxcontrib-htmlhelp": { + "hashes": [ + "sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f", + "sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.3" + }, + "sphinxcontrib-httpdomain": { + "hashes": [ + "sha256:1fb5375007d70bf180cdd1c79e741082be7aa2d37ba99efe561e1c2e3f38191e", + "sha256:ac40b4fba58c76b073b03931c7b8ead611066a6aebccafb34dc19694f4eb6335" + ], + "version": "==1.7.0" + }, + "sphinxcontrib-jsmath": { + "hashes": [ + "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", + "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.1" + }, + "sphinxcontrib-qthelp": { + "hashes": [ + "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72", + "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.3" + }, + "sphinxcontrib-serializinghtml": { + "hashes": [ + "sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc", + "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a" + ], + "markers": "python_version >= '3.5'", + "version": "==1.1.4" + }, + "toml": { + "hashes": [ + "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", + "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.10.2" + }, + "tomlkit": { + "hashes": [ + "sha256:6babbd33b17d5c9691896b0e68159215a9387ebfa938aa3ac42f4a4beeb2b831", + "sha256:ac57f29693fab3e309ea789252fcce3061e19110085aa31af5446ca749325618" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.7.0" + }, + "typed-ast": { + "hashes": [ + "sha256:07d49388d5bf7e863f7fa2f124b1b1d89d8aa0e2f7812faff0a5658c01c59aa1", + "sha256:14bf1522cdee369e8f5581238edac09150c765ec1cb33615855889cf33dcb92d", + "sha256:240296b27397e4e37874abb1df2a608a92df85cf3e2a04d0d4d61055c8305ba6", + "sha256:36d829b31ab67d6fcb30e185ec996e1f72b892255a745d3a82138c97d21ed1cd", + "sha256:37f48d46d733d57cc70fd5f30572d11ab8ed92da6e6b28e024e4a3edfb456e37", + "sha256:4822449fb865605582a22d23997444ff3eaa3d0920b04b9902e37f8edbeadca6", + "sha256:4c790331247081ea7c632a76d5b2a265e6d325ecd3179d06e9cf8d46d90dd151", + "sha256:5dcfc2e264bd8a1db8b11a892bd1647154ce03eeba94b461effe68790d8b8e07", + "sha256:7147e2a76c75f0f64c4319886e7639e490fee87c9d25cb1d4faef1d8cf83a440", + "sha256:7703620125e4fb79b64aa52427ec192822e9f45d37d4b6625ab37ef403e1df70", + "sha256:8368f83e93c7156ccd40e49a783a6a6850ca25b556c0fa0240ed0f659d2fe496", + "sha256:84aa6223d71012c68d577c83f4e7db50d11d6b1399a9c779046d75e24bed74ea", + "sha256:85f95aa97a35bdb2f2f7d10ec5bbdac0aeb9dafdaf88e17492da0504de2e6400", + "sha256:8db0e856712f79c45956da0c9a40ca4246abc3485ae0d7ecc86a20f5e4c09abc", + "sha256:9044ef2df88d7f33692ae3f18d3be63dec69c4fb1b5a4a9ac950f9b4ba571606", + "sha256:963c80b583b0661918718b095e02303d8078950b26cc00b5e5ea9ababe0de1fc", + "sha256:987f15737aba2ab5f3928c617ccf1ce412e2e321c77ab16ca5a293e7bbffd581", + "sha256:9ec45db0c766f196ae629e509f059ff05fc3148f9ffd28f3cfe75d4afb485412", + "sha256:9fc0b3cb5d1720e7141d103cf4819aea239f7d136acf9ee4a69b047b7986175a", + "sha256:a2c927c49f2029291fbabd673d51a2180038f8cd5a5b2f290f78c4516be48be2", + "sha256:a38878a223bdd37c9709d07cd357bb79f4c760b29210e14ad0fb395294583787", + "sha256:a93908d202f52ec64e24a41031f1336a14b66706be2c9e51949647f7ac4cbd22", + "sha256:b4fcdcfa302538f70929eb7b392f536a237cbe2ed9cba88e3bf5027b39f5f77f", + "sha256:c0c74e5579af4b977c8b932f40a5464764b2f86681327410aa028a22d2f54937", + "sha256:c1c876fd795b36126f773db9cbb393f19808edd2637e00fd6caba0e25f2c7b64", + "sha256:c9aadc4924d4b5799112837b226160428524a9a45f830e0d0f184b19e4090487", + "sha256:cc7b98bf58167b7f2db91a4327da24fb93368838eb84a44c472283778fc2446b", + "sha256:cf54cfa843f297991b7388c281cb3855d911137223c6b6d2dd82a47ae5125a41", + "sha256:d003156bb6a59cda9050e983441b7fa2487f7800d76bdc065566b7d728b4581a", + "sha256:d175297e9533d8d37437abc14e8a83cbc68af93cc9c1c59c2c292ec59a0697a3", + "sha256:d746a437cdbca200622385305aedd9aef68e8a645e385cc483bdc5e488f07166", + "sha256:e683e409e5c45d5c9082dc1daf13f6374300806240719f95dc783d1fc942af10" + ], + "markers": "python_version < '3.8' and implementation_name == 'cpython'", + "version": "==1.4.2" + }, + "typing-extensions": { + "hashes": [ + "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918", + "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c", + "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f" + ], + "markers": "python_version < '3.8'", + "version": "==3.7.4.3" + }, + "urllib3": { + "hashes": [ + "sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df", + "sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4.0'", + "version": "==1.26.4" + }, + "webargs": { + "hashes": [ + "sha256:2f3d883ce9f348fa884889440fcc1b207e7c67b04be5e90be00a5be73e2cd91d", + "sha256:ce8c565789ece1584be7edba41617319eb75de59b2987958bee3f3fdb3669e60" + ], + "markers": "python_version >= '3.6'", + "version": "==7.0.1" + }, + "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" + }, + "wrapt": { + "hashes": [ + "sha256:1ba3a6bcb5014ed4d9c98afe8aa47b5ed320f84292b4f1b9f6afa0f4b2b91351", + "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7", + "sha256:c16fd7cad3d27a5db392ae0e6215533a912a7d3d83a40b8cf275744276989780", + "sha256:d3294c918c5529e50b5454d39b589648d9baf6152e380067606d5566d71369a0" + ], + "version": "==1.12.1" + }, + "zeroconf": { + "hashes": [ + "sha256:3608be2db58f6f0dc70665e02ab420fb8bf428016f2c78403d879e066ecc9bff", + "sha256:4be24a10aa9c73406f48d42a8b3b077c217b0e8d7ed1e57639630da520c25959" + ], + "version": "==0.28.8" + }, + "zipp": { + "hashes": [ + "sha256:3607921face881ba3e026887d8150cca609d517579abe052ac81fc5aeffdbd76", + "sha256:51cb66cc54621609dd593d1787f286ee42a5c0adbb4b29abea5a63edc3e03098" + ], + "markers": "python_version >= '3.6'", + "version": "==3.4.1" + } + } } From 17b19d7dfde8212aafe3c86d1d18d48f78edb8ea Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Mon, 29 Mar 2021 16:59:40 +0100 Subject: [PATCH 06/15] fix poe poe was assuming we were using poetry - I have configured it not to use poetry now. This required using a newer version. --- pyproject.toml | 4 ++++ setup.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 02d9cc3d..96eaf8ff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,10 @@ line_length = 88 disable = "fixme,C,R" max-line-length = 88 +[tool.poe.executor] +type = "virtualenv" +location = ".venv" + [tool.poe.tasks] black = "black ." black_check = "black --check ." diff --git a/setup.py b/setup.py index 9f50b1e8..e012b40d 100644 --- a/setup.py +++ b/setup.py @@ -107,7 +107,7 @@ setup( "pylint ~= 2.3", "pytest ~= 6.1.2", "mypy ~= 0.790", - "poethepoet ~= 0.9.0", + "poethepoet ~= 0.10.0", "freezegun ~= 1.0.0", "lxml ~= 4.6", "black == 18.3a0", From cd5e32b8436e7f0cea9a04f2a3e93b1a09e00bb9 Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Tue, 30 Mar 2021 17:40:19 +0100 Subject: [PATCH 07/15] Removed deprecated np.float numpy 1.20 deprecates np.float, which was only ever an alias for ``float``. I've replaced all occurrences of np.float with float, as recommended. There should be no change in functionality. --- .../api/default_extensions/autofocus.py | 18 +++++++++--------- .../recalibrate_utils.py | 4 ++-- openflexure_microscope/json.py | 4 ++-- openflexure_microscope/stage/sanga.py | 6 +++--- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/openflexure_microscope/api/default_extensions/autofocus.py b/openflexure_microscope/api/default_extensions/autofocus.py index 339291ca..ed6fd813 100644 --- a/openflexure_microscope/api/default_extensions/autofocus.py +++ b/openflexure_microscope/api/default_extensions/autofocus.py @@ -127,16 +127,16 @@ def monitor_sharpness(microscope: Microscope): m.stop() -def sharpness_sum_lap2(rgb_image: np.ndarray) -> np.float: +def sharpness_sum_lap2(rgb_image: np.ndarray) -> float: """Return an image sharpness metric: sum(laplacian(image)**")""" - image_bw: np.float = np.mean(rgb_image, 2) - image_lap: np.float = ndimage.filters.laplace(image_bw) - return np.mean(image_lap.astype(np.float) ** 4) + image_bw: float = np.mean(rgb_image, 2) + image_lap: float = ndimage.filters.laplace(image_bw) + return np.mean(image_lap.astype(float) ** 4) -def sharpness_edge(image: np.ndarray) -> np.float: +def sharpness_edge(image: np.ndarray) -> float: """Return a sharpness metric optimised for vertical lines""" - gray: np.float = np.mean(image.astype(float), 2) + gray: float = np.mean(image.astype(float), 2) n: int = 20 edge: np.ndarray = np.array([[-1] * n + [1] * n]) return np.sum( @@ -169,7 +169,7 @@ class AutofocusExtension(BaseExtension): def measure_sharpness( self, microscope: Microscope, metric_fn: Callable = sharpness_sum_lap2 - ) -> np.float: + ) -> float: """Measure the sharpness of the camera's current view.""" if hasattr(microscope.camera, "array") and callable( @@ -185,7 +185,7 @@ class AutofocusExtension(BaseExtension): dz: List[int], settle: float = 0.5, metric_fn: Callable = sharpness_sum_lap2, - ) -> Tuple[List[int], List[np.float]]: + ) -> Tuple[List[int], List[float]]: """Perform a simple autofocus routine. The stage is moved to z positions (relative to current position) in dz, and at each position an image is captured and the sharpness function @@ -197,7 +197,7 @@ class AutofocusExtension(BaseExtension): stage: BaseStage = microscope.stage with set_properties(stage, backlash=256), stage.lock, camera.lock: - sharpnesses: List[np.float] = [] + sharpnesses: List[float] = [] positions: List[int] = [] # Some cameras may not have annotate_text. Reset if it does diff --git a/openflexure_microscope/api/default_extensions/picamera_autocalibrate/recalibrate_utils.py b/openflexure_microscope/api/default_extensions/picamera_autocalibrate/recalibrate_utils.py index 0392720e..445687a9 100644 --- a/openflexure_microscope/api/default_extensions/picamera_autocalibrate/recalibrate_utils.py +++ b/openflexure_microscope/api/default_extensions/picamera_autocalibrate/recalibrate_utils.py @@ -106,7 +106,7 @@ def lst_from_channels(channels: np.ndarray) -> np.ndarray: logging.info("Generating a lens shading table at %sx%s", *lst_resolution) lens_shading: np.ndarray = np.zeros( - [channels.shape[0]] + lst_resolution, dtype=np.float + [channels.shape[0]] + lst_resolution, dtype=float ) for i in range(lens_shading.shape[0]): image_channel: np.ndarray = channels[i, :, :] @@ -193,7 +193,7 @@ def recalibrate_camera(camera: PiCamera): _ = rgb_image(camera) # Fix the AWB gains so the image is neutral - channel_means = np.mean(np.mean(rgb_image(camera), axis=0, dtype=np.float), axis=0) + channel_means = np.mean(np.mean(rgb_image(camera), axis=0, dtype=float), axis=0) old_gains = camera.awb_gains camera.awb_gains = ( channel_means[1] / channel_means[0] * old_gains[0], diff --git a/openflexure_microscope/json.py b/openflexure_microscope/json.py index 025b6cb8..56aba734 100644 --- a/openflexure_microscope/json.py +++ b/openflexure_microscope/json.py @@ -21,8 +21,8 @@ class JSONEncoder(LabThingsJSONEncoder): # Numpy integers elif isinstance(o, np.integer): return int(o) - # Numpy floats - elif isinstance(o, np.float): + # Numpy floats are just Python floats + elif isinstance(o, float): return float(o) # Numpy arrays elif isinstance(o, np.ndarray): diff --git a/openflexure_microscope/stage/sanga.py b/openflexure_microscope/stage/sanga.py index 6ad68a28..6aaf8328 100644 --- a/openflexure_microscope/stage/sanga.py +++ b/openflexure_microscope/stage/sanga.py @@ -277,11 +277,11 @@ class SangaDeltaStage(SangaStage): logging.debug(self.R_camera) # Transformation matrix converting delta into cartesian - x_fac: np.float = -1 * np.multiply( + x_fac: float = -1 * np.multiply( np.divide(2, np.sqrt(3)), np.divide(self.flex_b, self.flex_h) ) - y_fac: np.float = -1 * np.divide(self.flex_b, self.flex_h) - z_fac: np.float = np.multiply( + y_fac: float = -1 * np.divide(self.flex_b, self.flex_h) + z_fac: float = np.multiply( np.divide(1, 3), np.divide(self.flex_b, self.flex_a) ) From e73ee8875c1d0bca33a57f6d82420074719a7903 Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Tue, 30 Mar 2021 17:51:00 +0100 Subject: [PATCH 08/15] Fixed type annotations in autofocus and mock stage I don't know why these didn't fail before - possibly because of incomplete type information from old numpy... I removed a few annotations because they were failing (e.g. np.sum can return a scalar or an array), but I don't think this should be a problem - the function inputs and return values are still typed. --- .../api/default_extensions/autofocus.py | 15 +++++++++------ openflexure_microscope/stage/mock.py | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/openflexure_microscope/api/default_extensions/autofocus.py b/openflexure_microscope/api/default_extensions/autofocus.py index ed6fd813..ba6f00ca 100644 --- a/openflexure_microscope/api/default_extensions/autofocus.py +++ b/openflexure_microscope/api/default_extensions/autofocus.py @@ -129,18 +129,21 @@ def monitor_sharpness(microscope: Microscope): def sharpness_sum_lap2(rgb_image: np.ndarray) -> float: """Return an image sharpness metric: sum(laplacian(image)**")""" - image_bw: float = np.mean(rgb_image, 2) - image_lap: float = ndimage.filters.laplace(image_bw) - return np.mean(image_lap.astype(float) ** 4) + image_bw = np.mean(rgb_image, 2) + image_lap = ndimage.filters.laplace(image_bw) + return float(np.mean(image_lap.astype(float) ** 4)) def sharpness_edge(image: np.ndarray) -> float: """Return a sharpness metric optimised for vertical lines""" - gray: float = np.mean(image.astype(float), 2) + gray = np.mean(image.astype(float), 2) n: int = 20 edge: np.ndarray = np.array([[-1] * n + [1] * n]) - return np.sum( - [np.sum(ndimage.filters.convolve(gray, W) ** 2) for W in [edge, edge.T]] + return float( + np.sum( + [np.sum(ndimage.filters.convolve(gray, W) ** 2) + for W in [edge, edge.T]] + ) ) diff --git a/openflexure_microscope/stage/mock.py b/openflexure_microscope/stage/mock.py index 8b67b196..4268224c 100644 --- a/openflexure_microscope/stage/mock.py +++ b/openflexure_microscope/stage/mock.py @@ -89,7 +89,7 @@ class MissingStage(BaseStage): ) displacement = move - initial_move = np.array(displacement, dtype=np.int) + initial_move = np.array(displacement, dtype=np.integer) self._position = list(np.array(self._position) + np.array(initial_move)) logging.debug(np.array(self._position) + np.array(initial_move)) From 300d6878bb34839045dbe6d138ca08d3bdcb32c0 Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Wed, 31 Mar 2021 09:35:13 +0100 Subject: [PATCH 09/15] Upgraded black to match master --- Pipfile.lock | 43 +++++++++++++++++++++++++------------------ setup.py | 2 +- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index 292ab0eb..b00fd3de 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -185,11 +185,11 @@ }, "importlib-metadata": { "hashes": [ - "sha256:1cedf994a9b6885dcbb7ed40b24c332b1de3956319f4b1a0f07c0621d453accc", - "sha256:c9c1b6c7dbc62084f3e6a614a194eb16ded7947736c18e3300125d5c0a7a8b3c" + "sha256:c9db46394197244adf2f0b08ec5bc3cf16757e9590b02af1fca085c16c0d600a", + "sha256:d2d46ef77ffc85cbf7dac7e81dd663fde71c45326131bea8033b9bad42268ebe" ], "markers": "python_version < '3.8'", - "version": "==3.9.1" + "version": "==3.10.0" }, "iniconfig": { "hashes": [ @@ -286,11 +286,11 @@ }, "marshmallow": { "hashes": [ - "sha256:1d3b0699117f4e90b974824581a3743acaf2627d066a5b56611fea64c51fe309", - "sha256:58a554073364beab1cdf6b29d6cf5d99129664808e042788f51a0323fd47514d" + "sha256:0dd42891a5ef288217ed6410917f3c6048f585f8692075a0052c24f9bfff9dfd", + "sha256:16e99cb7f630c0ef4d7d364ed0109ac194268dde123966076ab3dafb9ae3906b" ], "markers": "python_version >= '3.5'", - "version": "==3.11.0" + "version": "==3.11.1" }, "numpy": { "hashes": [ @@ -643,6 +643,13 @@ "markers": "python_version >= '3.6'", "version": "==0.5.2" }, + "appdirs": { + "hashes": [ + "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41", + "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128" + ], + "version": "==1.4.4" + }, "astroid": { "hashes": [ "sha256:6b0ed1af831570e500e2437625979eaa3b36011f66ddfc4ce930128610258ca9", @@ -677,11 +684,11 @@ }, "black": { "hashes": [ - "sha256:0461c7a52b5beb378936bf642753dec7a45305c96c6129d540b9c53227121a5a", - "sha256:7183263650ba3071034e90b40a1ea74abccbd32cf525cef6d7914479dbe7f2fb" + "sha256:817243426042db1d36617910df579a54f1afd659adb96fc5032fcf4b36209739", + "sha256:e030a9a28f542debc08acceb273f228ac422798e5215ba2a791a6ddeaaca22a5" ], "markers": "python_version >= '3.6'", - "version": "==18.3a0" + "version": "==18.9b0" }, "camera-stage-mapping": { "hashes": [ @@ -860,11 +867,11 @@ }, "importlib-metadata": { "hashes": [ - "sha256:1cedf994a9b6885dcbb7ed40b24c332b1de3956319f4b1a0f07c0621d453accc", - "sha256:c9c1b6c7dbc62084f3e6a614a194eb16ded7947736c18e3300125d5c0a7a8b3c" + "sha256:c9db46394197244adf2f0b08ec5bc3cf16757e9590b02af1fca085c16c0d600a", + "sha256:d2d46ef77ffc85cbf7dac7e81dd663fde71c45326131bea8033b9bad42268ebe" ], "markers": "python_version < '3.8'", - "version": "==3.9.1" + "version": "==3.10.0" }, "iniconfig": { "hashes": [ @@ -1042,11 +1049,11 @@ }, "marshmallow": { "hashes": [ - "sha256:1d3b0699117f4e90b974824581a3743acaf2627d066a5b56611fea64c51fe309", - "sha256:58a554073364beab1cdf6b29d6cf5d99129664808e042788f51a0323fd47514d" + "sha256:0dd42891a5ef288217ed6410917f3c6048f585f8692075a0052c24f9bfff9dfd", + "sha256:16e99cb7f630c0ef4d7d364ed0109ac194268dde123966076ab3dafb9ae3906b" ], "markers": "python_version >= '3.5'", - "version": "==3.11.0" + "version": "==3.11.1" }, "mccabe": { "hashes": [ @@ -1277,11 +1284,11 @@ }, "pylint": { "hashes": [ - "sha256:0e21d3b80b96740909d77206d741aa3ce0b06b41be375d92e1f3244a274c1f8a", - "sha256:d09b0b07ba06bcdff463958f53f23df25e740ecd81895f7d2699ec04bbd8dc3b" + "sha256:209d712ec870a0182df034ae19f347e725c1e615b2269519ab58a35b3fcbbe7a", + "sha256:bd38914c7731cdc518634a8d3c5585951302b6e2b6de60fbb3f7a0220e21eeee" ], "markers": "python_version ~= '3.6'", - "version": "==2.7.2" + "version": "==2.7.4" }, "pyparsing": { "hashes": [ diff --git a/setup.py b/setup.py index e012b40d..bdafa22a 100644 --- a/setup.py +++ b/setup.py @@ -110,7 +110,7 @@ setup( "poethepoet ~= 0.10.0", "freezegun ~= 1.0.0", "lxml ~= 4.6", - "black == 18.3a0", + "black == 18.9b0", ] }, # Optional # If there are data files included in your packages that need to be From 1cea75be7087037029ff391074ac71a1053b6e29 Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Wed, 31 Mar 2021 09:40:31 +0100 Subject: [PATCH 10/15] Formatting fixes --- openflexure_microscope/api/app.py | 2 + .../api/default_extensions/autofocus.py | 5 +- openflexure_microscope/stage/sanga.py | 4 +- setup.py | 52 ++++++++++--------- 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/openflexure_microscope/api/app.py b/openflexure_microscope/api/app.py index 2978f34f..2a310f0c 100644 --- a/openflexure_microscope/api/app.py +++ b/openflexure_microscope/api/app.py @@ -218,6 +218,7 @@ def cleanup(): atexit.register(cleanup) + def ofm_serve(): # Start a debug server from labthings import Server @@ -226,6 +227,7 @@ def ofm_serve(): server: Server = Server(app) server.run(host="0.0.0.0", port=5000, debug=debug_app, zeroconf=True) + # Start the app if the module is run directly if __name__ == "__main__": ofm_serve() diff --git a/openflexure_microscope/api/default_extensions/autofocus.py b/openflexure_microscope/api/default_extensions/autofocus.py index ba6f00ca..15044f70 100644 --- a/openflexure_microscope/api/default_extensions/autofocus.py +++ b/openflexure_microscope/api/default_extensions/autofocus.py @@ -140,10 +140,7 @@ def sharpness_edge(image: np.ndarray) -> float: n: int = 20 edge: np.ndarray = np.array([[-1] * n + [1] * n]) return float( - np.sum( - [np.sum(ndimage.filters.convolve(gray, W) ** 2) - for W in [edge, edge.T]] - ) + np.sum([np.sum(ndimage.filters.convolve(gray, W) ** 2) for W in [edge, edge.T]]) ) diff --git a/openflexure_microscope/stage/sanga.py b/openflexure_microscope/stage/sanga.py index 6aaf8328..28d13dda 100644 --- a/openflexure_microscope/stage/sanga.py +++ b/openflexure_microscope/stage/sanga.py @@ -281,9 +281,7 @@ class SangaDeltaStage(SangaStage): np.divide(2, np.sqrt(3)), np.divide(self.flex_b, self.flex_h) ) y_fac: float = -1 * np.divide(self.flex_b, self.flex_h) - z_fac: float = np.multiply( - np.divide(1, 3), np.divide(self.flex_b, self.flex_a) - ) + z_fac: float = np.multiply(np.divide(1, 3), np.divide(self.flex_b, self.flex_a)) self.Tvd: np.ndarray = np.array( [ diff --git a/setup.py b/setup.py index bdafa22a..bc1f9fbb 100644 --- a/setup.py +++ b/setup.py @@ -17,9 +17,9 @@ with open(path.join(here, "README.md"), encoding="utf-8") as f: # Fields marked as "Optional" may be commented out. setup( - name = "openflexure-microscope-server", - version = "2.9.3", - description = "Python module, and Flask-based web API, to run the OpenFlexure Microscope.", + name="openflexure-microscope-server", + version="2.9.3", + description="Python module, and Flask-based web API, to run the OpenFlexure Microscope.", long_description=long_description, # Optional, read from README.md # Denotes that our long_description is in Markdown; valid values are long_description_content_type="text/markdown", # Optional (see note above) @@ -38,33 +38,35 @@ setup( # # For a list of valid classifiers, see https://pypi.org/classifiers/ classifiers=[ # Optional -# # How mature is this project? Common values are -# # 3 - Alpha -# # 4 - Beta -# # 5 - Production/Stable -# "Development Status :: 3 - Alpha", -# # Indicate who your project is intended for -# "Intended Audience :: Developers", -# "Topic :: Software Development :: Build Tools", -# # Pick your license as you wish + # # How mature is this project? Common values are + # # 3 - Alpha + # # 4 - Beta + # # 5 - Production/Stable + # "Development Status :: 3 - Alpha", + # # Indicate who your project is intended for + # "Intended Audience :: Developers", + # "Topic :: Software Development :: Build Tools", + # # Pick your license as you wish "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", -# # Specify the Python versions you support here. In particular, ensure -# # that you indicate whether you support Python 2, Python 3 or both. -# # These classifiers are *not* checked by 'pip install'. See instead -# # 'python_requires' below. -# "Programming Language :: Python :: 2", -# "Programming Language :: Python :: 2.7", -# "Programming Language :: Python :: 3", -# "Programming Language :: Python :: 3.5", -# "Programming Language :: Python :: 3.6", -# "Programming Language :: Python :: 3.7", + # # Specify the Python versions you support here. In particular, ensure + # # that you indicate whether you support Python 2, Python 3 or both. + # # These classifiers are *not* checked by 'pip install'. See instead + # # 'python_requires' below. + # "Programming Language :: Python :: 2", + # "Programming Language :: Python :: 2.7", + # "Programming Language :: Python :: 3", + # "Programming Language :: Python :: 3.5", + # "Programming Language :: Python :: 3.6", + # "Programming Language :: Python :: 3.7", ], # This field adds keywords for your project which will appear on the # project page. What does your project relate to? # # Note that this is a string of words separated by whitespace, not a list. keywords="raspberry pi arduino microscope", # Optional - packages=find_packages(exclude=["contrib", "docs", "tests", "*node_modules*"]), # Required + packages=find_packages( + exclude=["contrib", "docs", "tests", "*node_modules*"] + ), # Required # Specify which Python versions you support python_requires="== 3.7.*", # This field lists other packages that your project depends on to run. @@ -79,7 +81,7 @@ setup( "numpy ~= 1.20", "scipy ~= 1.6.1", "python-dateutil ~= 2.8", - "psutil ~= 5.6.7", # Autostorage extension + "psutil ~= 5.6.7", # Autostorage extension "opencv-python-headless ~= 4.5.1", "sangaboard ~= 0.2", "expiringdict ~= 1.2.1", @@ -156,6 +158,6 @@ setup( # maintainers, and where to support the project financially. The key is # what's used to render the link text on PyPI. project_urls={ # Optional - "Source": "https://gitlab.com/openflexure/openflexure-microscope-server", + "Source": "https://gitlab.com/openflexure/openflexure-microscope-server" }, ) From 9783dfaeff6383476cd9b78845b86c15dee3aee0 Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Wed, 31 Mar 2021 10:21:45 +0100 Subject: [PATCH 11/15] Updated readme and version-bump for clarity --- README.md | 27 ++++++++++++++------------- setup.py | 2 +- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 72075a01..8f1042a8 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,9 @@ There are 2 important settings files: ## Creating releases * Update the applications internal version number - * `poetry version X.y.z` (replace X.y.z with a semantic version number) - * or `poetry version {patch/minor/major}` (see https://python-poetry.org/docs/cli/#version) + * Edit ``setup.py`` to update the version number * Git commit and git push -* Create a new version tag on GitLab (e.g. V2.6.11) +* Create a new version tag on GitLab (e.g. ``v2.6.11``) * Make sure you prefix a lower case 'v', otherwise it won't be recognised as a release! * This tagging will trigger a CI pipeline that builds the JS client, tarballs up the server, and deploys it * Note: This also updates the build server's nginx redirect map file @@ -56,10 +55,10 @@ The Raspberry Pi image we use currently ships with Python 3.7.3. For local devel * `python -m venv .venv` * `source .venv/bin/activate` (on Linux) or `.venv/Scripts/activate` (on Windows) * `pip install pipenv` - * `pipenv install` + * `pipenv install --dev` (This will install development dependencies. If you don't need these, `pipenv install` will get you just the dependencies needed to run the server, which takes about half the time.) * Finally, run the server: * You can use `ofm serve` or `ofm restart` on the Raspberry Pi to manage the server. - * To run the server locally, with dummy hardware, you can use ``poetry run python -m openflexure_microscope.api.app`` to start a development-mode Flask server on ``localhost:5000`` + * To run the server locally, with dummy hardware, you can use ``python -m openflexure_microscope.api.app`` to start a development-mode Flask server on ``localhost:5000`` ### Set up the Javascript environment and build * The Flask web application, written in Python, serves a web application written in ``Vue.js``. This is distributed as part of the built version of the server, hosted on our [build server](https://build.openflexure.org/openflexure-microscope-server/). @@ -77,12 +76,13 @@ The Raspberry Pi image we use currently ships with Python 3.7.3. For local devel * You access the development server on a different port (it's printed on the command line when you run the above command). This means that when it starts up you will need to tell it where the microscope server is, using the "override API origin" field in the page that pops up. If you are running a test server on your computer, this is most likely ``http://localhost:5000/``. ## Formatting, linting, and tests +All of the commands below assume that you are running in the OFM virtual environment, i.e. you have run ``ofm activate`` on an OpenFlexure SD card, or ``source .venv/bin/activate`` on Linux, or ``.venv/Scripts/activate``on Windows. ### Tl;dr **Before committing** -* To auto-format the Python code run `poetry run poe format` +* To auto-format the Python code run `poe format` * To auto-format the Javascript code, run * ``cd openflexure_microscope/api/static`` * ``npm run lint`` @@ -91,7 +91,7 @@ Auto-formats the code **Before submitting a merge request/merging** -* To auto-format and type-check the Python code run `poetry run poe check` +* To auto-format and type-check the Python code run `poe check` * To auto-format the Javascript code, run * ``cd openflexure_microscope/api/static`` * ``npm run lint`` @@ -107,28 +107,29 @@ Our CI will check each of these automatically, so ensuring they pass locally wil * **Black** - Code formatting with minimal configuration. * While sometimes it's not perfect, its fine 90% of the time and prevents arguments about formatting. * Automatically formats your code - * `poetry run poe black` + * This will rewrite your files in-place, so if you want to be able to revert, make a backup first! + * `poe black` * **Pylint** - Static code analysis * Analyses your code, failing if issues are detected. * We've disabled some less severe warnings, so _if anything fails your merge request will be blocked_ - * `poetry run poe pylint` + * `poe pylint` * **Mypy** - Type checking * Analyses your type hints and annotations to flag up potential bugs * Where possible, use type hints in your code. Even if dependencies don't support it, it'll help identify issues. - * `poetry run poe mypy` + * `poe mypy` * **Pytest** - Unit testing * While unit testing is of limited use due to our dependence on real hardware, some simple isolated functions can (and should) be unit tested. - * `poetry run poe test` + * `poe test` Though not in the CI, our `format` script also runs isort: * **Isort** - Import sorting * Automatically organises your imports to stop things getting out of hand - * `poetry run poe isort` + * `poe isort` ## Build-system -As of 1.0.0b0, we're using [Poetry](https://github.com/sdispater/poetry) to manage dependencies, build, and distribute the package. All package information and dependencies are found in `pyproject.toml`, in line with [PEP 518](https://www.python.org/dev/peps/pep-0518/). If you're developing this package, make use of `poetry.lock` to ensure you're using the latest locked dependency list. +As of ``2.10.0b0`` we have switched to using ``pipenv`` for managing dependencies, and a standard ``setuptools`` based build system. See "local installation" above for instructions on how to install the project. ## Changelog generation diff --git a/setup.py b/setup.py index bc1f9fbb..8399367b 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ with open(path.join(here, "README.md"), encoding="utf-8") as f: setup( name="openflexure-microscope-server", - version="2.9.3", + version="2.10.0b0", description="Python module, and Flask-based web API, to run the OpenFlexure Microscope.", long_description=long_description, # Optional, read from README.md # Denotes that our long_description is in Markdown; valid values are From 4629fa67c6287a2a7b17ef0c0c2ada06038e1f4c Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Wed, 21 Apr 2021 10:35:09 +0100 Subject: [PATCH 12/15] Consistent single backtick `code` --- README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 8f1042a8..78ecebf2 100644 --- a/README.md +++ b/README.md @@ -31,9 +31,9 @@ There are 2 important settings files: ## Creating releases * Update the applications internal version number - * Edit ``setup.py`` to update the version number + * Edit `setup.py` to update the version number * Git commit and git push -* Create a new version tag on GitLab (e.g. ``v2.6.11``) +* Create a new version tag on GitLab (e.g. `v2.6.11`) * Make sure you prefix a lower case 'v', otherwise it won't be recognised as a release! * This tagging will trigger a CI pipeline that builds the JS client, tarballs up the server, and deploys it * Note: This also updates the build server's nginx redirect map file @@ -58,12 +58,12 @@ The Raspberry Pi image we use currently ships with Python 3.7.3. For local devel * `pipenv install --dev` (This will install development dependencies. If you don't need these, `pipenv install` will get you just the dependencies needed to run the server, which takes about half the time.) * Finally, run the server: * You can use `ofm serve` or `ofm restart` on the Raspberry Pi to manage the server. - * To run the server locally, with dummy hardware, you can use ``python -m openflexure_microscope.api.app`` to start a development-mode Flask server on ``localhost:5000`` + * To run the server locally, with dummy hardware, you can use `python -m openflexure_microscope.api.app` to start a development-mode Flask server on `localhost:5000` ### Set up the Javascript environment and build -* The Flask web application, written in Python, serves a web application written in ``Vue.js``. This is distributed as part of the built version of the server, hosted on our [build server](https://build.openflexure.org/openflexure-microscope-server/). +* The Flask web application, written in Python, serves a web application written in `Vue.js`. This is distributed as part of the built version of the server, hosted on our [build server](https://build.openflexure.org/openflexure-microscope-server/). * You could extract the pre-built web app from this tarball, which saves you having to set up Node.js. However, it also means you're not able to change the interface, and it's possible your interface will get out of sync with your server. -* Building the web interface will require a valid Node.js installation. If you don't have Node.js (including ``npm``) the [Node.js website](https://nodejs.org/en/) offers downloads for all platforms, though see the instructions below for Raspberry Pi. +* Building the web interface will require a valid Node.js installation. If you don't have Node.js (including `npm`) the [Node.js website](https://nodejs.org/en/) offers downloads for all platforms, though see the instructions below for Raspberry Pi. * To install Node.js on a Raspberry Pi: * `curl -sL https://deb.nodesource.com/setup_14.x | sudo bash -` * `sudo apt install nodejs` @@ -73,10 +73,10 @@ The Raspberry Pi image we use currently ships with Python 3.7.3. For local devel * `npm run build` * To create a Node.js development server (this will help various development tools to display more information, and auto-rebuilds when you change the source files) * `npm run serve` - * You access the development server on a different port (it's printed on the command line when you run the above command). This means that when it starts up you will need to tell it where the microscope server is, using the "override API origin" field in the page that pops up. If you are running a test server on your computer, this is most likely ``http://localhost:5000/``. + * You access the development server on a different port (it's printed on the command line when you run the above command). This means that when it starts up you will need to tell it where the microscope server is, using the "override API origin" field in the page that pops up. If you are running a test server on your computer, this is most likely `http://localhost:5000/`. ## Formatting, linting, and tests -All of the commands below assume that you are running in the OFM virtual environment, i.e. you have run ``ofm activate`` on an OpenFlexure SD card, or ``source .venv/bin/activate`` on Linux, or ``.venv/Scripts/activate``on Windows. +All of the commands below assume that you are running in the OFM virtual environment, i.e. you have run `ofm activate` on an OpenFlexure SD card, or `source .venv/bin/activate` on Linux, or `.venv/Scripts/activate`on Windows. ### Tl;dr @@ -84,8 +84,8 @@ All of the commands below assume that you are running in the OFM virtual environ * To auto-format the Python code run `poe format` * To auto-format the Javascript code, run - * ``cd openflexure_microscope/api/static`` - * ``npm run lint`` + * `cd openflexure_microscope/api/static` + * `npm run lint` Auto-formats the code @@ -93,8 +93,8 @@ Auto-formats the code * To auto-format and type-check the Python code run `poe check` * To auto-format the Javascript code, run - * ``cd openflexure_microscope/api/static`` - * ``npm run lint`` + * `cd openflexure_microscope/api/static` + * `npm run lint` Formats code, lints, runs static analysis, and runs unit tests. @@ -129,7 +129,7 @@ Though not in the CI, our `format` script also runs isort: ## Build-system -As of ``2.10.0b0`` we have switched to using ``pipenv`` for managing dependencies, and a standard ``setuptools`` based build system. See "local installation" above for instructions on how to install the project. +As of `2.10.0b0` we have switched to using `pipenv` for managing dependencies, and a standard `setuptools` based build system. See "local installation" above for instructions on how to install the project. ## Changelog generation From 85df85c6e808da61ecb061e0c5f1e81c4fbf8873 Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Wed, 21 Apr 2021 11:12:54 +0100 Subject: [PATCH 13/15] reworked readme to improve clarity and style --- README.md | 70 +++++++++++++++++++++++++++---------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 78ecebf2..0fac108c 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,40 @@ # OpenFlexure Microscope Software -## Quickstart +The "server" is the main component of the OpenFlexure Microscope's software. It is responsible for controlling microscope hardware, data management, and allowing it to be controlled locally and over a network. +This repository now includes the web client, which is served from the root of the Python web server. +This software runs on [Python-LabThings](https://github.com/labthings/python-labthings/), and so most non-microscope functionality is handled by that library. + +## Getting started A general user-guide on setting up your microscope can be found [**here on our website**](https://www.openflexure.org/projects/microscope/). This includes basic installation instructions suitable for most users. +The simplest way to set up a microscope is to download the pre-built Raspberry Pi SD card image, which has this server already installed, along with all of its dependencies. +There are instructions on how to [use the microscope](https://openflexure.org/projects/microscope/control) once you have installed the software, either from OpenFlexure Connect, or through a web browser. +The web server starts on port 5000 by default, and the microscope SD image uses the hostname "microscope" so you can usually access the web interface at . -Full developer documentation can be found on [**ReadTheDocs**](https://openflexure-microscope-software.readthedocs.io/). -This includes installing the server in a mode better suited for active development. +Full developer documentation can be found on [**ReadTheDocs**](https://openflexure-microscope-software.readthedocs.io/), including some installation notes. +More information is also available in the [handbook](https://gitlab.com/openflexure/microscope-handbook/), and in the "development instructions" below. -## Key info +## Settings -* Responsible for actually controlling microscope hardware, data management, and creating the API server. -Also now includes the web client, which is served from the server root. -* Server starts on port 5000 by default. -* Runs on [Python-LabThings](https://github.com/labthings/python-labthings/), and so basically all non-microscope functionality is handled by that library. - -### Server settings - -https://openflexure-microscope-software.readthedocs.io/en/master/config.html - -There are 2 important settings files: +There are 2 important settings files, described in the [docs](https://openflexure-microscope-software.readthedocs.io/en/master/config.html). The paths given below are for the Raspberry Pi installation on our pre-built SD card, and will change if you run on another system: * `/var/openflexure/settings/microscope_configuration.json` * Boot-time microscope configuration. Things like the type of camera connected, the stage board, geometry etc. - *Anything that needs to be loaded once as the server starts, and usually doesn't need to be re-written while the server is running + * Anything that needs to be loaded once as the server starts, and usually doesn't need to be re-written while the server is running + * This configuration file does not change often, and usually only needs to be updated when you change the physical hardware. * `/var/openflexure/settings/microscope_settings.json` * Every other persistent setting. Camera settings, calibration data, default capture settings, stream resolution etc. + * This file changes very regularly, and if you need to reset your settings, it's usually this file that you should remove or reset. # Developer guidelines -## Creating releases - -* Update the applications internal version number - * Edit `setup.py` to update the version number - * Git commit and git push -* Create a new version tag on GitLab (e.g. `v2.6.11`) - * Make sure you prefix a lower case 'v', otherwise it won't be recognised as a release! - * This tagging will trigger a CI pipeline that builds the JS client, tarballs up the server, and deploys it - * Note: This also updates the build server's nginx redirect map file - ## Local installation -The Raspberry Pi image we use currently ships with Python 3.7.3. For local development, please use PyEnv or similar to make sure you're running on this version. For example, Windows users can use [Scoop](https://scoop.sh/) to install specific Python versions. +The Raspberry Pi image we use currently ships with Python 3.7.3. For local development on a different platform, please use PyEnv or similar to make sure you're running on this version. For example, Windows users can use [Scoop](https://scoop.sh/) to install specific Python versions. This repository contains two closely related parts; a web server written in Python, that handles hardware control, and a web application using Vue.js that provides a graphical control interface. It is possible to work on either of these in isolation, but bear in mind that if you only set up Python development, you will need to host the web application elsewhere. + +Most of our core team don't run the Javascript development on the Raspberry Pi, as npm can be quite slow to build the application. Instead, we set up the Python part of the project on a Raspberry Pi, and run the Javascript part on your development machine. You can then connect to the web application served from your local machine, and enter the address of the Raspberry Pi when the interface first loads. + +To set up a development version of the software (most likely using emulated camera and stage if you're not running on a Raspberry Pi): ### Clone the repository * `git clone https://gitlab.com/openflexure/openflexure-microscope-server.git` @@ -78,25 +72,20 @@ The Raspberry Pi image we use currently ships with Python 3.7.3. For local devel ## Formatting, linting, and tests All of the commands below assume that you are running in the OFM virtual environment, i.e. you have run `ofm activate` on an OpenFlexure SD card, or `source .venv/bin/activate` on Linux, or `.venv/Scripts/activate`on Windows. -### Tl;dr - -**Before committing** +**Before committing** you should auto-format your code: * To auto-format the Python code run `poe format` * To auto-format the Javascript code, run * `cd openflexure_microscope/api/static` * `npm run lint` -Auto-formats the code - -**Before submitting a merge request/merging** +**Before submitting a merge request/merging** please auto-format your code and also run the quality checks (linting, static analysis, and unit tests) * To auto-format and type-check the Python code run `poe check` * To auto-format the Javascript code, run * `cd openflexure_microscope/api/static` * `npm run lint` -Formats code, lints, runs static analysis, and runs unit tests. ### Details @@ -127,9 +116,19 @@ Though not in the CI, our `format` script also runs isort: * Automatically organises your imports to stop things getting out of hand * `poe isort` -## Build-system +## Python environment, build, and dependencies -As of `2.10.0b0` we have switched to using `pipenv` for managing dependencies, and a standard `setuptools` based build system. See "local installation" above for instructions on how to install the project. +As of `2.10.0b0` we have switched to using `pipenv` for managing dependencies, and a standard `setuptools` based build system. See "local installation" above for instructions on how to install the project. Earlier versions of the project used `poetry` but we moved away because of [difficulties](https://gitlab.com/openflexure/openflexure-microscope-server/-/merge_requests/124) getting it to work both on the Raspberry Pi and in our CI pipeline. + +## Creating releases + +* Update the application's internal version number + * Edit `setup.py` to update the version number + * Git commit and git push +* Create a new version tag on GitLab (e.g. `v2.6.11`) + * Make sure you prefix a lower case 'v', otherwise it won't be recognised as a release! + * This tagging will trigger a CI pipeline that builds the JS client, tarballs up the server, and deploys it + * Note: This also updates the build server's nginx redirect map file ## Changelog generation @@ -139,3 +138,4 @@ As of `2.10.0b0` we have switched to using `pipenv` for managing dependencies, a ## Microscope extensions The Microscope module, and Flask app, both support plugins for extending lower-level functionality not well suited to web API calls. The current documentation can be found [here](https://openflexure-microscope-software.readthedocs.io/en/latest/plugins.html). +If you want to add functions to the microscope software, this is probably the best mechanism to use if it works for you. From 1b5b5766649f4cb256188646cad98292e0ac6ffe Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Wed, 21 Apr 2021 11:28:30 +0100 Subject: [PATCH 14/15] Improved comments --- pyproject.toml | 11 +++- setup.py | 133 ++++++++++++------------------------------------- 2 files changed, 41 insertions(+), 103 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 96eaf8ff..64ac002c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,9 +2,16 @@ requires = ["setuptools", "wheel"] build-backend = "setuptools.build_meta" - +# The [tool.poetry] metadata has been removed from this file, because +# we have switched to Pipenv for dependency management and setuptools +# for the build system. All metadata has been moved either to +# Pipfile or setup.py. +# The one key that doesn't map over nicely is the exclusion of +# the node_modules folder, i.e. the line below: #exclude = ["**/node_modules/"] # I've tried to put this in the "packages" key but not sure it works. - +# I have left it here in case we ever switch back to Poetry, but I +# don't believe it's critical at present, because we don't use +# the Python package - we distribute a tarball directly. [tool.black] exclude = '(\.eggs|\.git|\.venv|\venv|node_modules/)' diff --git a/setup.py b/setup.py index 8399367b..73269b1a 100644 --- a/setup.py +++ b/setup.py @@ -1,9 +1,12 @@ -"""A setuptools based setup module. -See: +"""A setuptools based setup module for the OpenFlexure Microscope server + +This file was prepared according to: https://packaging.python.org/guides/distributing-packages-using-setuptools/ + + """ -# Always prefer setuptools over distutils +# the following imports, from the guide above, prefer `setuptools` to `distutils` from setuptools import setup, find_packages from os import path @@ -13,68 +16,32 @@ here = path.abspath(path.dirname(__file__)) with open(path.join(here, "README.md"), encoding="utf-8") as f: long_description = f.read() -# Arguments marked as "Required" below must be included for upload to PyPI. -# Fields marked as "Optional" may be commented out. +# Not all arguments to `setup()` are required for upload to PyPI. +# See the tutorial linked to at the top for which ones are needed. setup( name="openflexure-microscope-server", version="2.10.0b0", description="Python module, and Flask-based web API, to run the OpenFlexure Microscope.", - long_description=long_description, # Optional, read from README.md - # Denotes that our long_description is in Markdown; valid values are - long_description_content_type="text/markdown", # Optional (see note above) - # This should be a valid link to your project's main homepage. - # - # This field corresponds to the "Home-Page" metadata field: - # https://packaging.python.org/specifications/core-metadata/#home-page-optional - url="https://www.openflexure.org", # Optional - # This should be your name or the name of the organization which owns the - # project. - author="Joel Collins, Richard Bowman, Julian Stirling", # Optional - # This should be a valid email address corresponding to the author listed - # above. - author_email="contact@openflexure.org", # Optional - # Classifiers help users find your project by categorizing it. - # + long_description=long_description, + long_description_content_type="text/markdown", + url="https://www.openflexure.org", # "home-page" metadata field + author="Joel Collins, Richard Bowman, Julian Stirling", + author_email="contact@openflexure.org", # For a list of valid classifiers, see https://pypi.org/classifiers/ - classifiers=[ # Optional - # # How mature is this project? Common values are - # # 3 - Alpha - # # 4 - Beta - # # 5 - Production/Stable - # "Development Status :: 3 - Alpha", - # # Indicate who your project is intended for - # "Intended Audience :: Developers", - # "Topic :: Software Development :: Build Tools", - # # Pick your license as you wish - "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", - # # Specify the Python versions you support here. In particular, ensure - # # that you indicate whether you support Python 2, Python 3 or both. - # # These classifiers are *not* checked by 'pip install'. See instead - # # 'python_requires' below. - # "Programming Language :: Python :: 2", - # "Programming Language :: Python :: 2.7", - # "Programming Language :: Python :: 3", - # "Programming Language :: Python :: 3.5", - # "Programming Language :: Python :: 3.6", - # "Programming Language :: Python :: 3.7", - ], - # This field adds keywords for your project which will appear on the - # project page. What does your project relate to? - # - # Note that this is a string of words separated by whitespace, not a list. + # NB declaring Python versions here doesn't affect dependency resolution - it's for info only. + classifiers=["License :: OSI Approved :: GNU General Public License v3 (GPLv3)"], keywords="raspberry pi arduino microscope", # Optional - packages=find_packages( - exclude=["contrib", "docs", "tests", "*node_modules*"] - ), # Required - # Specify which Python versions you support + packages=find_packages(exclude=["contrib", "docs", "tests", "*node_modules*"]), python_requires="== 3.7.*", # This field lists other packages that your project depends on to run. # Any package you put here will be installed by pip when your project is # installed, so they must be valid existing projects. # - # For an analysis of "install_requires" vs pip's requirements files see: - # https://packaging.python.org/en/latest/requirements.html + # These dependencies specify relatively flexible versions; Pipenv then resolves these + # to specific versions, and locks those versions in ``Pipfile``. Usually, when you + # set up the project for development, you use those specific packages, rather than + # the looser specifications given here. install_requires=[ "Flask ~= 1.0", "Pillow ~= 7.2.0", @@ -93,15 +60,10 @@ setup( "labthings ~= 1.2.2", "typing-extensions ~= 3.7.4", # Needed for some type-hints in Python < 3.8 (e.g. Literal) "RPi.GPIO ~= 0.7.0; platform_machine == 'armv7l'", - ], # Optional - # List additional groups of dependencies here (e.g. development - # dependencies). Users will be able to install these using the "extras" - # syntax, for example: - # - # $ pip install sampleproject[dev] - # - # Similar to `install_requires` above, these must be valid existing - # projects. + ], + # "dev" specifies extra packages used for development (linting, testing, etc.) + # As with install_requires, these are relatively loose versions - Pipfile will then lock + # them to specific versions to enable consistent builds and testing. extras_require={ "dev": [ "sphinxcontrib-httpdomain ~= 1.7", @@ -112,52 +74,21 @@ setup( "poethepoet ~= 0.10.0", "freezegun ~= 1.0.0", "lxml ~= 4.6", - "black == 18.9b0", + "black == 18.9b0", # Because black is in prerelease, giving a flexible version + # specifier causes all manner of problems. A fixed version + # avoids issues with prereleases (which are normally not + # allowed by pipenv) but can be a bit of a pain sometimes! ] - }, # Optional - # If there are data files included in your packages that need to be - # installed, specify them here. - # - # Sometimes you’ll want to use packages that are properly arranged with - # setuptools, but are not published to PyPI. In those cases, you can specify - # a list of one or more dependency_links URLs where the package can - # be downloaded, along with some additional hints, and setuptools - # will find and install the package correctly. - # see https://python-packaging.readthedocs.io/en/latest/dependencies.html#packages-not-on-pypi - # + }, dependency_links=[], - # If using Python 2.6 or earlier, then these have to be included in - # MANIFEST.in as well. - # package_data={"sample": ["package_data.dat"]}, # Optional - # Although 'package_data' is the preferred approach, in some case you may - # need to place data files outside of your packages. See: - # http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files - # - # In this case, 'data_file' will be installed into '/my_data' - # data_files=[("my_data", ["data/data_file"])], # Optional - # To provide executable scripts, use entry points in preference to the - # "scripts" keyword. Entry points provide cross-platform support and allow - # `pip` to create the appropriate form of executable for the target - # platform. - # - # For example, the following would provide a command called `sample` which - # executes the function `main` from this package when invoked: + # We create some "entry points" to make it easier to run important modules entry_points={ "console_scripts": [ "ofm-serve=openflexure_microscope.api.app:ofm_serve", "ofm-rescue=openflexure_microscope.rescue.auto:main", ] - }, # Optional - # List additional URLs that are relevant to your project as a dict. - # - # This field corresponds to the "Project-URL" metadata fields: - # https://packaging.python.org/specifications/core-metadata/#project-url-multiple-use - # - # Examples listed include a pattern for specifying where the package tracks - # issues, where the source is hosted, where to say thanks to the package - # maintainers, and where to support the project financially. The key is - # what's used to render the link text on PyPI. - project_urls={ # Optional + }, + project_urls={ "Source": "https://gitlab.com/openflexure/openflexure-microscope-server" }, ) From 5d5990f7384fb8af2f862e6bb8fda43d19b7fe00 Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Wed, 21 Apr 2021 11:40:45 +0100 Subject: [PATCH 15/15] Described config files better in reame --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0fac108c..a693ff90 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,13 @@ Though not in the CI, our `format` script also runs isort: ## Python environment, build, and dependencies -As of `2.10.0b0` we have switched to using `pipenv` for managing dependencies, and a standard `setuptools` based build system. See "local installation" above for instructions on how to install the project. Earlier versions of the project used `poetry` but we moved away because of [difficulties](https://gitlab.com/openflexure/openflexure-microscope-server/-/merge_requests/124) getting it to work both on the Raspberry Pi and in our CI pipeline. +As of `2.10.0b0` we have switched to using `pipenv` for managing dependencies, and a standard `setuptools` based build system. See "local installation" above for instructions on how to install the project. Earlier versions of the project used `poetry` but we moved away because of [difficulties](https://gitlab.com/openflexure/openflexure-microscope-server/-/merge_requests/124) getting it to work both on the Raspberry Pi and in our CI pipeline. The new arrangement for configuration files is: + +* Dependencies, and dev-dependencies, are specified in `setup.py` in the usual way (using `install_requires` and `extra_requires[dev]`). +* Package metadata is specified in `setup.py` in the usual way. +* `pyproject.toml` is retained, but *no longer includes package metadata or dependencies* and does not have a `[tool.poetry]` table. It does define the build system as per PEP517, which is `setuptools`, and it also contains settings for `black`, `poe` and `isort`. +* `Pipfile` is very minimal, and only declares dependencies on the current module, i.e. the dependencies declared in `setup.py`. It also specifies the Python version. This allows us to single-source dependency information from `setup.py` but use the dependency resolution/locking functionality of `pipenv` +* `Pipfile.lock` locks the dependency versions in the same way as `poetry.lock` used to, i.e. it specifies exact versions of everything, derived from the looser specifications in `setup.py`. ## Creating releases