From 458c78db72a7f2901429e2ae778668c63b22bd83 Mon Sep 17 00:00:00 2001 From: stringertheory Date: Sun, 29 Mar 2020 00:26:58 -0500 Subject: [PATCH 01/18] adding ipython stuff --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 36bfed8..a9cfe88 100644 --- a/.gitignore +++ b/.gitignore @@ -47,8 +47,8 @@ cover *.mo *.pot -# Django stuff: -*.log +# IPython stuff +.ipynb_checkpoints/ # mkdocs docs/_build From e5e89cfdc03ee61ec502961fc8994a99a2f72b59 Mon Sep 17 00:00:00 2001 From: stringertheory Date: Sun, 29 Mar 2020 00:27:08 -0500 Subject: [PATCH 02/18] adding pipenv files --- Pipfile | 37 +++ Pipfile.lock | 877 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 914 insertions(+) create mode 100644 Pipfile create mode 100644 Pipfile.lock diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..2b77aa8 --- /dev/null +++ b/Pipfile @@ -0,0 +1,37 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] +sphinxcontrib-napoleon = "*" +recommonmark = "*" +sphinx-autobuild = "*" +bumpversion = "*" +tox = "*" +flake8 = "*" +coverage = "*" +cryptography = "*" +Sphinx = "*" +CProfileV = "*" +PyYAML = "*" +pycodestyle = "*" +coveralls = "*" +nose = "*" +pytest = "*" +pytest-mpl = "*" +numpy = "*" +scipy = "*" +pandas = "*" +matplotlib = "*" +setuptools = "*" +wheel = "*" +twine = "*" + +[packages] +sortedcontainers = "*" +infinity = "*" +python-dateutil = "*" + +[requires] +python_version = "3.8" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..1709a8e --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,877 @@ +{ + "_meta": { + "hash": { + "sha256": "4f04dda9a59afb00aab87f4006bd3e016d535fdc8a745e266c2366358a5476fe" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.8" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "infinity": { + "hashes": [ + "sha256:dc4aa138d7e366fc00d2e741e32c78a0fecd16b74f8daeb3f7408b459668005c" + ], + "index": "pypi", + "version": "==1.4" + }, + "python-dateutil": { + "hashes": [ + "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", + "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" + ], + "index": "pypi", + "version": "==2.8.1" + }, + "six": { + "hashes": [ + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" + ], + "version": "==1.14.0" + }, + "sortedcontainers": { + "hashes": [ + "sha256:974e9a32f56b17c1bac2aebd9dcf197f3eb9cd30553c5852a3187ad162e1a03a", + "sha256:d9e96492dd51fae31e60837736b38fe42a187b5404c16606ff7ee7cd582d4c60" + ], + "index": "pypi", + "version": "==2.1.0" + } + }, + "develop": { + "alabaster": { + "hashes": [ + "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", + "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02" + ], + "version": "==0.7.12" + }, + "appdirs": { + "hashes": [ + "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", + "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e" + ], + "version": "==1.4.3" + }, + "argh": { + "hashes": [ + "sha256:a9b3aaa1904eeb78e32394cd46c6f37ac0fb4af6dc488daa58971bdc7d7fcaf3", + "sha256:e9535b8c84dc9571a48999094fda7f33e63c3f1b74f3e5f3ac0105a58405bb65" + ], + "version": "==0.26.2" + }, + "attrs": { + "hashes": [ + "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", + "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72" + ], + "version": "==19.3.0" + }, + "babel": { + "hashes": [ + "sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38", + "sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4" + ], + "version": "==2.8.0" + }, + "bleach": { + "hashes": [ + "sha256:cc8da25076a1fe56c3ac63671e2194458e0c4d9c7becfd52ca251650d517903c", + "sha256:e78e426105ac07026ba098f04de8abe9b6e3e98b5befbf89b51a5ef0a4292b03" + ], + "version": "==3.1.4" + }, + "bottle": { + "hashes": [ + "sha256:0819b74b145a7def225c0e83b16a4d5711fde751cd92bae467a69efce720f69e", + "sha256:43157254e88f32c6be16f8d9eb1f1d1472396a4e174ebd2bf62544854ecf37e7" + ], + "version": "==0.12.18" + }, + "bumpversion": { + "hashes": [ + "sha256:6744c873dd7aafc24453d8b6a1a0d6d109faf63cd0cd19cb78fd46e74932c77e", + "sha256:6753d9ff3552013e2130f7bc03c1007e24473b4835952679653fb132367bdd57" + ], + "index": "pypi", + "version": "==0.5.3" + }, + "certifi": { + "hashes": [ + "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", + "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f" + ], + "version": "==2019.11.28" + }, + "cffi": { + "hashes": [ + "sha256:001bf3242a1bb04d985d63e138230802c6c8d4db3668fb545fb5005ddf5bb5ff", + "sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b", + "sha256:028a579fc9aed3af38f4892bdcc7390508adabc30c6af4a6e4f611b0c680e6ac", + "sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0", + "sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384", + "sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26", + "sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6", + "sha256:337d448e5a725bba2d8293c48d9353fc68d0e9e4088d62a9571def317797522b", + "sha256:399aed636c7d3749bbed55bc907c3288cb43c65c4389964ad5ff849b6370603e", + "sha256:3b911c2dbd4f423b4c4fcca138cadde747abdb20d196c4a48708b8a2d32b16dd", + "sha256:3d311bcc4a41408cf5854f06ef2c5cab88f9fded37a3b95936c9879c1640d4c2", + "sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66", + "sha256:66e41db66b47d0d8672d8ed2708ba91b2f2524ece3dee48b5dfb36be8c2f21dc", + "sha256:675686925a9fb403edba0114db74e741d8181683dcf216be697d208857e04ca8", + "sha256:7e63cbcf2429a8dbfe48dcc2322d5f2220b77b2e17b7ba023d6166d84655da55", + "sha256:8a6c688fefb4e1cd56feb6c511984a6c4f7ec7d2a1ff31a10254f3c817054ae4", + "sha256:8c0ffc886aea5df6a1762d0019e9cb05f825d0eec1f520c51be9d198701daee5", + "sha256:95cd16d3dee553f882540c1ffe331d085c9e629499ceadfbda4d4fde635f4b7d", + "sha256:99f748a7e71ff382613b4e1acc0ac83bf7ad167fb3802e35e90d9763daba4d78", + "sha256:b8c78301cefcf5fd914aad35d3c04c2b21ce8629b5e4f4e45ae6812e461910fa", + "sha256:c420917b188a5582a56d8b93bdd8e0f6eca08c84ff623a4c16e809152cd35793", + "sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f", + "sha256:cab50b8c2250b46fe738c77dbd25ce017d5e6fb35d3407606e7a4180656a5a6a", + "sha256:cef128cb4d5e0b3493f058f10ce32365972c554572ff821e175dbc6f8ff6924f", + "sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30", + "sha256:e56c744aa6ff427a607763346e4170629caf7e48ead6921745986db3692f987f", + "sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3", + "sha256:f2b0fa0c01d8a0c7483afd9f31d7ecf2d71760ca24499c8697aeb5ca37dc090c" + ], + "version": "==1.14.0" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "commonmark": { + "hashes": [ + "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60", + "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9" + ], + "version": "==0.9.1" + }, + "coverage": { + "hashes": [ + "sha256:03f630aba2b9b0d69871c2e8d23a69b7fe94a1e2f5f10df5049c0df99db639a0", + "sha256:046a1a742e66d065d16fb564a26c2a15867f17695e7f3d358d7b1ad8a61bca30", + "sha256:0a907199566269e1cfa304325cc3b45c72ae341fbb3253ddde19fa820ded7a8b", + "sha256:165a48268bfb5a77e2d9dbb80de7ea917332a79c7adb747bd005b3a07ff8caf0", + "sha256:1b60a95fc995649464e0cd48cecc8288bac5f4198f21d04b8229dc4097d76823", + "sha256:1f66cf263ec77af5b8fe14ef14c5e46e2eb4a795ac495ad7c03adc72ae43fafe", + "sha256:2e08c32cbede4a29e2a701822291ae2bc9b5220a971bba9d1e7615312efd3037", + "sha256:3844c3dab800ca8536f75ae89f3cf566848a3eb2af4d9f7b1103b4f4f7a5dad6", + "sha256:408ce64078398b2ee2ec08199ea3fcf382828d2f8a19c5a5ba2946fe5ddc6c31", + "sha256:443be7602c790960b9514567917af538cac7807a7c0c0727c4d2bbd4014920fd", + "sha256:4482f69e0701139d0f2c44f3c395d1d1d37abd81bfafbf9b6efbe2542679d892", + "sha256:4a8a259bf990044351baf69d3b23e575699dd60b18460c71e81dc565f5819ac1", + "sha256:513e6526e0082c59a984448f4104c9bf346c2da9961779ede1fc458e8e8a1f78", + "sha256:5f587dfd83cb669933186661a351ad6fc7166273bc3e3a1531ec5c783d997aac", + "sha256:62061e87071497951155cbccee487980524d7abea647a1b2a6eb6b9647df9006", + "sha256:641e329e7f2c01531c45c687efcec8aeca2a78a4ff26d49184dce3d53fc35014", + "sha256:65a7e00c00472cd0f59ae09d2fb8a8aaae7f4a0cf54b2b74f3138d9f9ceb9cb2", + "sha256:6ad6ca45e9e92c05295f638e78cd42bfaaf8ee07878c9ed73e93190b26c125f7", + "sha256:73aa6e86034dad9f00f4bbf5a666a889d17d79db73bc5af04abd6c20a014d9c8", + "sha256:7c9762f80a25d8d0e4ab3cb1af5d9dffbddb3ee5d21c43e3474c84bf5ff941f7", + "sha256:85596aa5d9aac1bf39fe39d9fa1051b0f00823982a1de5766e35d495b4a36ca9", + "sha256:86a0ea78fd851b313b2e712266f663e13b6bc78c2fb260b079e8b67d970474b1", + "sha256:8a620767b8209f3446197c0e29ba895d75a1e272a36af0786ec70fe7834e4307", + "sha256:922fb9ef2c67c3ab20e22948dcfd783397e4c043a5c5fa5ff5e9df5529074b0a", + "sha256:9fad78c13e71546a76c2f8789623eec8e499f8d2d799f4b4547162ce0a4df435", + "sha256:a37c6233b28e5bc340054cf6170e7090a4e85069513320275a4dc929144dccf0", + "sha256:c3fc325ce4cbf902d05a80daa47b645d07e796a80682c1c5800d6ac5045193e5", + "sha256:cda33311cb9fb9323958a69499a667bd728a39a7aa4718d7622597a44c4f1441", + "sha256:db1d4e38c9b15be1521722e946ee24f6db95b189d1447fa9ff18dd16ba89f732", + "sha256:eda55e6e9ea258f5e4add23bcf33dc53b2c319e70806e180aecbff8d90ea24de", + "sha256:f372cdbb240e09ee855735b9d85e7f50730dcfb6296b74b95a3e5dea0615c4c1" + ], + "index": "pypi", + "version": "==5.0.4" + }, + "coveralls": { + "hashes": [ + "sha256:4b6bfc2a2a77b890f556bc631e35ba1ac21193c356393b66c84465c06218e135", + "sha256:67188c7ec630c5f708c31552f2bcdac4580e172219897c4136504f14b823132f" + ], + "index": "pypi", + "version": "==1.11.1" + }, + "cprofilev": { + "hashes": [ + "sha256:8791748b1f3d3468c2c927c3fd5f905080b84d8f2d217ca764b7d9d7a1fb9a77" + ], + "index": "pypi", + "version": "==1.0.7" + }, + "cryptography": { + "hashes": [ + "sha256:02079a6addc7b5140ba0825f542c0869ff4df9a69c360e339ecead5baefa843c", + "sha256:1df22371fbf2004c6f64e927668734070a8953362cd8370ddd336774d6743595", + "sha256:369d2346db5934345787451504853ad9d342d7f721ae82d098083e1f49a582ad", + "sha256:3cda1f0ed8747339bbdf71b9f38ca74c7b592f24f65cdb3ab3765e4b02871651", + "sha256:44ff04138935882fef7c686878e1c8fd80a723161ad6a98da31e14b7553170c2", + "sha256:4b1030728872c59687badcca1e225a9103440e467c17d6d1730ab3d2d64bfeff", + "sha256:58363dbd966afb4f89b3b11dfb8ff200058fbc3b947507675c19ceb46104b48d", + "sha256:6ec280fb24d27e3d97aa731e16207d58bd8ae94ef6eab97249a2afe4ba643d42", + "sha256:7270a6c29199adc1297776937a05b59720e8a782531f1f122f2eb8467f9aab4d", + "sha256:73fd30c57fa2d0a1d7a49c561c40c2f79c7d6c374cc7750e9ac7c99176f6428e", + "sha256:7f09806ed4fbea8f51585231ba742b58cbcfbfe823ea197d8c89a5e433c7e912", + "sha256:90df0cc93e1f8d2fba8365fb59a858f51a11a394d64dbf3ef844f783844cc793", + "sha256:971221ed40f058f5662a604bd1ae6e4521d84e6cad0b7b170564cc34169c8f13", + "sha256:a518c153a2b5ed6b8cc03f7ae79d5ffad7315ad4569b2d5333a13c38d64bd8d7", + "sha256:b0de590a8b0979649ebeef8bb9f54394d3a41f66c5584fff4220901739b6b2f0", + "sha256:b43f53f29816ba1db8525f006fa6f49292e9b029554b3eb56a189a70f2a40879", + "sha256:d31402aad60ed889c7e57934a03477b572a03af7794fa8fb1780f21ea8f6551f", + "sha256:de96157ec73458a7f14e3d26f17f8128c959084931e8997b9e655a39c8fde9f9", + "sha256:df6b4dca2e11865e6cfbfb708e800efb18370f5a46fd601d3755bc7f85b3a8a2", + "sha256:ecadccc7ba52193963c0475ac9f6fa28ac01e01349a2ca48509667ef41ffd2cf", + "sha256:fb81c17e0ebe3358486cd8cc3ad78adbae58af12fc2bf2bc0bb84e8090fa5ce8" + ], + "index": "pypi", + "version": "==2.8" + }, + "cycler": { + "hashes": [ + "sha256:1d8a5ae1ff6c5cf9b93e8811e581232ad8920aeec647c37316ceac982b08cb2d", + "sha256:cd7b2d1018258d7247a71425e9f26463dfb444d411c39569972f4ce586b0c9d8" + ], + "version": "==0.10.0" + }, + "distlib": { + "hashes": [ + "sha256:2e166e231a26b36d6dfe35a48c4464346620f8645ed0ace01ee31822b288de21" + ], + "version": "==0.3.0" + }, + "docopt": { + "hashes": [ + "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491" + ], + "version": "==0.6.2" + }, + "docutils": { + "hashes": [ + "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", + "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" + ], + "version": "==0.16" + }, + "entrypoints": { + "hashes": [ + "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", + "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451" + ], + "version": "==0.3" + }, + "filelock": { + "hashes": [ + "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59", + "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836" + ], + "version": "==3.0.12" + }, + "flake8": { + "hashes": [ + "sha256:45681a117ecc81e870cbf1262835ae4af5e7a8b08e40b944a8a6e6b895914cfb", + "sha256:49356e766643ad15072a789a20915d3c91dc89fd313ccd71802303fd67e4deca" + ], + "index": "pypi", + "version": "==3.7.9" + }, + "idna": { + "hashes": [ + "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb", + "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa" + ], + "version": "==2.9" + }, + "imagesize": { + "hashes": [ + "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1", + "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1" + ], + "version": "==1.2.0" + }, + "jinja2": { + "hashes": [ + "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250", + "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49" + ], + "version": "==2.11.1" + }, + "keyring": { + "hashes": [ + "sha256:197fd5903901030ef7b82fe247f43cfed2c157a28e7747d1cfcf4bc5e699dd03", + "sha256:8179b1cdcdcbc221456b5b74e6b7cfa06f8dd9f239eb81892166d9223d82c5ba" + ], + "version": "==21.2.0" + }, + "kiwisolver": { + "hashes": [ + "sha256:05b5b061e09f60f56244adc885c4a7867da25ca387376b02c1efc29cc16bcd0f", + "sha256:210d8c39d01758d76c2b9a693567e1657ec661229bc32eac30761fa79b2474b0", + "sha256:26f4fbd6f5e1dabff70a9ba0d2c4bd30761086454aa30dddc5b52764ee4852b7", + "sha256:3b15d56a9cd40c52d7ab763ff0bc700edbb4e1a298dc43715ecccd605002cf11", + "sha256:3b2378ad387f49cbb328205bda569b9f87288d6bc1bf4cd683c34523a2341efe", + "sha256:400599c0fe58d21522cae0e8b22318e09d9729451b17ee61ba8e1e7c0346565c", + "sha256:47b8cb81a7d18dbaf4fed6a61c3cecdb5adec7b4ac292bddb0d016d57e8507d5", + "sha256:53eaed412477c836e1b9522c19858a8557d6e595077830146182225613b11a75", + "sha256:58e626e1f7dfbb620d08d457325a4cdac65d1809680009f46bf41eaf74ad0187", + "sha256:5a52e1b006bfa5be04fe4debbcdd2688432a9af4b207a3f429c74ad625022641", + "sha256:5c7ca4e449ac9f99b3b9d4693debb1d6d237d1542dd6a56b3305fe8a9620f883", + "sha256:682e54f0ce8f45981878756d7203fd01e188cc6c8b2c5e2cf03675390b4534d5", + "sha256:76275ee077772c8dde04fb6c5bc24b91af1bb3e7f4816fd1852f1495a64dad93", + "sha256:79bfb2f0bd7cbf9ea256612c9523367e5ec51d7cd616ae20ca2c90f575d839a2", + "sha256:7f4dd50874177d2bb060d74769210f3bce1af87a8c7cf5b37d032ebf94f0aca3", + "sha256:8944a16020c07b682df861207b7e0efcd2f46c7488619cb55f65882279119389", + "sha256:8aa7009437640beb2768bfd06da049bad0df85f47ff18426261acecd1cf00897", + "sha256:9105ce82dcc32c73eb53a04c869b6a4bc756b43e4385f76ea7943e827f529e4d", + "sha256:933df612c453928f1c6faa9236161a1d999a26cd40abf1dc5d7ebbc6dbfb8fca", + "sha256:939f36f21a8c571686eb491acfffa9c7f1ac345087281b412d63ea39ca14ec4a", + "sha256:9491578147849b93e70d7c1d23cb1229458f71fc79c51d52dce0809b2ca44eea", + "sha256:9733b7f64bd9f807832d673355f79703f81f0b3e52bfce420fc00d8cb28c6a6c", + "sha256:a02f6c3e229d0b7220bd74600e9351e18bc0c361b05f29adae0d10599ae0e326", + "sha256:a0c0a9f06872330d0dd31b45607197caab3c22777600e88031bfe66799e70bb0", + "sha256:aa716b9122307c50686356cfb47bfbc66541868078d0c801341df31dca1232a9", + "sha256:acc4df99308111585121db217681f1ce0eecb48d3a828a2f9bbf9773f4937e9e", + "sha256:b64916959e4ae0ac78af7c3e8cef4becee0c0e9694ad477b4c6b3a536de6a544", + "sha256:d22702cadb86b6fcba0e6b907d9f84a312db9cd6934ee728144ce3018e715ee1", + "sha256:d3fcf0819dc3fea58be1fd1ca390851bdb719a549850e708ed858503ff25d995", + "sha256:d52e3b1868a4e8fd18b5cb15055c76820df514e26aa84cc02f593d99fef6707f", + "sha256:db1a5d3cc4ae943d674718d6c47d2d82488ddd94b93b9e12d24aabdbfe48caee", + "sha256:e3a21a720791712ed721c7b95d433e036134de6f18c77dbe96119eaf7aa08004", + "sha256:e8bf074363ce2babeb4764d94f8e65efd22e6a7c74860a4f05a6947afc020ff2", + "sha256:f16814a4a96dc04bf1da7d53ee8d5b1d6decfc1a92a63349bb15d37b6a263dd9", + "sha256:f2b22153870ca5cf2ab9c940d7bc38e8e9089fa0f7e5856ea195e1cf4ff43d5a", + "sha256:f790f8b3dff3d53453de6a7b7ddd173d2e020fb160baff578d578065b108a05f", + "sha256:fe51b79da0062f8e9d49ed0182a626a7dc7a0cbca0328f612c6ee5e4711c81e4" + ], + "version": "==1.1.0" + }, + "livereload": { + "hashes": [ + "sha256:78d55f2c268a8823ba499305dcac64e28ddeb9a92571e12d543cd304faf5817b", + "sha256:89254f78d7529d7ea0a3417d224c34287ebfe266b05e67e51facaf82c27f0f66" + ], + "version": "==2.6.1" + }, + "markupsafe": { + "hashes": [ + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" + ], + "version": "==1.1.1" + }, + "matplotlib": { + "hashes": [ + "sha256:2466d4dddeb0f5666fd1e6736cc5287a4f9f7ae6c1a9e0779deff798b28e1d35", + "sha256:282b3fc8023c4365bad924d1bb442ddc565c2d1635f210b700722776da466ca3", + "sha256:4bb50ee4755271a2017b070984bcb788d483a8ce3132fab68393d1555b62d4ba", + "sha256:56d3147714da5c7ac4bc452d041e70e0e0b07c763f604110bd4e2527f320b86d", + "sha256:7a9baefad265907c6f0b037c8c35a10cf437f7708c27415a5513cf09ac6d6ddd", + "sha256:aae7d107dc37b4bb72dcc45f70394e6df2e5e92ac4079761aacd0e2ad1d3b1f7", + "sha256:af14e77829c5b5d5be11858d042d6f2459878f8e296228c7ea13ec1fd308eb68", + "sha256:c1cf735970b7cd424502719b44288b21089863aaaab099f55e0283a721aaf781", + "sha256:ce378047902b7a05546b6485b14df77b2ff207a0054e60c10b5680132090c8ee", + "sha256:d35891a86a4388b6965c2d527b9a9f9e657d9e110b0575ca8a24ba0d4e34b8fc", + "sha256:e06304686209331f99640642dee08781a9d55c6e32abb45ed54f021f46ccae47", + "sha256:e20ba7fb37d4647ac38f3c6d8672dd8b62451ee16173a0711b37ba0ce42bf37d", + "sha256:f4412241e32d0f8d3713b68d3ca6430190a5e8a7c070f1c07d7833d8c5264398", + "sha256:ffe2f9cdcea1086fc414e82f42271ecf1976700b8edd16ca9d376189c6d93aee" + ], + "index": "pypi", + "version": "==3.2.1" + }, + "mccabe": { + "hashes": [ + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + ], + "version": "==0.6.1" + }, + "more-itertools": { + "hashes": [ + "sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c", + "sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507" + ], + "version": "==8.2.0" + }, + "nose": { + "hashes": [ + "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac", + "sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a", + "sha256:f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98" + ], + "index": "pypi", + "version": "==1.3.7" + }, + "numpy": { + "hashes": [ + "sha256:1598a6de323508cfeed6b7cd6c4efb43324f4692e20d1f76e1feec7f59013448", + "sha256:1b0ece94018ae21163d1f651b527156e1f03943b986188dd81bc7e066eae9d1c", + "sha256:2e40be731ad618cb4974d5ba60d373cdf4f1b8dcbf1dcf4d9dff5e212baf69c5", + "sha256:4ba59db1fcc27ea31368af524dcf874d9277f21fd2e1f7f1e2e0c75ee61419ed", + "sha256:59ca9c6592da581a03d42cc4e270732552243dc45e87248aa8d636d53812f6a5", + "sha256:5e0feb76849ca3e83dd396254e47c7dba65b3fa9ed3df67c2556293ae3e16de3", + "sha256:6d205249a0293e62bbb3898c4c2e1ff8a22f98375a34775a259a0523111a8f6c", + "sha256:6fcc5a3990e269f86d388f165a089259893851437b904f422d301cdce4ff25c8", + "sha256:82847f2765835c8e5308f136bc34018d09b49037ec23ecc42b246424c767056b", + "sha256:87902e5c03355335fc5992a74ba0247a70d937f326d852fc613b7f53516c0963", + "sha256:9ab21d1cb156a620d3999dd92f7d1c86824c622873841d6b080ca5495fa10fef", + "sha256:a1baa1dc8ecd88fb2d2a651671a84b9938461e8a8eed13e2f0a812a94084d1fa", + "sha256:a244f7af80dacf21054386539699ce29bcc64796ed9850c99a34b41305630286", + "sha256:a35af656a7ba1d3decdd4fae5322b87277de8ac98b7d9da657d9e212ece76a61", + "sha256:b1fe1a6f3a6f355f6c29789b5927f8bd4f134a4bd9a781099a7c4f66af8850f5", + "sha256:b5ad0adb51b2dee7d0ee75a69e9871e2ddfb061c73ea8bc439376298141f77f5", + "sha256:ba3c7a2814ec8a176bb71f91478293d633c08582119e713a0c5351c0f77698da", + "sha256:cd77d58fb2acf57c1d1ee2835567cd70e6f1835e32090538f17f8a3a99e5e34b", + "sha256:cdb3a70285e8220875e4d2bc394e49b4988bdb1298ffa4e0bd81b2f613be397c", + "sha256:deb529c40c3f1e38d53d5ae6cd077c21f1d49e13afc7936f7f868455e16b64a0", + "sha256:e7894793e6e8540dbeac77c87b489e331947813511108ae097f1715c018b8f3d" + ], + "index": "pypi", + "version": "==1.18.2" + }, + "packaging": { + "hashes": [ + "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3", + "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752" + ], + "version": "==20.3" + }, + "pandas": { + "hashes": [ + "sha256:07c1b58936b80eafdfe694ce964ac21567b80a48d972879a359b3ebb2ea76835", + "sha256:0ebe327fb088df4d06145227a4aa0998e4f80a9e6aed4b61c1f303bdfdf7c722", + "sha256:11c7cb654cd3a0e9c54d81761b5920cdc86b373510d829461d8f2ed6d5905266", + "sha256:12f492dd840e9db1688126216706aa2d1fcd3f4df68a195f9479272d50054645", + "sha256:167a1315367cea6ec6a5e11e791d9604f8e03f95b57ad227409de35cf850c9c5", + "sha256:1a7c56f1df8d5ad8571fa251b864231f26b47b59cbe41aa5c0983d17dbb7a8e4", + "sha256:1fa4bae1a6784aa550a1c9e168422798104a85bf9c77a1063ea77ee6f8452e3a", + "sha256:32f42e322fb903d0e189a4c10b75ba70d90958cc4f66a1781ed027f1a1d14586", + "sha256:387dc7b3c0424327fe3218f81e05fc27832772a5dffbed385013161be58df90b", + "sha256:6597df07ea361231e60c00692d8a8099b519ed741c04e65821e632bc9ccb924c", + "sha256:743bba36e99d4440403beb45a6f4f3a667c090c00394c176092b0b910666189b", + "sha256:858a0d890d957ae62338624e4aeaf1de436dba2c2c0772570a686eaca8b4fc85", + "sha256:863c3e4b7ae550749a0bb77fa22e601a36df9d2905afef34a6965bed092ba9e5", + "sha256:a210c91a02ec5ff05617a298ad6f137b9f6f5771bf31f2d6b6367d7f71486639", + "sha256:ca84a44cf727f211752e91eab2d1c6c1ab0f0540d5636a8382a3af428542826e", + "sha256:d234bcf669e8b4d6cbcd99e3ce7a8918414520aeb113e2a81aeb02d0a533d7f7" + ], + "index": "pypi", + "version": "==1.0.3" + }, + "pathtools": { + "hashes": [ + "sha256:7c35c5421a39bb82e58018febd90e3b6e5db34c5443aaaf742b3f33d4655f1c0" + ], + "version": "==0.1.2" + }, + "pillow": { + "hashes": [ + "sha256:0a628977ac2e01ca96aaae247ec2bd38e729631ddf2221b4b715446fd45505be", + "sha256:4d9ed9a64095e031435af120d3c910148067087541131e82b3e8db302f4c8946", + "sha256:54ebae163e8412aff0b9df1e88adab65788f5f5b58e625dc5c7f51eaf14a6837", + "sha256:5bfef0b1cdde9f33881c913af14e43db69815c7e8df429ceda4c70a5e529210f", + "sha256:5f3546ceb08089cedb9e8ff7e3f6a7042bb5b37c2a95d392fb027c3e53a2da00", + "sha256:5f7ae9126d16194f114435ebb79cc536b5682002a4fa57fa7bb2cbcde65f2f4d", + "sha256:62a889aeb0a79e50ecf5af272e9e3c164148f4bd9636cc6bcfa182a52c8b0533", + "sha256:7406f5a9b2fd966e79e6abdaf700585a4522e98d6559ce37fc52e5c955fade0a", + "sha256:8453f914f4e5a3d828281a6628cf517832abfa13ff50679a4848926dac7c0358", + "sha256:87269cc6ce1e3dee11f23fa515e4249ae678dbbe2704598a51cee76c52e19cda", + "sha256:875358310ed7abd5320f21dd97351d62de4929b0426cdb1eaa904b64ac36b435", + "sha256:8ac6ce7ff3892e5deaab7abaec763538ffd011f74dc1801d93d3c5fc541feee2", + "sha256:91b710e3353aea6fc758cdb7136d9bbdcb26b53cefe43e2cba953ac3ee1d3313", + "sha256:9d2ba4ed13af381233e2d810ff3bab84ef9f18430a9b336ab69eaf3cd24299ff", + "sha256:a62ec5e13e227399be73303ff301f2865bf68657d15ea50b038d25fc41097317", + "sha256:ab76e5580b0ed647a8d8d2d2daee170e8e9f8aad225ede314f684e297e3643c2", + "sha256:bf4003aa538af3f4205c5fac56eacaa67a6dd81e454ffd9e9f055fff9f1bc614", + "sha256:bf598d2e37cf8edb1a2f26ed3fb255191f5232badea4003c16301cb94ac5bdd0", + "sha256:c18f70dc27cc5d236f10e7834236aff60aadc71346a5bc1f4f83a4b3abee6386", + "sha256:c5ed816632204a2fc9486d784d8e0d0ae754347aba99c811458d69fcdfd2a2f9", + "sha256:dc058b7833184970d1248135b8b0ab702e6daa833be14035179f2acb78ff5636", + "sha256:ff3797f2f16bf9d17d53257612da84dd0758db33935777149b3334c01ff68865" + ], + "version": "==7.0.0" + }, + "pkginfo": { + "hashes": [ + "sha256:7424f2c8511c186cd5424bbf31045b77435b37a8d604990b79d4e70d741148bb", + "sha256:a6d9e40ca61ad3ebd0b72fbadd4fba16e4c0e4df0428c041e01e06eb6ee71f32" + ], + "version": "==1.5.0.1" + }, + "pluggy": { + "hashes": [ + "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", + "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" + ], + "version": "==0.13.1" + }, + "pockets": { + "hashes": [ + "sha256:68597934193c08a08eb2bf6a1d85593f627c22f9b065cc727a4f03f669d96d86", + "sha256:9320f1a3c6f7a9133fe3b571f283bcf3353cd70249025ae8d618e40e9f7e92b3" + ], + "version": "==0.9.1" + }, + "port-for": { + "hashes": [ + "sha256:b16a84bb29c2954db44c29be38b17c659c9c27e33918dec16b90d375cc596f1c" + ], + "version": "==0.3.1" + }, + "py": { + "hashes": [ + "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa", + "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0" + ], + "version": "==1.8.1" + }, + "pycodestyle": { + "hashes": [ + "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", + "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" + ], + "index": "pypi", + "version": "==2.5.0" + }, + "pycparser": { + "hashes": [ + "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", + "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705" + ], + "version": "==2.20" + }, + "pyflakes": { + "hashes": [ + "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", + "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2" + ], + "version": "==2.1.1" + }, + "pygments": { + "hashes": [ + "sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44", + "sha256:ff7a40b4860b727ab48fad6360eb351cc1b33cbf9b15a0f689ca5353e9463324" + ], + "version": "==2.6.1" + }, + "pyparsing": { + "hashes": [ + "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f", + "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec" + ], + "version": "==2.4.6" + }, + "pytest": { + "hashes": [ + "sha256:0e5b30f5cb04e887b91b1ee519fa3d89049595f428c1db76e73bd7f17b09b172", + "sha256:84dde37075b8805f3d1f392cc47e38a0e59518fb46a431cfdaf7cf1ce805f970" + ], + "index": "pypi", + "version": "==5.4.1" + }, + "pytest-mpl": { + "hashes": [ + "sha256:26c5a47a8fdbc04652f18b65c587da642c6cc0354680ee44b16c161d9800a2ce", + "sha256:d9b8d7cbb9848cacb6aa291c14fdf61b6f8f585c8b1d2fb16b431a7404a3a5f6" + ], + "index": "pypi", + "version": "==0.11" + }, + "python-dateutil": { + "hashes": [ + "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", + "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" + ], + "index": "pypi", + "version": "==2.8.1" + }, + "pytz": { + "hashes": [ + "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d", + "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be" + ], + "version": "==2019.3" + }, + "pyyaml": { + "hashes": [ + "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97", + "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76", + "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2", + "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648", + "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf", + "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f", + "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2", + "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee", + "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d", + "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c", + "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a" + ], + "index": "pypi", + "version": "==5.3.1" + }, + "readme-renderer": { + "hashes": [ + "sha256:1b6d8dd1673a0b293766b4106af766b6eff3654605f9c4f239e65de6076bc222", + "sha256:e67d64242f0174a63c3b727801a2fff4c1f38ebe5d71d95ff7ece081945a6cd4" + ], + "version": "==25.0" + }, + "recommonmark": { + "hashes": [ + "sha256:29cd4faeb6c5268c633634f2d69aef9431e0f4d347f90659fd0aab20e541efeb", + "sha256:2ec4207a574289355d5b6ae4ae4abb29043346ca12cdd5f07d374dc5987d2852" + ], + "index": "pypi", + "version": "==0.6.0" + }, + "requests": { + "hashes": [ + "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee", + "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6" + ], + "version": "==2.23.0" + }, + "requests-toolbelt": { + "hashes": [ + "sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f", + "sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0" + ], + "version": "==0.9.1" + }, + "scipy": { + "hashes": [ + "sha256:00af72998a46c25bdb5824d2b729e7dabec0c765f9deb0b504f928591f5ff9d4", + "sha256:0902a620a381f101e184a958459b36d3ee50f5effd186db76e131cbefcbb96f7", + "sha256:1e3190466d669d658233e8a583b854f6386dd62d655539b77b3fa25bfb2abb70", + "sha256:2cce3f9847a1a51019e8c5b47620da93950e58ebc611f13e0d11f4980ca5fecb", + "sha256:3092857f36b690a321a662fe5496cb816a7f4eecd875e1d36793d92d3f884073", + "sha256:386086e2972ed2db17cebf88610aab7d7f6e2c0ca30042dc9a89cf18dcc363fa", + "sha256:71eb180f22c49066f25d6df16f8709f215723317cc951d99e54dc88020ea57be", + "sha256:770254a280d741dd3436919d47e35712fb081a6ff8bafc0f319382b954b77802", + "sha256:787cc50cab3020a865640aba3485e9fbd161d4d3b0d03a967df1a2881320512d", + "sha256:8a07760d5c7f3a92e440ad3aedcc98891e915ce857664282ae3c0220f3301eb6", + "sha256:8d3bc3993b8e4be7eade6dcc6fd59a412d96d3a33fa42b0fa45dc9e24495ede9", + "sha256:9508a7c628a165c2c835f2497837bf6ac80eb25291055f56c129df3c943cbaf8", + "sha256:a144811318853a23d32a07bc7fd5561ff0cac5da643d96ed94a4ffe967d89672", + "sha256:a1aae70d52d0b074d8121333bc807a485f9f1e6a69742010b33780df2e60cfe0", + "sha256:a2d6df9eb074af7f08866598e4ef068a2b310d98f87dc23bd1b90ec7bdcec802", + "sha256:bb517872058a1f087c4528e7429b4a44533a902644987e7b2fe35ecc223bc408", + "sha256:c5cac0c0387272ee0e789e94a570ac51deb01c796b37fb2aad1fb13f85e2f97d", + "sha256:cc971a82ea1170e677443108703a2ec9ff0f70752258d0e9f5433d00dda01f59", + "sha256:dba8306f6da99e37ea08c08fef6e274b5bf8567bb094d1dbe86a20e532aca088", + "sha256:dc60bb302f48acf6da8ca4444cfa17d52c63c5415302a9ee77b3b21618090521", + "sha256:dee1bbf3a6c8f73b6b218cb28eed8dd13347ea2f87d572ce19b289d6fd3fbc59" + ], + "index": "pypi", + "version": "==1.4.1" + }, + "six": { + "hashes": [ + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" + ], + "version": "==1.14.0" + }, + "snowballstemmer": { + "hashes": [ + "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0", + "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52" + ], + "version": "==2.0.0" + }, + "sphinx": { + "hashes": [ + "sha256:b4c750d546ab6d7e05bdff6ac24db8ae3e8b8253a3569b754e445110a0a12b66", + "sha256:fc312670b56cb54920d6cc2ced455a22a547910de10b3142276495ced49231cb" + ], + "index": "pypi", + "version": "==2.4.4" + }, + "sphinx-autobuild": { + "hashes": [ + "sha256:66388f81884666e3821edbe05dd53a0cfb68093873d17320d0610de8db28c74e", + "sha256:e60aea0789cab02fa32ee63c7acae5ef41c06f1434d9fd0a74250a61f5994692" + ], + "index": "pypi", + "version": "==0.7.1" + }, + "sphinxcontrib-applehelp": { + "hashes": [ + "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a", + "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58" + ], + "version": "==1.0.2" + }, + "sphinxcontrib-devhelp": { + "hashes": [ + "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e", + "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4" + ], + "version": "==1.0.2" + }, + "sphinxcontrib-htmlhelp": { + "hashes": [ + "sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f", + "sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b" + ], + "version": "==1.0.3" + }, + "sphinxcontrib-jsmath": { + "hashes": [ + "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", + "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8" + ], + "version": "==1.0.1" + }, + "sphinxcontrib-napoleon": { + "hashes": [ + "sha256:407382beed396e9f2d7f3043fad6afda95719204a1e1a231ac865f40abcbfcf8", + "sha256:711e41a3974bdf110a484aec4c1a556799eb0b3f3b897521a018ad7e2db13fef" + ], + "index": "pypi", + "version": "==0.7" + }, + "sphinxcontrib-qthelp": { + "hashes": [ + "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72", + "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6" + ], + "version": "==1.0.3" + }, + "sphinxcontrib-serializinghtml": { + "hashes": [ + "sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc", + "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a" + ], + "version": "==1.1.4" + }, + "toml": { + "hashes": [ + "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", + "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e" + ], + "version": "==0.10.0" + }, + "tornado": { + "hashes": [ + "sha256:0fe2d45ba43b00a41cd73f8be321a44936dc1aba233dee979f17a042b83eb6dc", + "sha256:22aed82c2ea340c3771e3babc5ef220272f6fd06b5108a53b4976d0d722bcd52", + "sha256:2c027eb2a393d964b22b5c154d1a23a5f8727db6fda837118a776b29e2b8ebc6", + "sha256:5217e601700f24e966ddab689f90b7ea4bd91ff3357c3600fa1045e26d68e55d", + "sha256:5618f72e947533832cbc3dec54e1dffc1747a5cb17d1fd91577ed14fa0dc081b", + "sha256:5f6a07e62e799be5d2330e68d808c8ac41d4a259b9cea61da4101b83cb5dc673", + "sha256:c58d56003daf1b616336781b26d184023ea4af13ae143d9dda65e31e534940b9", + "sha256:c952975c8ba74f546ae6de2e226ab3cc3cc11ae47baf607459a6728585bb542a", + "sha256:c98232a3ac391f5faea6821b53db8db461157baa788f5d6222a193e9456e1740" + ], + "version": "==6.0.4" + }, + "tox": { + "hashes": [ + "sha256:a4a6689045d93c208d77230853b28058b7513f5123647b67bf012f82fa168303", + "sha256:b2c4b91c975ea5c11463d9ca00bebf82654439c5df0f614807b9bdec62cc9471" + ], + "index": "pypi", + "version": "==3.14.6" + }, + "tqdm": { + "hashes": [ + "sha256:4f882b23c492e7060f50d83af86f163b67e4cfbe35dfe12077e748c56282f438", + "sha256:f0fc945df434e5e612fb7eb93bf29e924940913590450c3760f198dd75a2cd19" + ], + "version": "==4.44.0" + }, + "twine": { + "hashes": [ + "sha256:c1af8ca391e43b0a06bbc155f7f67db0bf0d19d284bfc88d1675da497a946124", + "sha256:d561a5e511f70275e5a485a6275ff61851c16ffcb3a95a602189161112d9f160" + ], + "index": "pypi", + "version": "==3.1.1" + }, + "urllib3": { + "hashes": [ + "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc", + "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc" + ], + "version": "==1.25.8" + }, + "virtualenv": { + "hashes": [ + "sha256:4e399f48c6b71228bf79f5febd27e3bbb753d9d5905776a86667bc61ab628a25", + "sha256:9e81279f4a9d16d1c0654a127c2c86e5bca2073585341691882c1e66e31ef8a5" + ], + "version": "==20.0.15" + }, + "watchdog": { + "hashes": [ + "sha256:c560efb643faed5ef28784b2245cf8874f939569717a4a12826a173ac644456b" + ], + "version": "==0.10.2" + }, + "wcwidth": { + "hashes": [ + "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1", + "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1" + ], + "version": "==0.1.9" + }, + "webencodings": { + "hashes": [ + "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", + "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" + ], + "version": "==0.5.1" + }, + "wheel": { + "hashes": [ + "sha256:8788e9155fe14f54164c1b9eb0a319d98ef02c160725587ad60f14ddc57b6f96", + "sha256:df277cb51e61359aba502208d680f90c0493adec6f0e848af94948778aed386e" + ], + "index": "pypi", + "version": "==0.34.2" + } + } +} From 914d210452d442a74c917e818df4183d50287583 Mon Sep 17 00:00:00 2001 From: stringertheory Date: Sun, 29 Mar 2020 00:29:37 -0500 Subject: [PATCH 03/18] adding example of plot --- examples/Plot.ipynb | 93 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 examples/Plot.ipynb diff --git a/examples/Plot.ipynb b/examples/Plot.ipynb new file mode 100644 index 0000000..7e746bf --- /dev/null +++ b/examples/Plot.ipynb @@ -0,0 +1,93 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "%config InlineBackend.figure_format = 'retina'" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import traces" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "ts = traces.TimeSeries()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "ts[0] = 0\n", + "ts[1] = 1\n", + "ts[2] = 0\n", + "ts[5] = 2\n", + "ts[10] = 2" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABU8AAADFCAYAAABkSAN6AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+j8jraAAAgAElEQVR4nO3de5Bc110n8K8iW1KkSGjFGDlYKyUSC1RMBAGHJEAqDgnaJRQGli2eYQlZvGdJeInHQiU8QsDFowCR3SxwooUQ4yVAFQEECYU34IgKjyJxyDqQsLAWq7EUS6uxIqSMrJFHmf2je4Qj91gt1DO3T8/nU6VqT/ftvr+r0de3+9fnnrNmYWEhAAAAAAB8vKd0XQAAAAAAwDjSPAUAAAAAGEDzFAAAAABgAM1TAAAAAIABNE8BAAAAAAbQPAUAAAAAGEDzFAAAAABgAM1TAAAAAIABNE8BAAAAAAbQPAUAAAAAGEDzFAAAAABgAM1TAAAAAIABNE8BAAAAAAbQPAUAAAAAGOCGUb1QKWVrkv1JvjLJM5NcTPK3Sd6c5JdqrZdGtS8AAAAAgOW2ZmFh4bpfpJTyKUnemWRX/66HkmxLsqn/8x8l+ZJa69x17wwAAAAAYAVc98jTUsraJL+dXuP0j5N8c631H0opa5J8UZJfTvKSJD+S5Puvd38DXH/3FwAAAACYdGuu+QnXO/K0lPLSJP8zyYeTfGqtdfaKx1+S3qjUf0yyrdb6seva4RNpngIAAAAAV3PNzdNRzHm6p3/71isbp333JZlN8glJtid5eAT7BACAJ3j00Udz77335qGHHsrOnTuzb9++bNiwoeuyAADGivdMwxtF8/RQkk9LcmCJxxeSLI42fWwE+1u1Tp06lSS56aabOq4EuBp5hTbI6mR54IEHcuedd2ZmZubyfVNTUzl48GD27t3bYWWMgrxCG2QVxp/3TNdmJAtGPZlSyvOT/HmSD9Van7UMu1g1l+0fOXIkSbJ79+6OKwGuRl6hDbI6OS5cuJAXvehFH/chYNHU1FQOHz5sNEXj5BXaIKsw3rxn6uay/SWVUp6S5Cf6P/74NTzv/mG3rbUm6f0P+vH/cz5x4kTOnz+f7du3Z9OmTUmSs2fPZmZmJps3b778Ldj8/Hymp6ezdu3a7Nq16/Lzjx07losXL+aWW27J+vXrkySnT5/OmTNnsnXr1mzbti1JMjc3l+PHj2fdunXZsWPH5ecfPXo0ly5dys6dO3PDDb2/5lOnTuXcuXOZmprKli1bkiSzs7M5efJkNm7cmJtvvvny8wedcG688cY89thjmZ2dnZhjmsTfk2NyTFu3bs3U1NTEHdMk/p4ck2OamprKzMzMqngfMenH9Ed/9EcDPwQkyczMTG699daBjwEA0DMzM5N77rkn3/AN3zCW7/eu5z3s9Xyh85R/9jOH85okL0ry+0nuWeZ9Tbwbb7yx6xKAIW3ZsuXyiQEYX3I6Oaanp7suAQCgeQ8/bKmiKy3bZfullC9P8rYkR5PcVmt9ZFl2tIou2wcAYLBDhw5l//79Sz5+4MCB3HHHHStYEQDA+PGe6dov21+W5mkp5bYkf5LkUpLPr7U+MPKd/JNV0zydnZ1NksvDlIHxJa/QBlmdHObvmnzyCm2QVRhv3jNde/N05Jftl1J2Jvm9JOuTfM0yN05XlZMnT+bkyZNdlwEMQV6hDbI6OTZs2JCDBw9ennN60eLKsRP+IWBVkFdog6zCePOe6dqNdMGoUsqW9OY3vTnJd9Za3z7K11/tNm7c2HUJwJDkFdogq5Nl7969OXz48OXFoQ4cOJB9+/b5EDAh5BXaIKsw/hbfM/3mb/5mPvzhD+dZz3qW90xPYmSX7ZdSbkhyKMkXJ/mFJK+uta7EJfWr5rJ9AACubs+ePUmSBx98sONKAAAYM91ctl9KWZPkDek1Tu9N8u0r1DgFAAAAAFgWo5rz9FX9Px9K8lW11vkRvS4AAAAAQCeu+7L9UsqmJDNJNvRvH1li04Ukb6q1HriuHQ5+3VXhyJEjSZLdu3d3XAlwNfIKbZDVyeSy/ckkr9AGWYV2rNK8XvNl+6NYMOqxJO9P8vwkU/0/S3nGCPYHAAAAALDsRrZgVIeaPwAAAEbHyFMAAJbQzYJRAAAAAACTRvMUAAAAAGAAzdOGnDhxIidOnOi6DGAI8gptkFVoh7xCG2QV2iGvwxnFglGskPPnz3ddAjAkeYU2yCq0Q16hDbIK7ZDX4WieNmT79u1dlwAMSV6hDbIK7ZBXaIOsQjvkdTiapw3ZtGlT1yUAQ5JXaIOsQjvkFdogq9AOeR2OOU8BAAAAAAbQPG3I2bNnc/bs2a7LAIYgr9AGWYV2yCu0QVahHfI6HJftN2RmZiZJsmXLlo4rAa5GXqENsgrtkFdog6xCO+R1OJqnDdm8eXPXJQBDkldog6xCO+QV2iCr0A55Hc6ahYWFrmu4Xs0fAAAAo7Nnz54kyYMPPthxJQAAjJk11/oEc54CAAAAAAygedqQ+fn5zM/Pd10GMAR5hTbIKrRDXqENsgrtkNfhaJ42ZHp6OtPT012XAQxBXqENsgrtkFdog6xCO+R1OBaMasjatWu7LgEYkrxCG2QV2iGv0AZZhXbI63AsGAUAwESxYBQAAEuwYBQAAAAAwChongIAAAAADKB52pBjx47l2LFjXZcBDEFeoQ2yCu2QV2iDrEI75HU4FoxqyMWLF7suARiSvEIbZBXaIa/QBlmFdsjrcCwY1ZC5ubkkyfr16zuuBLgaeYU2yOpksmDUZJJXaIOsQjtWaV6vecEoI08bssr+MUPT5BXaIKvQDnmFNsgqtENeh2POUwAAAACAATRPG3L69OmcPn266zKAIcgrtEFWoR3yCm2QVWiHvA5H87QhZ86cyZkzZ7ouAxiCvEIbZBXaIa/QBlmFdsjrcMx52pCtW7d2XQIwJHmFNsgqtENeoQ2yCu2Q1+GsWVhofrH65g8AAIDR2bNnT5LkwQcf7LgSAADGzJprfYLL9gEAAAAABtA8bcjc3Fzm5ua6LgMYgrxCG2QV2iGv0AZZhXbI63A0Txty/PjxHD9+vOsygCHIK7RBVqEd8gptkFVoh7wOx4JRDVm3bl3XJQBDkldog6xCO+QV2iCr0A55HY4FowAAmCgWjAIAYAkWjAIAAAAAGAXNUwAAAACAATRPG3L06NEcPXq06zKAIcgrtEFWoR3yCm2QVWiHvA7HglENuXTpUtclAEOSV2iDrEI75BXaIKvQDnkdzrIuGFVK+Ywkv5jk05O8rNb6l8uwm1WzYNT8/HyS5IYb9Lxh3MkrtEFWJ5MFoyaTvEIbZBXasUrzes0LRi3b304p5eVJ3pTkqf27viTJcjRPV41V9o8Zmiav0AZZhXbIK7RBVqEd8jqckf8tlVJuTPJzSV6VZD7JB5I8O8naUe8LAAAAAGC5LMeCUXel1zg9muSFSd62DPtYlU6dOpVTp051XQYwBHmFNsgqtENeoQ2yCu2Q1+EsR/P03Ul+Jslzaq1/sQyvv2qdO3cu586d67oMRujRRx/N7/7u7+aNb3xjDh06lAsXLnRdEiMir9AGWYV2yCu0QVahHfI6nJFftl9rPZTk0Khfl2RqaqrrEhihBx54IHfeeWdmZmYu3zc1NZWDBw9m7969HVbGKMgrtEFWoR3yCm2QVWiHvA7HzLAN2bJlS9clMCIXLlx4QuM0SWZmZnLnnXfm8OHD2bBhQ0fVMQryCm2QVWiHvEIbZBXaIa/DGcvmaSnl/mG3rbUmSY4cOZLdu3dfvv/EiRM5f/58tm/fnk2bNiVJzp49m5mZmWzevDk33XRTkmR+fj7T09NZu3Ztdu3adfn5x44dy8WLF3PLLbdk/fr1SZLTp0/nzJkz2bp1a7Zt25YkmZuby/Hjx7Nu3brs2LHj8vOPHj2aS5cuZefOnZdXLzt16lTOnTuXqampy/9AZ2dnc/LkyWzcuDE333zz5ecfOXIkSRzThB7Tvffe+4TG6aKZmZnceuutAx+jLbfffnt+/ud/fqz+7SWTlyfH5Jgck2O68piuNAnHNIm/J8fkmByTY3JMjskxOaaVOqbHv+a1Wo45T1km8/PzXZfAiExPT3ddAivgXe96V9clAFcxOzvbdQnAkB599FGZhQbMzs5mbm6u6zKAISwsLDi3DmHNwsLCsu6glPK6JD+c5K5a6w8swy6W9wDGyKAOPG06dOhQ9u/fv+TjBw4cyB133LGCFTFqe/bsSZI8+OCDHVcCPBnn1snk/8GTSV6hDbIK7VileV1zrU8Yy8v2GWzjxo1dl8CI7Nu3L1NTUwMv3Z+amsq+ffs6qApg9XFuhXbIK7RBVqEd8joczdOGPH4eCNq2YcOGHDx48AmLRk1NTeXgwYMWiwJYIc6t0A55hTbIKrRDXodjzlPoyN69e3P48OHLPx84cCCHDx/O3r17O6wKAAAAgEVGnkKHHj/C1BynAAAAAOPFyNOGHDly5PJkvgDA9XNuhXbIK7RBVqEd8joczVMAAAAAgAFctt+Q3bt3d10CAEwU51Zoh7xCG2QV2iGvw1mJkafvSTLbvwUAAAAAaMKyjzyttb49ydOWez8AAAAAAKNkztOGnDhxIidOnOi6DACYGM6t0A55hTbIKrRDXodjztOGnD9/vusSAGCiOLdCO+QV2iCr0A55HY7maUO2b9/edQkAMFGcW6Ed8gptkFVoh7wOR/O0IZs2beq6BACYKM6t0A55hTbIKrRDXodjzlMAAAAAgAE0Txty9uzZnD17tusyAGBiOLdCO+QV2iCr0A55HY7L9hsyMzOTJNmyZUvHlQDAZHBuhXbIK7RBVqEd8joczdOGbN68uesSAGCiOLdCO+QV2iCr0A55HY7maUNuuummrksAgIni3ArtkFdog6xCO+R1OOY8BQAAAAAYQPO0IfPz85mfn++6DACYGM6t0A55hTbIKrRDXoejedqQ6enpTE9Pd10GAEwM51Zoh7xCG2QV2iGvwzHnaUPWrl3bdQkAMFGcW6Ed8gptkFVoh7wOR/O0Ibt27eq6BACYKM6t0A55hTbIKrRDXofjsn0AAAAAgAE0TwEAAAAABtA8bcixY8dy7NixrssAgInh3ArtkFdog6xCO+R1OOY8bcjFixe7LgEAJopzK7RDXqENsgrtkNfhaJ425JZbbum6BACYKM6t0A55hTbIKrRDXoejedqQ9evXd10CAEwU51Zoh7xCG2QV2iGvwzHnKQAAAADAAJqnDTl9+nROnz7ddRkAMDGcW6Ed8gptkFVoh7wOR/O0IWfOnMmZM2e6LgMAJoZzK7RDXqENsgrtkNfhmPO0IVu3bu26BACYKM6t0A55hTbIKrRDXoejedqQbdu2dV0CAEwU51Zoh7xCG2QV2iGvw3HZPgAAAADAAJqnDZmbm8vc3FzXZQDAxHBuhXbIK7RBVqEd8joczdOGHD9+PMePH++6DACYGM6t0A55hTbIKrRDXodjztOGrFu3rusSAGCiOLdCO+QV2iCr0A55HY7maUN27NjRdQkAMFGcW6Ed8gptkFVoh7wOx2X7AAAAAAADaJ4CAAAAAAygedqQo0eP5ujRo12XAQATw7kV2iGv0AZZhXbI63DMedqQS5cudV0CAEwU51Zoh7xCG2QV2iGvw9E8bcjOnTu7LgEAJopzK7RDXqENsgrtkNfhaJ425IYb/LoAYJScW6Ed8gptkFVoh7wOZ6R/S6WUFyT5/iRfkGRLkoeS/E6Su2qtj4xyXwAAAAAAy2lkC0aVUr4uyZ8muSPJhiQPJ9mVZH+S+0spO0a1r9Xq1KlTOXXqVNdlAMDEcG6FdsgrtEFWoR3yOpyRNE9LKc9N8pYkC0m+O8m2WuvOJM9Icm96TdR3lFKMB74O586dy7lz57ouAwAmhnMrtENeoQ2yCu2Q1+GMqpl5V/+1Xldr/dnFO2utD5VSviLJ/UmeneRrk/zqiPa56kxNTXVdAgBMFOdWaIe8QhtkFdohr8O57pGnpZQ9Sb4oyUeS/PSVj9dazyd5ff/Hb7ne/a1Wjz76aO67777cfffdOXToUC5cuNB1ScASHn300cv/La8w3rZs2ZItW7Z0XQYwBHmFNsgqtENehzOKkae392/fUWudXWKbQ0nmkjy3lPK0WutHR7DfVeOBBx7InXfemZmZmcv3TU1N5eDBg9m7d2+HlQFXWszrov3798srAAAANGoUc57e1r9971Ib9JuqH0yvWat7cA0uXLjwhMZpkszMzOTOO+80og3GiLxCe2ZnZzM7u9R3v8A4kVdog6xCO+R1OKMYefqJ/duHrrLddJLnPG77JZVS7h9257XWJMmRI0eye/fuy/efOHEi58+fz/bt27Np06YkydmzZzMzM5PNmzfnpptuSpLMz89neno6a9euza5duy4//9ixY7l48WJuueWWrF+/Pkly+vTpnDlzJlu3bs22bduSJHNzczl+/HjWrVuXHTt2XH7+0aNHc+nSpezcuTM33ND7az516lTOnTuXqampy8OiZ2dnc/LkyWzcuDE333zz5ecfOXIkSfLXf/3XT2jELJqZmcmtt9467F8VjRiXf3uTmKflPqa3ve1t8gowhlb7+WlSjmnR7t27J+aYJvH35Jgc08mTJy9vPynHNIm/J8fkmKanpy8/b/E1JuGYlvo9Pf41r9Uomqfb+rdXuxR/8fFtT7oVH+fx/5iZXLfffnvXJTACx48f77oEAPo+7/M+r+sSGLENGzbkKU8ZxYVzwHLauHFj5ufnP+5LD2A8rVmzJk996lO7LmPsrVlYWLiuFyilvDPJS5L8m1rrHz7Jdvck+fok31Rr/ZXr2unHu74DGHOHDh3K/v37l3z8wIEDueOOO1awImAp8goAAABjbc21PmEUX91+pH+76SrbPa1/e3oE+1w19u3bl6mpqYGPTU1NZd++fStcEbAUeQUAAIDJMorm6SP9251X2W7x8UeedCs+zoYNG3Lw4MEnNGQWV+/esGFDR5UBV5JXAAAAmCyjmPP0ff3b5y61QSllY5JnJbmU5AMj2Oeqsnfv3hw+fDj33HNPHn744XzmZ35m9u3bpxEDY0heoS2DJqUHxpO8QhtkFdohr8MZxZynn5rkfyc5k2RHrXV2wDZfneTXk7yn1vq517XDJ5roOU8BAAAAgJFY+TlPa61/l+RdSbYm+d4rHy+lbEjyQ4ubX+/+AAAAAABWwigu20+S1yb5kyQ/WEo5l+SNtda5UsotSd6U3iX7H0py94j293jX3DFuVSnl/iSptX5O17UAT05eoQ2yCu2QV2iDrEI75HU4o1gwKrXWP0vyyv7r/XSSR0opR5NMJ3lZkmNJvrjW+tgo9gcAAAAAsNxG0jxNklrr3UlemOT3kzyW5Jb0mqdvSPLZtdajo9oXAAAAAMByG9Vl+0mSWuu7k7x7lK8JAAAAANCFkY08BQAAAACYJJqnAAAAAAADaJ4CAAAAAAygeQoAAAAAMIDmKQAAAADAAJqnAAAAAAADaJ4CAAAAAAywZmFhoesaAAAAAADGjpGnAAAAAAADaJ4CAAAAAAygeQoAAAAAMIDmKQAAAADAAJqnAAAAAAADaJ4CAAAAAAygeQoAAAAAMIDmKQAAAADAADd0XQBXV0p5QZLvT/IFSbYkeSjJ7yS5q9b6SJe1Af+klLI1yf4kX5nkmUkuJvnbJG9O8ku11ksdlgc8iVLKlyZ5U5KFJF9Za/3zjksC+kopO5N8T5KXJdmR3vn1fyX5pSS/Xmu90GF5QJJSypokX5Pkm5J8VpKtSU4l+ZMkb6y1/mmH5cGqVkr5jCS/mOTTk7ys1vqXA7Z5VpLXJnlJkk9McjLJHyT5sVrr0RUsdywZeTrmSilfl+RPk9yRZEOSh5PsSq9Bc38pZUeH5QF9pZRPSfL+JD+U5NYkjyS5Mcnzk9Qkf1hKWd9dhcBS+vl9a5Kbkzw9vQ9+wBgopXxhkg8k+bb03gOfTHIpvUEFb07y/lLKJ3dXIVBKWZfkd5P8WpIvSrI5yYkk29NrqL67lPLa7iqE1auU8vIkf5nk89Nrin7JgG1uT/K+JF+X3hcfH04vv9+c5K9KKc9eqXrHlebpGCulPDfJW9IbBfPdSbbVWncmeUaSe9N7A/mOUooRxNChUsraJL+dXib/OMnuflY3J/nXSY6n9w3ej3RWJDBQKeUp6TVgNiX5/f7dG7urCFhUSnlGeufXLUl+PMlNtdZd6X34+8IkH0zyaUle01WNQJLkB5J8aXpfbnxZkk3998JPS/Kd6X3h8WP9L0OAFVBKubGU8t+S/Gp6g3o+0H9o7RXb7UpyKMn6JD+VZKp/rn16/7n/Ir2BQJ+wUrWPI83T8XZXelMrvL7W+rO11rkkqbU+lOQr0rsc+NlJvra7EoEkL07yGel9Q3dHrfUfkqTWulBrvTfJN/a3+0/9Rg0wPr41vRFsv57ktzquBfh4r0+vcfrTtdbX1FrPJEmt9WO11vuSfG6S16U3chzozuJ73VfWWg/VWj+WJLXWC7XWN6TXkEmSV3ZSHaxOdyV5VZKjSV6Y5G1LbPfa9Ab9/Eqt9ftqrR9NklrrTJJXJLkvvUbqty93wePMh/gxVUrZk94lDx9J8tNXPl5rPZ/eG8ok+ZYVLA14oj3927fWWmcHPH5fktkkn5De5Q/AGCilPDO90Wyn0rskGBgTpZQtSb46ydkkPzpom1rrbK31R8ylCJ1bfH/7Z0s8vnj/zStQC9Dz7iQ/k+Q5tda/GLRBKWVjel9+fCy96ec+Tv+LkMUpN76lP7fxqqR5Or5u79++Y4lmTNIbWj2X5LmllKetSFXAIIeSHOj/GWQhvRNSkjy2IhUBT6r/5u9N6V2i/239b9eB8fFFSdYl+YNa69muiwGe1P392xcs8fji/e9dgVqAJP1R4N9Ta/3Ik2z2gvTOtX/ev8J5kL9Ib9Hypyf5VyMusxnmyhxft/VvlzzB1FpnSykfTPKcJHuz9Dd9wDKqtT6c5LueZJPnpXcpxIc0aGBsfH2SlyZ5e5Lf7LgW4Ik+s3/73v6UN/8uvYVn9iQ5neQ9SX5hcaocoFP/Ob15/99SSnllel96XCqlPDW9BWe+L8mx9EbBAeNjmL7TQinlvUn+ZX/7v1uJwsaNkafj6xP7t0t1/xdNX7E9MEb6H/h+ov/jj3dZC9BTStma3ge42SSvqrUudFwS8ESf0r89kd6XHL+R3pz/e9O7Qut7k3ywlPL1nVQHXNafOuPFSY4k+b0kp0sp/5DeFHT/pX/f59daT3VXJTCAvtOQNE/H17b+7Uevst3i49uedCugK69J8qL0VvG+p+NagJ7XJ/mkJD9Ua52+2sZAJ7b0b78rvUv4X5/kmelNtbE3yVuSbEhvpNtSlwoDK2dH/im3W5I8I73Vu5PevP+rtukCY0zfaUgu258cq3biXhhXpZQvT+/D3v9N8gqj26B7pZRnJ3l1kvenNxoGGE8b+7fPSfJ1tda3Pu6xDyR5RSnlTJLvSG9F4S9c4fqAvlLK/iQ/m95I029N8jtJHknvC4//kGR/kj8rpbzUAm/QtFXbd9I8HV+Lk/puusp2iwtFnV7GWoBrVEq5LcmvpXdZ8JfVWh/puCRY9fqLRP1celfevLrWOt9xScDSLvRvH7iicfp4P5rkVUleXEqZMq84rLxSyjOT/GSS80leWGv9m8c9/KEk31NK+UCSX0ny5lLKp/dX8Aa6p+80JJftj6/FRsvOq2y3+LjGDIyJUsrO9OZ2Wp/ka2qtD3RcEtDzkvRGp91Ta7XIIoy3xQ90S2a1/8Xk3/d/3LXsFQGDfHWSG5PcfUXj9PHuTvK36a3U/byVKgy4Kn2nIRl5Or7e17997lIblFI2JnlWkkvpXb4EdKyUsiW9+U1vTvKdtda3d1wS8E++rH+7r5TyfwY8vjhX25f3H//7JF9Ra70wYFtgeS1m9Goj1B4bcjtgeTyzf/vBpTbor9b9wSSfnt5cqH++AnUBVzdM32lNks+5YvtVx8jT8fWu/u3LSilLDaH+0vRGtr2v1np2RaoCllRKuSHJryd5dpJfiPkUYdz8QXrfmH9Skj0D/tzU325T/+fPiC+aoSuL8yJ+zlIb9AcSfEr/R4u/QTcWp8v4l1fZbnHk2sllrAW4Nn+WZD7J80spS2X4c9PL7/9LbwT5quQDwZiqtf5dKeVdSW5P8r1JXvf4x0spG5L80OLmK1kb8ET9b+TekOSLk9yb5NstEAXjpdb6jiRTSz1eSnl5kl9N8j9qrS9fscKAQQ6n90Htef1FZt45YJuS3pcdh80tDp05nOQ16S3i9jO11ic0R0spL05yW5JzSd67wvUBS6i1frSUck+SV6Q3j/grHv94KeUpSX6s/+ObVvPnWyNPx9tr07sk/wdLKd9dSlmfJKWUW5L8VnqX7H8ovTlkgG69qv/nQ0m+ykI0APDPV2udS/L6/o+/VUr5hlLKjUlvxGkp5buS/FSShVwxyABYUe9M7zL8m5LcV0q5vd9wSSllQynlFUl+u7/tT7piEsbOj6a3yPE3llJ+qpTytCQppWxL8t+TvDTJqSQHuiuxe2sWFlZt47gJpZR/n+Qt/R9n07vccEd6je9jSb6g1nq0o/KAJP2pNWaSbOjfLjX6ZSG9b+xW9YkHxpWRpzBe+ld1/GKS/9i/69H0RqPenN7UVfNJXl1rfVM3FQJJUkq5Ob2pcT6rf9fZ9Fblvjm998dJ8l+TfMdqHrkGXSqlvC7JDye5q9b6A1c89tIkb0+yLslckhNJPjm9xeD+McmLa61/taIFjxkjT8dcrfXuJC9MbwGax5Lckt6cTm9I8tkapzAWHkvy/v5/TyX5tCX+LE6SD4ynv4lLCmFs1FoXaq0lyb9Nb0qcjyZ5epKHk7w5yW0ap9C9WuuJJM9L8uok705yMb3Gy6kkb01ye63VlFbQrfekNyDvPVc+0J8a57Ykv5Helx870svvLyf5rNXeOE2MPAUAAAAAGMjIUwAAAACAATRPAQAAAAAG0DwFAAAAABhA8xQAAAAAYADNUwAAAACAATRPAQAAAAAG0DwFAAAAABhA8xQAAAAAYADNUwAAAACAATRPAQAAAAAG0DwFAAAAABhA8xQAAG1NsCkAAAA7SURBVAAAYADNUwAAAACAATRPAQAAAAAG0DwFAAAAABhA8xQAAAAAYADNUwAAAACAATRPAQAAAAAG+P8jEUnWUEa9aAAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "image/png": { + "height": 98, + "width": 679 + }, + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "figure, axes = ts.plot()\n", + "figure.savefig(\"test.pdf\", bbox_inches=\"tight\", format=\"pdf\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.2" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From 0a095d298aa9ab6437938fe764cc7cd59d15b402 Mon Sep 17 00:00:00 2001 From: stringertheory Date: Wed, 8 Apr 2020 00:52:57 -0500 Subject: [PATCH 04/18] str function truncates for readability, repr function improved --- traces/timeseries.py | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/traces/timeseries.py b/traces/timeseries.py index 356b8d2..ad099fa 100644 --- a/traces/timeseries.py +++ b/traces/timeseries.py @@ -251,7 +251,43 @@ def __len__(self): return self.n_measurements() def __repr__(self): - return "\n%s\n" % pprint.pformat(self._d) + """A detailed string representation for debugging.""" + + def format_item(item): + return "{!r}: {!r}".format(*item) + + return "{name}({{{items}}})".format( + name=type(self).__name__, + items=", ".join(format_item(_) for _ in self._d.items()), + ) + + def __str__(self): + """A human-readable string representation (truncated if it gets too + long). + + """ + + def format_item(item): + return "{!s}: {!s}".format(*item) + + MAX_LENGTH = 20 + half = MAX_LENGTH // 2 + if len(self) > MAX_LENGTH: + one = ", ".join(format_item(_) for _ in self._d.items()[:half]) + two = ", ".join( + format_item(_) for _ in self._d.items()[half:-half] + ) + three = ", ".join(format_item(_) for _ in self._d.items()[-half:]) + truncate_string = "<...{} items...>".format(len(self) - MAX_LENGTH) + if len(truncate_string) < len(two): + two = truncate_string + items = ", ".join([one, two, three]) + else: + items = ", ".join(format_item(_) for _ in self._d.items()) + + return "{name}({{{items}}})".format( + name=type(self).__name__, items=items, + ) def iterintervals(self, n=2): """Iterate over groups of `n` consecutive measurement points in the @@ -434,7 +470,7 @@ def moving_average( ) # convert to datetime if the times are datetimes - full_window = window_size * 1. + full_window = window_size * 1.0 half_window = full_window / 2 if isinstance(start, datetime.date) and not isinstance( full_window, datetime.timedelta From 24791ed8906ac71b94dd0fa0013d56ca54298498 Mon Sep 17 00:00:00 2001 From: stringertheory Date: Wed, 8 Apr 2020 00:53:18 -0500 Subject: [PATCH 05/18] str function truncates for readability, repr function improved --- tests/test_methods.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/test_methods.py b/tests/test_methods.py index 711223f..29b32ca 100644 --- a/tests/test_methods.py +++ b/tests/test_methods.py @@ -377,3 +377,20 @@ def test_radd(): ) nose.tools.assert_raises(TypeError, ts3.__radd__, 1) + +def test_repr(): + import traces + import random + import datetime + + ts = traces.TimeSeries() + t = datetime.date(2000, 1, 1) + for i in range(1000): + ts[t] = i + t += datetime.timedelta(days=i) + + assert '<...' not in repr(ts) + + assert '<...' in str(ts) + + From 9cf8c870ab008bee4883ea98dd04a887a439aaad Mon Sep 17 00:00:00 2001 From: stringertheory Date: Wed, 8 Apr 2020 01:14:38 -0500 Subject: [PATCH 06/18] switching to codecov --- .circleci/config.yml | 2 +- Pipfile | 1 + Pipfile.lock | 193 ++++++++++++++++------------------- requirements/python-test.txt | 1 + 4 files changed, 92 insertions(+), 105 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1a667fa..46d33b3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -42,7 +42,7 @@ jobs: command: | . venv/bin/activate nosetests --with-coverage --cover-package=traces - coveralls + codecov pycodestyle traces/ pytest --mpl tests/test_plot.py --mpl-results-path=/tmp/artifacts - store_artifacts: diff --git a/Pipfile b/Pipfile index 2b77aa8..08ffb7f 100644 --- a/Pipfile +++ b/Pipfile @@ -27,6 +27,7 @@ matplotlib = "*" setuptools = "*" wheel = "*" twine = "*" +codecov = "*" [packages] sortedcontainers = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 1709a8e..7b09f3b 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "4f04dda9a59afb00aab87f4006bd3e016d535fdc8a745e266c2366358a5476fe" + "sha256": "bc69256b6160ead4bc240040d04bb402238c1c3b07ccf642ff4c422e6456f954" }, "pipfile-spec": 6, "requires": { @@ -107,10 +107,10 @@ }, "certifi": { "hashes": [ - "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", - "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f" + "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304", + "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519" ], - "version": "==2019.11.28" + "version": "==2020.4.5.1" }, "cffi": { "hashes": [ @@ -152,6 +152,14 @@ ], "version": "==3.0.4" }, + "codecov": { + "hashes": [ + "sha256:09fb045eb044a619cd2b9dacd7789ae8e322cb7f18196378579fd8d883e6b665", + "sha256:aeeefa3a03cac8a78e4f988e935b51a4689bb1f17f20d4e827807ee11135f845" + ], + "index": "pypi", + "version": "==2.0.22" + }, "commonmark": { "hashes": [ "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60", @@ -198,11 +206,11 @@ }, "coveralls": { "hashes": [ - "sha256:4b6bfc2a2a77b890f556bc631e35ba1ac21193c356393b66c84465c06218e135", - "sha256:67188c7ec630c5f708c31552f2bcdac4580e172219897c4136504f14b823132f" + "sha256:41bd57b60321dfd5b56e990ab3f7ed876090691c21a9e3b005e1f6e42e6ba4b9", + "sha256:d213f5edd49053d03f0db316ccabfe17725f2758147afc9a37eaca9d8e8602b5" ], "index": "pypi", - "version": "==1.11.1" + "version": "==2.0.0" }, "cprofilev": { "hashes": [ @@ -213,30 +221,28 @@ }, "cryptography": { "hashes": [ - "sha256:02079a6addc7b5140ba0825f542c0869ff4df9a69c360e339ecead5baefa843c", - "sha256:1df22371fbf2004c6f64e927668734070a8953362cd8370ddd336774d6743595", - "sha256:369d2346db5934345787451504853ad9d342d7f721ae82d098083e1f49a582ad", - "sha256:3cda1f0ed8747339bbdf71b9f38ca74c7b592f24f65cdb3ab3765e4b02871651", - "sha256:44ff04138935882fef7c686878e1c8fd80a723161ad6a98da31e14b7553170c2", - "sha256:4b1030728872c59687badcca1e225a9103440e467c17d6d1730ab3d2d64bfeff", - "sha256:58363dbd966afb4f89b3b11dfb8ff200058fbc3b947507675c19ceb46104b48d", - "sha256:6ec280fb24d27e3d97aa731e16207d58bd8ae94ef6eab97249a2afe4ba643d42", - "sha256:7270a6c29199adc1297776937a05b59720e8a782531f1f122f2eb8467f9aab4d", - "sha256:73fd30c57fa2d0a1d7a49c561c40c2f79c7d6c374cc7750e9ac7c99176f6428e", - "sha256:7f09806ed4fbea8f51585231ba742b58cbcfbfe823ea197d8c89a5e433c7e912", - "sha256:90df0cc93e1f8d2fba8365fb59a858f51a11a394d64dbf3ef844f783844cc793", - "sha256:971221ed40f058f5662a604bd1ae6e4521d84e6cad0b7b170564cc34169c8f13", - "sha256:a518c153a2b5ed6b8cc03f7ae79d5ffad7315ad4569b2d5333a13c38d64bd8d7", - "sha256:b0de590a8b0979649ebeef8bb9f54394d3a41f66c5584fff4220901739b6b2f0", - "sha256:b43f53f29816ba1db8525f006fa6f49292e9b029554b3eb56a189a70f2a40879", - "sha256:d31402aad60ed889c7e57934a03477b572a03af7794fa8fb1780f21ea8f6551f", - "sha256:de96157ec73458a7f14e3d26f17f8128c959084931e8997b9e655a39c8fde9f9", - "sha256:df6b4dca2e11865e6cfbfb708e800efb18370f5a46fd601d3755bc7f85b3a8a2", - "sha256:ecadccc7ba52193963c0475ac9f6fa28ac01e01349a2ca48509667ef41ffd2cf", - "sha256:fb81c17e0ebe3358486cd8cc3ad78adbae58af12fc2bf2bc0bb84e8090fa5ce8" + "sha256:0cacd3ef5c604b8e5f59bf2582c076c98a37fe206b31430d0cd08138aff0986e", + "sha256:192ca04a36852a994ef21df13cca4d822adbbdc9d5009c0f96f1d2929e375d4f", + "sha256:19ae795137682a9778892fb4390c07811828b173741bce91e30f899424b3934d", + "sha256:1b9b535d6b55936a79dbe4990b64bb16048f48747c76c29713fea8c50eca2acf", + "sha256:2a2ad24d43398d89f92209289f15265107928f22a8d10385f70def7a698d6a02", + "sha256:3be7a5722d5bfe69894d3f7bbed15547b17619f3a88a318aab2e37f457524164", + "sha256:49870684da168b90110bbaf86140d4681032c5e6a2461adc7afdd93be5634216", + "sha256:587f98ce27ac4547177a0c6fe0986b8736058daffe9160dcf5f1bd411b7fbaa1", + "sha256:5aca6f00b2f42546b9bdf11a69f248d1881212ce5b9e2618b04935b87f6f82a1", + "sha256:6b744039b55988519cc183149cceb573189b3e46e16ccf6f8c46798bb767c9dc", + "sha256:6b91cab3841b4c7cb70e4db1697c69f036c8bc0a253edc0baa6783154f1301e4", + "sha256:7598974f6879a338c785c513e7c5a4329fbc58b9f6b9a6305035fca5b1076552", + "sha256:7a279f33a081d436e90e91d1a7c338553c04e464de1c9302311a5e7e4b746088", + "sha256:95e1296e0157361fe2f5f0ed307fd31f94b0ca13372e3673fa95095a627636a1", + "sha256:9fc9da390e98cb6975eadf251b6e5fa088820141061bf041cd5c72deba1dc526", + "sha256:cc20316e3f5a6b582fc3b029d8dc03aabeb645acfcb7fc1d9848841a33265748", + "sha256:d1bf5a1a0d60c7f9a78e448adcb99aa101f3f9588b16708044638881be15d6bc", + "sha256:ed1d0760c7e46436ec90834d6f10477ff09475c692ed1695329d324b2c5cd547", + "sha256:ef9a55013676907df6c9d7dd943eb1770d014f68beaa7e73250fb43c759f4585" ], "index": "pypi", - "version": "==2.8" + "version": "==2.9" }, "cycler": { "hashes": [ @@ -316,45 +322,24 @@ }, "kiwisolver": { "hashes": [ - "sha256:05b5b061e09f60f56244adc885c4a7867da25ca387376b02c1efc29cc16bcd0f", - "sha256:210d8c39d01758d76c2b9a693567e1657ec661229bc32eac30761fa79b2474b0", - "sha256:26f4fbd6f5e1dabff70a9ba0d2c4bd30761086454aa30dddc5b52764ee4852b7", - "sha256:3b15d56a9cd40c52d7ab763ff0bc700edbb4e1a298dc43715ecccd605002cf11", - "sha256:3b2378ad387f49cbb328205bda569b9f87288d6bc1bf4cd683c34523a2341efe", - "sha256:400599c0fe58d21522cae0e8b22318e09d9729451b17ee61ba8e1e7c0346565c", - "sha256:47b8cb81a7d18dbaf4fed6a61c3cecdb5adec7b4ac292bddb0d016d57e8507d5", - "sha256:53eaed412477c836e1b9522c19858a8557d6e595077830146182225613b11a75", - "sha256:58e626e1f7dfbb620d08d457325a4cdac65d1809680009f46bf41eaf74ad0187", - "sha256:5a52e1b006bfa5be04fe4debbcdd2688432a9af4b207a3f429c74ad625022641", - "sha256:5c7ca4e449ac9f99b3b9d4693debb1d6d237d1542dd6a56b3305fe8a9620f883", - "sha256:682e54f0ce8f45981878756d7203fd01e188cc6c8b2c5e2cf03675390b4534d5", - "sha256:76275ee077772c8dde04fb6c5bc24b91af1bb3e7f4816fd1852f1495a64dad93", - "sha256:79bfb2f0bd7cbf9ea256612c9523367e5ec51d7cd616ae20ca2c90f575d839a2", - "sha256:7f4dd50874177d2bb060d74769210f3bce1af87a8c7cf5b37d032ebf94f0aca3", - "sha256:8944a16020c07b682df861207b7e0efcd2f46c7488619cb55f65882279119389", - "sha256:8aa7009437640beb2768bfd06da049bad0df85f47ff18426261acecd1cf00897", - "sha256:9105ce82dcc32c73eb53a04c869b6a4bc756b43e4385f76ea7943e827f529e4d", - "sha256:933df612c453928f1c6faa9236161a1d999a26cd40abf1dc5d7ebbc6dbfb8fca", - "sha256:939f36f21a8c571686eb491acfffa9c7f1ac345087281b412d63ea39ca14ec4a", - "sha256:9491578147849b93e70d7c1d23cb1229458f71fc79c51d52dce0809b2ca44eea", - "sha256:9733b7f64bd9f807832d673355f79703f81f0b3e52bfce420fc00d8cb28c6a6c", - "sha256:a02f6c3e229d0b7220bd74600e9351e18bc0c361b05f29adae0d10599ae0e326", - "sha256:a0c0a9f06872330d0dd31b45607197caab3c22777600e88031bfe66799e70bb0", - "sha256:aa716b9122307c50686356cfb47bfbc66541868078d0c801341df31dca1232a9", - "sha256:acc4df99308111585121db217681f1ce0eecb48d3a828a2f9bbf9773f4937e9e", - "sha256:b64916959e4ae0ac78af7c3e8cef4becee0c0e9694ad477b4c6b3a536de6a544", - "sha256:d22702cadb86b6fcba0e6b907d9f84a312db9cd6934ee728144ce3018e715ee1", - "sha256:d3fcf0819dc3fea58be1fd1ca390851bdb719a549850e708ed858503ff25d995", - "sha256:d52e3b1868a4e8fd18b5cb15055c76820df514e26aa84cc02f593d99fef6707f", - "sha256:db1a5d3cc4ae943d674718d6c47d2d82488ddd94b93b9e12d24aabdbfe48caee", - "sha256:e3a21a720791712ed721c7b95d433e036134de6f18c77dbe96119eaf7aa08004", - "sha256:e8bf074363ce2babeb4764d94f8e65efd22e6a7c74860a4f05a6947afc020ff2", - "sha256:f16814a4a96dc04bf1da7d53ee8d5b1d6decfc1a92a63349bb15d37b6a263dd9", - "sha256:f2b22153870ca5cf2ab9c940d7bc38e8e9089fa0f7e5856ea195e1cf4ff43d5a", - "sha256:f790f8b3dff3d53453de6a7b7ddd173d2e020fb160baff578d578065b108a05f", - "sha256:fe51b79da0062f8e9d49ed0182a626a7dc7a0cbca0328f612c6ee5e4711c81e4" - ], - "version": "==1.1.0" + "sha256:03662cbd3e6729f341a97dd2690b271e51a67a68322affab12a5b011344b973c", + "sha256:18d749f3e56c0480dccd1714230da0f328e6e4accf188dd4e6884bdd06bf02dd", + "sha256:247800260cd38160c362d211dcaf4ed0f7816afb5efe56544748b21d6ad6d17f", + "sha256:443c2320520eda0a5b930b2725b26f6175ca4453c61f739fef7a5847bd262f74", + "sha256:4eadb361baf3069f278b055e3bb53fa189cea2fd02cb2c353b7a99ebb4477ef1", + "sha256:556da0a5f60f6486ec4969abbc1dd83cf9b5c2deadc8288508e55c0f5f87d29c", + "sha256:603162139684ee56bcd57acc74035fceed7dd8d732f38c0959c8bd157f913fec", + "sha256:60a78858580761fe611d22127868f3dc9f98871e6fdf0a15cc4203ed9ba6179b", + "sha256:7cc095a4661bdd8a5742aaf7c10ea9fac142d76ff1770a0f84394038126d8fc7", + "sha256:c31bc3c8e903d60a1ea31a754c72559398d91b5929fcb329b1c3a3d3f6e72113", + "sha256:c955791d80e464da3b471ab41eb65cf5a40c15ce9b001fdc5bbc241170de58ec", + "sha256:d069ef4b20b1e6b19f790d00097a5d5d2c50871b66d10075dab78938dc2ee2cf", + "sha256:d52b989dc23cdaa92582ceb4af8d5bcc94d74b2c3e64cd6785558ec6a879793e", + "sha256:e586b28354d7b6584d8973656a7954b1c69c93f708c0c07b77884f91640b7657", + "sha256:efcf3397ae1e3c3a4a0a0636542bcad5adad3b1dd3e8e629d0b6e201347176c8", + "sha256:fccefc0d36a38c57b7bd233a9b485e2f1eb71903ca7ad7adacad6c28a56d62d2" + ], + "version": "==1.2.0" }, "livereload": { "hashes": [ @@ -508,30 +493,30 @@ }, "pillow": { "hashes": [ - "sha256:0a628977ac2e01ca96aaae247ec2bd38e729631ddf2221b4b715446fd45505be", - "sha256:4d9ed9a64095e031435af120d3c910148067087541131e82b3e8db302f4c8946", - "sha256:54ebae163e8412aff0b9df1e88adab65788f5f5b58e625dc5c7f51eaf14a6837", - "sha256:5bfef0b1cdde9f33881c913af14e43db69815c7e8df429ceda4c70a5e529210f", - "sha256:5f3546ceb08089cedb9e8ff7e3f6a7042bb5b37c2a95d392fb027c3e53a2da00", - "sha256:5f7ae9126d16194f114435ebb79cc536b5682002a4fa57fa7bb2cbcde65f2f4d", - "sha256:62a889aeb0a79e50ecf5af272e9e3c164148f4bd9636cc6bcfa182a52c8b0533", - "sha256:7406f5a9b2fd966e79e6abdaf700585a4522e98d6559ce37fc52e5c955fade0a", - "sha256:8453f914f4e5a3d828281a6628cf517832abfa13ff50679a4848926dac7c0358", - "sha256:87269cc6ce1e3dee11f23fa515e4249ae678dbbe2704598a51cee76c52e19cda", - "sha256:875358310ed7abd5320f21dd97351d62de4929b0426cdb1eaa904b64ac36b435", - "sha256:8ac6ce7ff3892e5deaab7abaec763538ffd011f74dc1801d93d3c5fc541feee2", - "sha256:91b710e3353aea6fc758cdb7136d9bbdcb26b53cefe43e2cba953ac3ee1d3313", - "sha256:9d2ba4ed13af381233e2d810ff3bab84ef9f18430a9b336ab69eaf3cd24299ff", - "sha256:a62ec5e13e227399be73303ff301f2865bf68657d15ea50b038d25fc41097317", - "sha256:ab76e5580b0ed647a8d8d2d2daee170e8e9f8aad225ede314f684e297e3643c2", - "sha256:bf4003aa538af3f4205c5fac56eacaa67a6dd81e454ffd9e9f055fff9f1bc614", - "sha256:bf598d2e37cf8edb1a2f26ed3fb255191f5232badea4003c16301cb94ac5bdd0", - "sha256:c18f70dc27cc5d236f10e7834236aff60aadc71346a5bc1f4f83a4b3abee6386", - "sha256:c5ed816632204a2fc9486d784d8e0d0ae754347aba99c811458d69fcdfd2a2f9", - "sha256:dc058b7833184970d1248135b8b0ab702e6daa833be14035179f2acb78ff5636", - "sha256:ff3797f2f16bf9d17d53257612da84dd0758db33935777149b3334c01ff68865" - ], - "version": "==7.0.0" + "sha256:04a10558320eba9137d6a78ca6fc8f4a5801f1b971152938851dc4629d903579", + "sha256:0f89ddc77cf421b8cd34ae852309501458942bf370831b4a9b406156b599a14e", + "sha256:251e5618125ec12ac800265d7048f5857a8f8f1979db9ea3e11382e159d17f68", + "sha256:291bad7097b06d648222b769bbfcd61e40d0abdfe10df686d20ede36eb8162b6", + "sha256:2f0b52a08d175f10c8ea36685115681a484c55d24d0933f9fd911e4111c04144", + "sha256:3713386d1e9e79cea1c5e6aaac042841d7eef838cc577a3ca153c8bedf570287", + "sha256:433bbc2469a2351bea53666d97bb1eb30f0d56461735be02ea6b27654569f80f", + "sha256:4510c6b33277970b1af83c987277f9a08ec2b02cc20ac0f9234e4026136bb137", + "sha256:50a10b048f4dd81c092adad99fa5f7ba941edaf2f9590510109ac2a15e706695", + "sha256:670e58d3643971f4afd79191abd21623761c2ebe61db1c2cb4797d817c4ba1a7", + "sha256:6c1924ed7dbc6ad0636907693bbbdd3fdae1d73072963e71f5644b864bb10b4d", + "sha256:721c04d3c77c38086f1f95d1cd8df87f2f9a505a780acf8575912b3206479da1", + "sha256:8d5799243050c2833c2662b824dfb16aa98e408d2092805edea4300a408490e7", + "sha256:90cd441a1638ae176eab4d8b6b94ab4ec24b212ed4c3fbee2a6e74672481d4f8", + "sha256:a5dc9f28c0239ec2742d4273bd85b2aa84655be2564db7ad1eb8f64b1efcdc4c", + "sha256:b2f3e8cc52ecd259b94ca880fea0d15f4ebc6da2cd3db515389bb878d800270f", + "sha256:b7453750cf911785009423789d2e4e5393aae9cbb8b3f471dab854b85a26cb89", + "sha256:b99b2607b6cd58396f363b448cbe71d3c35e28f03e442ab00806463439629c2c", + "sha256:cd47793f7bc9285a88c2b5551d3f16a2ddd005789614a34c5f4a598c2a162383", + "sha256:d6bf085f6f9ec6a1724c187083b37b58a8048f86036d42d21802ed5d1fae4853", + "sha256:da737ab273f4d60ae552f82ad83f7cbd0e173ca30ca20b160f708c92742ee212", + "sha256:eb84e7e5b07ff3725ab05977ac56d5eeb0c510795aeb48e8b691491be3c5745b" + ], + "version": "==7.1.1" }, "pkginfo": { "hashes": [ @@ -598,10 +583,10 @@ }, "pyparsing": { "hashes": [ - "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f", - "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec" + "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", + "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" ], - "version": "==2.4.6" + "version": "==2.4.7" }, "pytest": { "hashes": [ @@ -723,11 +708,11 @@ }, "sphinx": { "hashes": [ - "sha256:b4c750d546ab6d7e05bdff6ac24db8ae3e8b8253a3569b754e445110a0a12b66", - "sha256:fc312670b56cb54920d6cc2ced455a22a547910de10b3142276495ced49231cb" + "sha256:6a099e6faffdc3ceba99ca8c2d09982d43022245e409249375edf111caf79ed3", + "sha256:b63a0c879c4ff9a4dffcb05217fa55672ce07abdeb81e33c73303a563f8d8901" ], "index": "pypi", - "version": "==2.4.4" + "version": "==3.0.0" }, "sphinx-autobuild": { "hashes": [ @@ -818,10 +803,10 @@ }, "tqdm": { "hashes": [ - "sha256:4f882b23c492e7060f50d83af86f163b67e4cfbe35dfe12077e748c56282f438", - "sha256:f0fc945df434e5e612fb7eb93bf29e924940913590450c3760f198dd75a2cd19" + "sha256:00339634a22c10a7a22476ee946bbde2dbe48d042ded784e4d88e0236eca5d81", + "sha256:ea9e3fd6bd9a37e8783d75bfc4c1faf3c6813da6bd1c3e776488b41ec683af94" ], - "version": "==4.44.0" + "version": "==4.45.0" }, "twine": { "hashes": [ @@ -840,10 +825,10 @@ }, "virtualenv": { "hashes": [ - "sha256:4e399f48c6b71228bf79f5febd27e3bbb753d9d5905776a86667bc61ab628a25", - "sha256:9e81279f4a9d16d1c0654a127c2c86e5bca2073585341691882c1e66e31ef8a5" + "sha256:6ea131d41c477f6c4b7863948a9a54f7fa196854dbef73efbdff32b509f4d8bf", + "sha256:94f647e12d1e6ced2541b93215e51752aecbd1bbb18eb1816e2867f7532b1fe1" ], - "version": "==20.0.15" + "version": "==20.0.16" }, "watchdog": { "hashes": [ diff --git a/requirements/python-test.txt b/requirements/python-test.txt index e9f1f10..e317855 100644 --- a/requirements/python-test.txt +++ b/requirements/python-test.txt @@ -3,6 +3,7 @@ # testing pycodestyle coveralls +codecov nose pytest pytest-mpl From 2c2b4d41a68be18f0126321981bdc8b906d95f1c Mon Sep 17 00:00:00 2001 From: Nat Steinsultz Date: Mon, 4 May 2020 19:28:30 -0500 Subject: [PATCH 07/18] Initial implementation of EventSeries --- tests/test_eventseries.py | 100 ++++++++++++++++++++++++++++++++++++++ traces/__init__.py | 1 + traces/eventseries.py | 53 ++++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 tests/test_eventseries.py create mode 100644 traces/eventseries.py diff --git a/tests/test_eventseries.py b/tests/test_eventseries.py new file mode 100644 index 0000000..bcaefa6 --- /dev/null +++ b/tests/test_eventseries.py @@ -0,0 +1,100 @@ +from traces import EventSeries, TimeSeries +import pandas as pd + + +def test_init_data(): + es = EventSeries([0, 0, 6, 8.7, 10]) + + assert es[0] == 0 + assert es[1] == 0 + assert es[2] == 6 + assert es[3] == 8.7 + assert es[4] == 10 + + +def test_cumsum(): + # Test with basic timestamp data + data = ['2018-10-15T16:45:01', '2019-04-16T13:08:26', + '2019-02-22T12:05:08', '2019-04-16T13:09:06', + '2019-04-16T13:09:13', '2019-04-16T13:09:28', + '2019-04-16T13:09:29', '2019-04-16T13:10:20', + '2019-04-16T13:10:30', '2019-03-08T16:46:48', + '2019-04-16T13:09:29', '2019-04-16T13:10:20'] + es = EventSeries(pd.to_datetime(data)) + + reference = TimeSeries({pd.Timestamp('2018-10-15 16:45:01'): 1, + pd.Timestamp('2019-02-22 12:05:08'): 2, + pd.Timestamp('2019-03-08 16:46:48'): 3, + pd.Timestamp('2019-04-16 13:08:26'): 4, + pd.Timestamp('2019-04-16 13:09:06'): 5, + pd.Timestamp('2019-04-16 13:09:13'): 6, + pd.Timestamp('2019-04-16 13:09:28'): 7, + pd.Timestamp('2019-04-16 13:09:29'): 9, + pd.Timestamp('2019-04-16 13:10:20'): 11, + pd.Timestamp('2019-04-16 13:10:30'): 12}, default=0) + + assert es.cumsum() == reference + + # check default is 0 + assert es.cumsum()[pd.Timestamp('2015-01-01')] == 0 + + # Test Empty Series + es = EventSeries() + assert es.cumsum() == TimeSeries(default=0) + + +def test_events_between(): + data = ['2018-10-15T16:45:01', '2019-04-16T13:08:26', + '2019-02-22T12:05:08', '2019-04-16T13:09:06', + '2019-04-16T13:09:13', '2019-04-16T13:09:28', + '2019-04-16T13:09:29', '2019-04-16T13:10:20', + '2019-04-16T13:10:30', '2019-03-08T16:46:48', + '2019-04-16T13:09:29', '2019-04-16T13:10:20'] + es = EventSeries(pd.to_datetime(data)) + + assert es.events_between(pd.Timestamp( + '2018-01-01'), pd.Timestamp('2020-01-01')) == 12 + assert es.events_between(pd.Timestamp( + '2018-01-01'), pd.Timestamp('2019-01-01')) == 1 + assert es.events_between(pd.Timestamp( + '2020-01-01'), pd.Timestamp('2020-02-01')) == 0 + assert es.events_between(pd.Timestamp( + '2016-01-01'), pd.Timestamp('2017-02-01')) == 0 + + # Test closed boundaries on end points + # left + assert es.events_between(pd.Timestamp('2018-10-15 16:45:01'), + pd.Timestamp('2019-04-15 12:00:00')) == 3 + # right + assert es.events_between(pd.Timestamp('2019-02-28 12:00:00'), + pd.Timestamp('2019-04-16 13:10:20')) == 9 + # both + assert es.events_between(pd.Timestamp('2019-02-22 12:05:08'), + pd.Timestamp('2019-04-16 13:10:20')) == 10 + + +def test_count_active(): + es_open = EventSeries( + ['08:00', '09:00', '13:00', '07:00', '06:30', '13:00']) + es_closed = EventSeries(['08:00', '08:30', '12:00', '12:00', '12:00']) + ts = EventSeries.count_active(es_open, es_closed) + + assert ts['06:30'] == 1 + assert ts['07:00'] == 2 + assert ts['08:00'] == 2 + assert ts['12:00'] == -1 + assert ts['13:00'] == 1 + + +def test_time_lag(): + data = ['2019-02-01', '2019-02-28', + '2019-02-22', '2019-02-16', + '2019-02-26', '2019-02-16'] + es = EventSeries(pd.to_datetime(data)) + + time_lag = es.time_lag() + assert time_lag[0] == pd.Timedelta(days=15) + assert time_lag[1] == pd.Timedelta(days=0) + + # Make sure we got the right shape + assert time_lag.shape[0] == len(data)-1 diff --git a/traces/__init__.py b/traces/__init__.py index 0195f1f..ade756d 100644 --- a/traces/__init__.py +++ b/traces/__init__.py @@ -6,6 +6,7 @@ from .histogram import Histogram from .timeseries import TimeSeries from .utils import datetime_range +from .eventseries import EventSeries __author__ = 'Mike Stringer' __email__ = 'mike.stringer@datascopeanalytics.com' diff --git a/traces/eventseries.py b/traces/eventseries.py new file mode 100644 index 0000000..bce4f8a --- /dev/null +++ b/traces/eventseries.py @@ -0,0 +1,53 @@ +import sortedcontainers +import numpy as np +import collections + +from . import TimeSeries + + +class EventSeries(sortedcontainers.SortedList): + def __init__(self, data=None): + super().__init__(data) + + def cumsum(self): + ''' + Returns a TimeSeries with each unique time in the EventSeries as an index point + and with the cumulative number of events that have occured since the earliest time + in the EventSeries as the value + ''' + # Multiple events can happen at the same time so we need to hash them as counts + c = collections.Counter(self) + # Then we want to sort them and calculate the cumsum + c = sortedcontainers.SortedDict(c) + keys = c.keys() + values = np.cumsum(list(c.values())) + + return TimeSeries(zip(keys, values), default=0) + + def events_between(self, start, end): + ''' + Returns the number of events that occured between `start and `end. + Calculates on a closed interval, so start and end are included in the range + ''' + start_idx = self.bisect_left(start) + end_idx = self.bisect_right(end) + return end_idx - start_idx + + def time_lag(self): + ''' + Returns a `np.array` of inter event arrival times. + This will only work for EventSeries of a type that have a minus operation implemented. + ''' + return (np.array(self[1:]) - np.array(self[0:-1])) + + @staticmethod + def count_active(es_open, es_closed): + ''' + Calculates the running difference from two event series + `es_open` is an EventSeries that adds to the cumulative sum and + `es_closed` is an EventSeries of subtracts from it + + Returns a TimeSeries of the number of open cases at any given time, + assuming 0 open cases at the earliest time in either EventSeries + ''' + return es_open.cumsum() - es_closed.cumsum() From b78a9ecfcb19f4fdb334015958c22b402fb17a4f Mon Sep 17 00:00:00 2001 From: Nat Steinsultz Date: Tue, 5 May 2020 09:20:16 -0500 Subject: [PATCH 08/18] Formatting for pep8 --- tests/test_eventseries.py | 22 ++++++++++++---------- traces/eventseries.py | 16 +++++++++------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/tests/test_eventseries.py b/tests/test_eventseries.py index bcaefa6..10915c2 100644 --- a/tests/test_eventseries.py +++ b/tests/test_eventseries.py @@ -22,16 +22,18 @@ def test_cumsum(): '2019-04-16T13:09:29', '2019-04-16T13:10:20'] es = EventSeries(pd.to_datetime(data)) - reference = TimeSeries({pd.Timestamp('2018-10-15 16:45:01'): 1, - pd.Timestamp('2019-02-22 12:05:08'): 2, - pd.Timestamp('2019-03-08 16:46:48'): 3, - pd.Timestamp('2019-04-16 13:08:26'): 4, - pd.Timestamp('2019-04-16 13:09:06'): 5, - pd.Timestamp('2019-04-16 13:09:13'): 6, - pd.Timestamp('2019-04-16 13:09:28'): 7, - pd.Timestamp('2019-04-16 13:09:29'): 9, - pd.Timestamp('2019-04-16 13:10:20'): 11, - pd.Timestamp('2019-04-16 13:10:30'): 12}, default=0) + ref = {pd.Timestamp('2018-10-15 16:45:01'): 1, + pd.Timestamp('2019-02-22 12:05:08'): 2, + pd.Timestamp('2019-03-08 16:46:48'): 3, + pd.Timestamp('2019-04-16 13:08:26'): 4, + pd.Timestamp('2019-04-16 13:09:06'): 5, + pd.Timestamp('2019-04-16 13:09:13'): 6, + pd.Timestamp('2019-04-16 13:09:28'): 7, + pd.Timestamp('2019-04-16 13:09:29'): 9, + pd.Timestamp('2019-04-16 13:10:20'): 11, + pd.Timestamp('2019-04-16 13:10:30'): 12} + + reference = TimeSeries(ref, default=0) assert es.cumsum() == reference diff --git a/traces/eventseries.py b/traces/eventseries.py index bce4f8a..8919f12 100644 --- a/traces/eventseries.py +++ b/traces/eventseries.py @@ -11,11 +11,12 @@ def __init__(self, data=None): def cumsum(self): ''' - Returns a TimeSeries with each unique time in the EventSeries as an index point - and with the cumulative number of events that have occured since the earliest time - in the EventSeries as the value + Returns a TimeSeries with each unique time in the EventSeries as an + index point and with the cumulative number of events that have occured + since the earliest time in the EventSeries as the value ''' - # Multiple events can happen at the same time so we need to hash them as counts + # Multiple events can happen at the same time so we need to hash them + # as counts c = collections.Counter(self) # Then we want to sort them and calculate the cumsum c = sortedcontainers.SortedDict(c) @@ -27,7 +28,8 @@ def cumsum(self): def events_between(self, start, end): ''' Returns the number of events that occured between `start and `end. - Calculates on a closed interval, so start and end are included in the range + Calculates on a closed interval, so start and end are included in the + range ''' start_idx = self.bisect_left(start) end_idx = self.bisect_right(end) @@ -35,8 +37,8 @@ def events_between(self, start, end): def time_lag(self): ''' - Returns a `np.array` of inter event arrival times. - This will only work for EventSeries of a type that have a minus operation implemented. + Returns a `np.array` of inter event arrival times. This will only work + for EventSeries of a type that have a minus operation implemented. ''' return (np.array(self[1:]) - np.array(self[0:-1])) From 85a70b63982775006e509bffa4f221e567b54851 Mon Sep 17 00:00:00 2001 From: stringertheory Date: Fri, 2 Feb 2024 17:53:48 -0600 Subject: [PATCH 09/18] convert to poetry --- .editorconfig | 5 + .github/actions/setup-poetry-env/action.yml | 33 +++ .github/workflows/main.yml | 74 +++++++ .github/workflows/on-release-main.yml | 44 ++++ .github/workflows/validate-codecov-config.yml | 15 ++ .gitignore | 168 +++++++++++++++ .pre-commit-config.yaml | 22 ++ CONTRIBUTING.md | 194 +++++++++--------- Makefile | 132 +++++------- codecov.yaml | 9 + mkdocs.yml | 63 ++++-- poetry.toml | 2 + pyproject.toml | 100 +++++++++ tox.ini | 31 +-- 14 files changed, 689 insertions(+), 203 deletions(-) create mode 100644 .editorconfig create mode 100644 .github/actions/setup-poetry-env/action.yml create mode 100644 .github/workflows/main.yml create mode 100644 .github/workflows/on-release-main.yml create mode 100644 .github/workflows/validate-codecov-config.yml create mode 100644 .pre-commit-config.yaml create mode 100644 codecov.yaml create mode 100644 poetry.toml create mode 100644 pyproject.toml diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..461ca0d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,5 @@ +max_line_length = 80 + +[*.json] +indent_style = space +indent_size = 2 diff --git a/.github/actions/setup-poetry-env/action.yml b/.github/actions/setup-poetry-env/action.yml new file mode 100644 index 0000000..a7cdeb8 --- /dev/null +++ b/.github/actions/setup-poetry-env/action.yml @@ -0,0 +1,33 @@ +name: "setup-poetry-env" +description: "Composite action to setup the Python and poetry environment." + +inputs: + python-version: + required: false + description: "The python version to use" + default: "3.11" + +runs: + using: "composite" + steps: + - name: Set up python + uses: actions/setup-python@v4 + with: + python-version: ${{ inputs.python-version }} + + - name: Install Poetry + uses: snok/install-poetry@v1 + with: + virtualenvs-in-project: true + + - name: Load cached venv + id: cached-poetry-dependencies + uses: actions/cache@v3 + with: + path: .venv + key: venv-${{ runner.os }}-${{ inputs.python-version }}-${{ hashFiles('poetry.lock') }} + + - name: Install dependencies + if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' + run: poetry install --no-interaction + shell: bash diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..55e7ff8 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,74 @@ +name: Main + +on: + push: + branches: + - main + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + quality: + runs-on: ubuntu-latest + steps: + - name: Check out + uses: actions/checkout@v3 + + - uses: actions/cache@v3 + with: + path: ~/.cache/pre-commit + key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} + + - name: Set up the environment + uses: ./.github/actions/setup-poetry-env + + - name: Run checks + run: make check + + tox: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.8', '3.9', '3.10', '3.11'] + fail-fast: false + steps: + - name: Check out + uses: actions/checkout@v3 + + - name: Set up python + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Install Poetry + uses: snok/install-poetry@v1 + + - name: Load cached venv + uses: actions/cache@v3 + with: + path: .tox + key: venv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('poetry.lock') }} + + - name: Install tox + run: | + python -m pip install --upgrade pip + python -m pip install tox tox-gh-actions + + - name: Test with tox + run: tox + + - name: Upload coverage reports to Codecov with GitHub Action on Python 3.11 + uses: codecov/codecov-action@v3 + if: ${{ matrix.python-version == '3.11' }} + + check-docs: + runs-on: ubuntu-latest + steps: + - name: Check out + uses: actions/checkout@v3 + + - name: Set up the environment + uses: ./.github/actions/setup-poetry-env + + - name: Check if documentation can be built + run: poetry run mkdocs build -s diff --git a/.github/workflows/on-release-main.yml b/.github/workflows/on-release-main.yml new file mode 100644 index 0000000..c2ac8b8 --- /dev/null +++ b/.github/workflows/on-release-main.yml @@ -0,0 +1,44 @@ +name: release-main + +on: + release: + types: [published] + branches: [main] + +jobs: + + publish: + runs-on: ubuntu-latest + steps: + - name: Check out + uses: actions/checkout@v3 + + - name: Set up the environment + uses: ./.github/actions/setup-poetry-env + + - name: Export tag + id: vars + run: echo tag=${GITHUB_REF#refs/*/} >> $GITHUB_OUTPUT + + - name: Build and publish + run: | + source .venv/bin/activate + poetry version $RELEASE_VERSION + make build-and-publish + env: + PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} + RELEASE_VERSION: ${{ steps.vars.outputs.tag }} + + deploy-docs: + needs: publish + runs-on: ubuntu-latest + steps: + - name: Check out + uses: actions/checkout@v3 + + - name: Set up the environment + uses: ./.github/actions/setup-poetry-env + + - name: Deploy documentation + run: poetry run mkdocs gh-deploy --force + diff --git a/.github/workflows/validate-codecov-config.yml b/.github/workflows/validate-codecov-config.yml new file mode 100644 index 0000000..d063161 --- /dev/null +++ b/.github/workflows/validate-codecov-config.yml @@ -0,0 +1,15 @@ +name: validate-codecov-config + +on: + pull_request: + paths: [codecov.yaml] + push: + branches: [main] + +jobs: + validate-codecov-config: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + - name: Validate codecov configuration + run: curl -sSL --fail-with-body --data-binary @codecov.yaml https://codecov.io/validate diff --git a/.gitignore b/.gitignore index a9cfe88..9823e6a 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,171 @@ docs/_build # PyBuilder target/ .vscode + +docs/source + +# From https://raw.githubusercontent.com/github/gitignore/main/Python.gitignore + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# Vscode config files +.vscode/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..5e3015b --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,22 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: "v4.4.0" + hooks: + - id: check-case-conflict + - id: check-merge-conflict + - id: check-toml + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: "v0.1.6" + hooks: + - id: ruff + args: [--exit-non-zero-on-fix] + - id: ruff-format + + - repo: https://github.com/pre-commit/mirrors-prettier + rev: "v3.0.3" + hooks: + - id: prettier diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3ecd15b..b2554f0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,147 +1,149 @@ -Authors (chronological) -======================= +# Authors (chronological) -- [Mike Stringer](https://datascopeanalytics.com/team/mike-stringer/) -- [Vlad Seghete](https://datascopeanalytics.com/team/vlad-seghete/) -- [Yoke Peng - Leong](https://datascopeanalytics.com/team/yoke-peng-leong/) +- [Mike Stringer](https://datascopeanalytics.com/team/mike-stringer/) +- [Vlad Seghete](https://datascopeanalytics.com/team/vlad-seghete/) +- [Yoke Peng Leong](https://datascopeanalytics.com/team/yoke-peng-leong/) -Contributing -============ +# Design Philosophy -Contributions are welcome, and they are greatly appreciated! Every -little bit helps, and credit will always be given. You can contribute in -many ways. +- "Simplicity is better than functionality." - Pieter Hintjens +- "The API matters most, everything else is secondary." - Kenneth + Reitz -Design Philosophy ------------------ +# Contributing to `traces` -- "Simplicity is better than functionality." - Pieter Hintjens -- "The API matters most, everything else is secondary." - Kenneth - Reitz +Contributions are welcome, and they are greatly appreciated! +Every little bit helps, and credit will always be given. -Types of Contributions ----------------------- +You can contribute in many ways: -### Report Bugs +# Types of Contributions -Report bugs at . +## Report Bugs + +Report bugs at https://github.com/stringertheory/traces/issues If you are reporting a bug, please include: -- Your operating system name and version. -- Any details about your local setup that might be helpful - in troubleshooting. -- Detailed steps to reproduce the bug. +- Your operating system name and version. +- Any details about your local setup that might be helpful in troubleshooting. +- Detailed steps to reproduce the bug. -### Fix Bugs +## Fix Bugs -Look through the GitHub issues for bugs. Anything tagged with "bug" and -"help wanted" is open to whoever wants to implement it. +Look through the GitHub issues for bugs. Anything tagged with "bug" +and "help wanted" is open to whoever wants to implement a fix for it. -### Implement Features +## Implement Features Look through the GitHub issues for features. Anything tagged with "enhancement" and "help wanted" is open to whoever wants to implement it. -### Write Documentation +## Write Documentation -traces could always use more documentation, whether as part of the -official traces docs, in docstrings, or even on the web in blog posts, +Traces could always use more documentation, whether as part of the +official docs, in docstrings, or even on the web in blog posts, articles, and such. -### Submit Feedback +## Submit Feedback The best way to send feedback is to file an issue at -. +https://github.com/stringertheory/traces/issues. + +If you are proposing a new feature: + +- Explain in detail how it would work. +- Keep the scope as narrow as possible, to make it easier to implement. +- Remember that this is a volunteer-driven project, and that contributions + are welcome :) + +# Get Started! + +Ready to contribute? Here's how to set up `traces` for local development. +Please note this documentation assumes you already have `poetry` and `Git` installed and ready to go. -If you are proposing a feature: +1. Fork the `traces` repo on GitHub. -- Explain in detail how it would work. -- Keep the scope as narrow as possible, to make it easier - to implement. -- Remember that this is a volunteer-driven project, and that - contributions are welcome :) +2. Clone your fork locally: -When you are suggesting an enhancement, please include specific use -cases that demonstrate why the proposed enhancement is useful and make -sure that the proposed enhancement is aligned with the goals of the -project. +```bash +cd +git clone git@github.com:YOUR_NAME/traces.git +``` -Get Started! ------------- +3. Now we need to install the environment. Navigate into the directory -Ready to contribute? Here's how to set up `traces` for local -development. +```bash +cd traces +``` -1. Fork the `traces` repo on GitHub. -2. Clone your fork locally: +If you are using `pyenv`, select a version to use locally. (See installed versions with `pyenv versions`) - ``` {.sourceCode .bash} - $ git clone git@github.com:your_name_here/traces.git - ``` +```bash +pyenv local +``` -3. Install your local copy into a virtualenv. Assuming you have - virtualenvwrapper installed, this is how you set up your fork for - local development: +Then, install and activate the environment with: - ``` {.sourceCode .bash} - $ mkvirtualenv traces - $ cd traces/ - $ python setup.py develop - ``` +```bash +poetry install +poetry shell +``` -4. Create a branch for local development: +4. Install pre-commit to run linters/formatters at commit time: - ``` {.sourceCode .bash} - $ git checkout -b name-of-your-bugfix-or-feature - ``` +```bash +poetry run pre-commit install +``` + +5. Create a branch for local development: + +```bash +git checkout -b name-of-your-bugfix-or-feature +``` Now you can make your changes locally. -5. When you're done making changes, check that your changes pass flake8 - and the tests, including testing other Python versions with tox: +6. Don't forget to add test cases for your added functionality to the `tests` directory. - .. code:: bash +7. When you're done making changes, check that your changes pass the formatting tests. - > \$ flake8 traces tests \$ python setup.py test or py.test \$ tox +```bash +make check +``` -To get flake8 and tox, just pip install them into your virtualenv. +Now, validate that all unit tests are passing: -6. Commit your changes and push your branch to GitHub: +```bash +make test +``` - ``` {.sourceCode .bash} - $ git add . - $ git commit -m "Your detailed description of your changes." - $ git push origin name-of-your-bugfix-or-feature - ``` +9. Before raising a pull request you should also run tox. + This will run the tests across different versions of Python: -7. Submit a pull request through the GitHub website. +```bash +tox +``` -Pull Request Guidelines ------------------------ +This requires you to have multiple versions of python installed. +This step is also triggered in the CI/CD pipeline, so you could also choose to skip this step locally. -Pull requests are welcome! If the pull request is in response to an -existing Bug Report or Enhancement Request, please refer to it in the -description. Otherwise, if the pull request is a bug fix then make sure -to describe the bug just like if it were a bug report issue. If it's an -enhancement, describe the uses cases like you would when creating an -enhancement request. +10. Commit your changes and push your branch to GitHub: -Before you submit a pull request, check that it meets these guidelines: +```bash +git add . +git commit -m "Your detailed description of your changes." +git push origin name-of-your-bugfix-or-feature +``` -1. The pull request should include tests. -2. If the pull request adds functionality, the docs should be updated. - Put your new functionality into a function with a docstring, and add - the feature to the list in README.rst. -3. The pull request should work for Python 3.5-3.8. Check - and make sure - that the tests pass for all supported Python versions. +11. Submit a pull request through the GitHub website. -Tips ----- +# Pull Request Guidelines + +Before you submit a pull request, check that it meets these guidelines: -To run a subset of tests: +1. The pull request should include tests. - $ python -m unittest tests.test_traces +2. If the pull request adds functionality, the docs should be updated. + Put your new functionality into a function with a docstring, and add the feature to the list in `README.md`. diff --git a/Makefile b/Makefile index 798eec2..2a01119 100644 --- a/Makefile +++ b/Makefile @@ -1,82 +1,54 @@ -.PHONY: clean clean-test clean-pyc clean-build docs help -.DEFAULT_GOAL := help -define BROWSER_PYSCRIPT -import os, webbrowser, sys -try: - from urllib import pathname2url -except: - from urllib.request import pathname2url - -webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1]))) -endef -export BROWSER_PYSCRIPT - -define PRINT_HELP_PYSCRIPT -import re, sys - -for line in sys.stdin: - match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line) - if match: - target, help = match.groups() - print("%-20s %s" % (target, help)) -endef -export PRINT_HELP_PYSCRIPT -BROWSER := python -c "$$BROWSER_PYSCRIPT" - +.PHONY: install +install: ## Install the poetry environment and install the pre-commit hooks + @echo "🚀 Creating virtual environment using pyenv and poetry" + @poetry install + @ poetry run pre-commit install + @poetry shell + +.PHONY: check +check: ## Run code quality tools. + @echo "🚀 Checking Poetry lock file consistency with 'pyproject.toml': Running poetry lock --check" + @poetry check --lock + @echo "🚀 Linting code: Running pre-commit" + @poetry run pre-commit run -a + @echo "🚀 Static type checking: Running mypy" + @poetry run mypy + +.PHONY: test +test: ## Test the code with pytest + @echo "🚀 Testing code: Running pytest" + @poetry run pytest --cov --cov-config=pyproject.toml --cov-report=xml + +.PHONY: build +build: clean-build ## Build wheel file using poetry + @echo "🚀 Creating wheel file" + @poetry build + +.PHONY: clean-build +clean-build: ## clean build artifacts + @rm -rf dist + +.PHONY: publish +publish: ## publish a release to pypi. + @echo "🚀 Publishing: Dry run." + @poetry config pypi-token.pypi $(PYPI_TOKEN) + @poetry publish --dry-run + @echo "🚀 Publishing." + @poetry publish + +.PHONY: build-and-publish +build-and-publish: build publish ## Build and publish. + +.PHONY: docs-test +docs-test: ## Test if documentation can be built without warnings or errors + @poetry run mkdocs build -s + +.PHONY: docs +docs: ## Build and serve the documentation + @poetry run mkdocs serve + +.PHONY: help help: - @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) - -clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts - - -clean-build: ## remove build artifacts - rm -fr build/ - rm -fr dist/ - rm -fr .eggs/ - find . -name '*.egg-info' -exec rm -fr {} + - find . -name '*.egg' -exec rm -f {} + - -clean-pyc: ## remove Python file artifacts - find . -name '*.pyc' -exec rm -f {} + - find . -name '*.pyo' -exec rm -f {} + - find . -name '*~' -exec rm -f {} + - find . -name '__pycache__' -exec rm -fr {} + - -clean-test: ## remove test and coverage artifacts - rm -fr .tox/ - rm -f .coverage - rm -fr htmlcov/ + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' -lint: ## check style with flake8 - flake8 traces tests - -test: ## run tests quickly with the default Python - nosetests --with-coverage --cover-package=traces - pycodestyle traces - pytest --mpl tests/test_plot.py - -test-all: ## run tests on every Python version with tox - tox - -coverage: ## check code coverage quickly with the default Python - coverage run --source traces setup.py test - coverage report -m - coverage html - $(BROWSER) htmlcov/index.html - -docs: ## generate HTML documentation - cd docs && make html - -servedocs: ## compile the docs watching for changes - sphinx-autobuild -z traces/ docs docs/_build/html - -release: clean ## package and upload a release - python setup.py sdist bdist_wheel - twine upload dist/* - -dist: clean ## builds source and wheel package - python setup.py sdist bdist_wheel - ls -l dist - -install: clean ## install the package to the active Python's site-packages - python setup.py install +.DEFAULT_GOAL := help diff --git a/codecov.yaml b/codecov.yaml new file mode 100644 index 0000000..058cfb7 --- /dev/null +++ b/codecov.yaml @@ -0,0 +1,9 @@ +coverage: + range: 70..100 + round: down + precision: 1 + status: + project: + default: + target: 90% + threshold: 0.5% diff --git a/mkdocs.yml b/mkdocs.yml index 5ffc839..2516c95 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,15 +1,54 @@ site_name: traces -repo_url: https://github.com/datascopeanalytics/traces/tree/master -theme: readthedocs -site_description: Tools for unevenly-spaced time series data +repo_url: https://github.com/stringertheory/traces +site_url: https://stringertheory.github.io/traces +site_description: A Python library for unevenly-spaced time series analysis site_author: Mike Stringer -site_favicon: http://datascopeanalytics.com/static/main/img/favicon.ico -copyright: -extra_javascript: - - http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML +edit_uri: edit/main/docs/ +repo_name: stringertheory/traces +copyright: Maintained by Mike. + +nav: + - Home: index.md + - Modules: modules.md +plugins: + - search + - mkdocstrings: + handlers: + python: + setup_commands: + - import sys + - sys.path.append('../') +theme: + name: material + feature: + tabs: true + palette: + - media: "(prefers-color-scheme: light)" + scheme: default + primary: white + accent: deep orange + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: black + accent: deep orange + toggle: + icon: material/brightness-4 + name: Switch to light mode + icon: + repo: fontawesome/brands/github + +extra: + social: + - icon: fontawesome/brands/github + link: https://github.com/stringertheory/traces + - icon: fontawesome/brands/python + link: https://pypi.org/project/traces + markdown_extensions: - - smarty - - mdx_math -pages: -- Home: 'index.md' -- Installation: 'installation.md' + - toc: + permalink: true + - pymdownx.arithmatex: + generic: true diff --git a/poetry.toml b/poetry.toml new file mode 100644 index 0000000..ab1033b --- /dev/null +++ b/poetry.toml @@ -0,0 +1,2 @@ +[virtualenvs] +in-project = true diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..bc4dabb --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,100 @@ +[tool.poetry] +name = "traces" +version = "0.0.1" +description = "A Python library for unevenly-spaced time series analysis" +authors = ["Mike Stringer "] +repository = "https://github.com/stringertheory/traces" +documentation = "https://stringertheory.github.io/traces/" +readme = "README.md" +packages = [ + {include = "traces"} +] + +[tool.poetry.dependencies] +python = ">=3.8,<4.0" + +[tool.poetry.group.dev.dependencies] +pytest = "^7.2.0" +pytest-cov = "^4.0.0" +mypy = "^1.5.1" +pre-commit = "^3.4.0" +tox = "^4.11.1" + +[tool.poetry.group.docs.dependencies] +mkdocs = "^1.4.2" +mkdocs-material = "^9.2.7" +mkdocstrings = {extras = ["python"], version = "^0.23.0"} + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" + +[tool.mypy] +files = ["traces"] +disallow_untyped_defs = "True" +disallow_any_unimported = "True" +no_implicit_optional = "True" +check_untyped_defs = "True" +warn_return_any = "True" +warn_unused_ignores = "True" +show_error_codes = "True" + +[tool.pytest.ini_options] +testpaths = ["tests"] + +[tool.ruff] +target-version = "py37" +line-length = 120 +fix = true +select = [ + # flake8-2020 + "YTT", + # flake8-bandit + "S", + # flake8-bugbear + "B", + # flake8-builtins + "A", + # flake8-comprehensions + "C4", + # flake8-debugger + "T10", + # flake8-simplify + "SIM", + # isort + "I", + # mccabe + "C90", + # pycodestyle + "E", "W", + # pyflakes + "F", + # pygrep-hooks + "PGH", + # pyupgrade + "UP", + # ruff + "RUF", + # tryceratops + "TRY", +] +ignore = [ + # LineTooLong + "E501", + # DoNotAssignLambda + "E731", +] + +[tool.ruff.format] +preview = true + +[tool.coverage.report] +skip_empty = true + +[tool.coverage.run] +branch = true +source = ["traces"] + + +[tool.ruff.per-file-ignores] +"tests/*" = ["S101"] diff --git a/tox.ini b/tox.ini index 5630c12..0ab4522 100644 --- a/tox.ini +++ b/tox.ini @@ -1,20 +1,21 @@ [tox] -envlist = py36, py37, py38, pycodestyle skipsdist = true +envlist = py36, py37, py38, py39, py310, py311, py312 -[testenv:pycodestyle] -basepython=python -deps=pycodestyle -commands=pycodestyle traces +[gh-actions] +python = + 3.6: py36 + 3.7: py37 + 3.8: py38 + 3.9: py39 + 3.10: py310 + 3.11: py311 + 3.12: py312 [testenv] -setenv = - PYTHONPATH = {toxinidir}:{toxinidir}/traces -deps = - -r{toxinidir}/requirements/python-test.txt -commands = python setup.py test - -; If you want to make tox run the tests with the same versions, create a -; requirements.txt with the pinned versions and uncomment the following lines: -; deps = -; -r{toxinidir}/requirements.txt +passenv = PYTHON_VERSION +allowlist_externals = poetry +commands = + poetry install -v + pytest --doctest-modules tests --cov --cov-config=pyproject.toml --cov-report=xml + mypy From 56b905faf1bffc8401d7acf082223e24dafec630 Mon Sep 17 00:00:00 2001 From: stringertheory Date: Fri, 2 Feb 2024 19:01:25 -0600 Subject: [PATCH 10/18] getting dependencies updated in pyproject.toml --- .pre-commit-config.yaml | 30 +- Pipfile | 38 - Pipfile.lock | 862 ----------------- poetry.lock | 1953 +++++++++++++++++++++++++++++++++++++++ pyproject.toml | 11 +- tests/test_histogram.py | 62 +- 6 files changed, 2006 insertions(+), 950 deletions(-) delete mode 100644 Pipfile delete mode 100644 Pipfile.lock create mode 100644 poetry.lock diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5e3015b..91e1f3e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,20 +3,20 @@ repos: rev: "v4.4.0" hooks: - id: check-case-conflict - - id: check-merge-conflict - - id: check-toml - - id: check-yaml - - id: end-of-file-fixer - - id: trailing-whitespace + # - id: check-merge-conflict + # - id: check-toml + # - id: check-yaml + # - id: end-of-file-fixer + # - id: trailing-whitespace - - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.1.6" - hooks: - - id: ruff - args: [--exit-non-zero-on-fix] - - id: ruff-format + # - repo: https://github.com/astral-sh/ruff-pre-commit + # rev: "v0.1.6" + # hooks: + # - id: ruff + # args: [--exit-non-zero-on-fix] + # - id: ruff-format - - repo: https://github.com/pre-commit/mirrors-prettier - rev: "v3.0.3" - hooks: - - id: prettier + # - repo: https://github.com/pre-commit/mirrors-prettier + # rev: "v3.0.3" + # hooks: + # - id: prettier diff --git a/Pipfile b/Pipfile deleted file mode 100644 index 08ffb7f..0000000 --- a/Pipfile +++ /dev/null @@ -1,38 +0,0 @@ -[[source]] -name = "pypi" -url = "https://pypi.org/simple" -verify_ssl = true - -[dev-packages] -sphinxcontrib-napoleon = "*" -recommonmark = "*" -sphinx-autobuild = "*" -bumpversion = "*" -tox = "*" -flake8 = "*" -coverage = "*" -cryptography = "*" -Sphinx = "*" -CProfileV = "*" -PyYAML = "*" -pycodestyle = "*" -coveralls = "*" -nose = "*" -pytest = "*" -pytest-mpl = "*" -numpy = "*" -scipy = "*" -pandas = "*" -matplotlib = "*" -setuptools = "*" -wheel = "*" -twine = "*" -codecov = "*" - -[packages] -sortedcontainers = "*" -infinity = "*" -python-dateutil = "*" - -[requires] -python_version = "3.8" diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index 7b09f3b..0000000 --- a/Pipfile.lock +++ /dev/null @@ -1,862 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "bc69256b6160ead4bc240040d04bb402238c1c3b07ccf642ff4c422e6456f954" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "3.8" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "infinity": { - "hashes": [ - "sha256:dc4aa138d7e366fc00d2e741e32c78a0fecd16b74f8daeb3f7408b459668005c" - ], - "index": "pypi", - "version": "==1.4" - }, - "python-dateutil": { - "hashes": [ - "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", - "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" - ], - "index": "pypi", - "version": "==2.8.1" - }, - "six": { - "hashes": [ - "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", - "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" - ], - "version": "==1.14.0" - }, - "sortedcontainers": { - "hashes": [ - "sha256:974e9a32f56b17c1bac2aebd9dcf197f3eb9cd30553c5852a3187ad162e1a03a", - "sha256:d9e96492dd51fae31e60837736b38fe42a187b5404c16606ff7ee7cd582d4c60" - ], - "index": "pypi", - "version": "==2.1.0" - } - }, - "develop": { - "alabaster": { - "hashes": [ - "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", - "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02" - ], - "version": "==0.7.12" - }, - "appdirs": { - "hashes": [ - "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", - "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e" - ], - "version": "==1.4.3" - }, - "argh": { - "hashes": [ - "sha256:a9b3aaa1904eeb78e32394cd46c6f37ac0fb4af6dc488daa58971bdc7d7fcaf3", - "sha256:e9535b8c84dc9571a48999094fda7f33e63c3f1b74f3e5f3ac0105a58405bb65" - ], - "version": "==0.26.2" - }, - "attrs": { - "hashes": [ - "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", - "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72" - ], - "version": "==19.3.0" - }, - "babel": { - "hashes": [ - "sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38", - "sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4" - ], - "version": "==2.8.0" - }, - "bleach": { - "hashes": [ - "sha256:cc8da25076a1fe56c3ac63671e2194458e0c4d9c7becfd52ca251650d517903c", - "sha256:e78e426105ac07026ba098f04de8abe9b6e3e98b5befbf89b51a5ef0a4292b03" - ], - "version": "==3.1.4" - }, - "bottle": { - "hashes": [ - "sha256:0819b74b145a7def225c0e83b16a4d5711fde751cd92bae467a69efce720f69e", - "sha256:43157254e88f32c6be16f8d9eb1f1d1472396a4e174ebd2bf62544854ecf37e7" - ], - "version": "==0.12.18" - }, - "bumpversion": { - "hashes": [ - "sha256:6744c873dd7aafc24453d8b6a1a0d6d109faf63cd0cd19cb78fd46e74932c77e", - "sha256:6753d9ff3552013e2130f7bc03c1007e24473b4835952679653fb132367bdd57" - ], - "index": "pypi", - "version": "==0.5.3" - }, - "certifi": { - "hashes": [ - "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304", - "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519" - ], - "version": "==2020.4.5.1" - }, - "cffi": { - "hashes": [ - "sha256:001bf3242a1bb04d985d63e138230802c6c8d4db3668fb545fb5005ddf5bb5ff", - "sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b", - "sha256:028a579fc9aed3af38f4892bdcc7390508adabc30c6af4a6e4f611b0c680e6ac", - "sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0", - "sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384", - "sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26", - "sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6", - "sha256:337d448e5a725bba2d8293c48d9353fc68d0e9e4088d62a9571def317797522b", - "sha256:399aed636c7d3749bbed55bc907c3288cb43c65c4389964ad5ff849b6370603e", - "sha256:3b911c2dbd4f423b4c4fcca138cadde747abdb20d196c4a48708b8a2d32b16dd", - "sha256:3d311bcc4a41408cf5854f06ef2c5cab88f9fded37a3b95936c9879c1640d4c2", - "sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66", - "sha256:66e41db66b47d0d8672d8ed2708ba91b2f2524ece3dee48b5dfb36be8c2f21dc", - "sha256:675686925a9fb403edba0114db74e741d8181683dcf216be697d208857e04ca8", - "sha256:7e63cbcf2429a8dbfe48dcc2322d5f2220b77b2e17b7ba023d6166d84655da55", - "sha256:8a6c688fefb4e1cd56feb6c511984a6c4f7ec7d2a1ff31a10254f3c817054ae4", - "sha256:8c0ffc886aea5df6a1762d0019e9cb05f825d0eec1f520c51be9d198701daee5", - "sha256:95cd16d3dee553f882540c1ffe331d085c9e629499ceadfbda4d4fde635f4b7d", - "sha256:99f748a7e71ff382613b4e1acc0ac83bf7ad167fb3802e35e90d9763daba4d78", - "sha256:b8c78301cefcf5fd914aad35d3c04c2b21ce8629b5e4f4e45ae6812e461910fa", - "sha256:c420917b188a5582a56d8b93bdd8e0f6eca08c84ff623a4c16e809152cd35793", - "sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f", - "sha256:cab50b8c2250b46fe738c77dbd25ce017d5e6fb35d3407606e7a4180656a5a6a", - "sha256:cef128cb4d5e0b3493f058f10ce32365972c554572ff821e175dbc6f8ff6924f", - "sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30", - "sha256:e56c744aa6ff427a607763346e4170629caf7e48ead6921745986db3692f987f", - "sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3", - "sha256:f2b0fa0c01d8a0c7483afd9f31d7ecf2d71760ca24499c8697aeb5ca37dc090c" - ], - "version": "==1.14.0" - }, - "chardet": { - "hashes": [ - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" - ], - "version": "==3.0.4" - }, - "codecov": { - "hashes": [ - "sha256:09fb045eb044a619cd2b9dacd7789ae8e322cb7f18196378579fd8d883e6b665", - "sha256:aeeefa3a03cac8a78e4f988e935b51a4689bb1f17f20d4e827807ee11135f845" - ], - "index": "pypi", - "version": "==2.0.22" - }, - "commonmark": { - "hashes": [ - "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60", - "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9" - ], - "version": "==0.9.1" - }, - "coverage": { - "hashes": [ - "sha256:03f630aba2b9b0d69871c2e8d23a69b7fe94a1e2f5f10df5049c0df99db639a0", - "sha256:046a1a742e66d065d16fb564a26c2a15867f17695e7f3d358d7b1ad8a61bca30", - "sha256:0a907199566269e1cfa304325cc3b45c72ae341fbb3253ddde19fa820ded7a8b", - "sha256:165a48268bfb5a77e2d9dbb80de7ea917332a79c7adb747bd005b3a07ff8caf0", - "sha256:1b60a95fc995649464e0cd48cecc8288bac5f4198f21d04b8229dc4097d76823", - "sha256:1f66cf263ec77af5b8fe14ef14c5e46e2eb4a795ac495ad7c03adc72ae43fafe", - "sha256:2e08c32cbede4a29e2a701822291ae2bc9b5220a971bba9d1e7615312efd3037", - "sha256:3844c3dab800ca8536f75ae89f3cf566848a3eb2af4d9f7b1103b4f4f7a5dad6", - "sha256:408ce64078398b2ee2ec08199ea3fcf382828d2f8a19c5a5ba2946fe5ddc6c31", - "sha256:443be7602c790960b9514567917af538cac7807a7c0c0727c4d2bbd4014920fd", - "sha256:4482f69e0701139d0f2c44f3c395d1d1d37abd81bfafbf9b6efbe2542679d892", - "sha256:4a8a259bf990044351baf69d3b23e575699dd60b18460c71e81dc565f5819ac1", - "sha256:513e6526e0082c59a984448f4104c9bf346c2da9961779ede1fc458e8e8a1f78", - "sha256:5f587dfd83cb669933186661a351ad6fc7166273bc3e3a1531ec5c783d997aac", - "sha256:62061e87071497951155cbccee487980524d7abea647a1b2a6eb6b9647df9006", - "sha256:641e329e7f2c01531c45c687efcec8aeca2a78a4ff26d49184dce3d53fc35014", - "sha256:65a7e00c00472cd0f59ae09d2fb8a8aaae7f4a0cf54b2b74f3138d9f9ceb9cb2", - "sha256:6ad6ca45e9e92c05295f638e78cd42bfaaf8ee07878c9ed73e93190b26c125f7", - "sha256:73aa6e86034dad9f00f4bbf5a666a889d17d79db73bc5af04abd6c20a014d9c8", - "sha256:7c9762f80a25d8d0e4ab3cb1af5d9dffbddb3ee5d21c43e3474c84bf5ff941f7", - "sha256:85596aa5d9aac1bf39fe39d9fa1051b0f00823982a1de5766e35d495b4a36ca9", - "sha256:86a0ea78fd851b313b2e712266f663e13b6bc78c2fb260b079e8b67d970474b1", - "sha256:8a620767b8209f3446197c0e29ba895d75a1e272a36af0786ec70fe7834e4307", - "sha256:922fb9ef2c67c3ab20e22948dcfd783397e4c043a5c5fa5ff5e9df5529074b0a", - "sha256:9fad78c13e71546a76c2f8789623eec8e499f8d2d799f4b4547162ce0a4df435", - "sha256:a37c6233b28e5bc340054cf6170e7090a4e85069513320275a4dc929144dccf0", - "sha256:c3fc325ce4cbf902d05a80daa47b645d07e796a80682c1c5800d6ac5045193e5", - "sha256:cda33311cb9fb9323958a69499a667bd728a39a7aa4718d7622597a44c4f1441", - "sha256:db1d4e38c9b15be1521722e946ee24f6db95b189d1447fa9ff18dd16ba89f732", - "sha256:eda55e6e9ea258f5e4add23bcf33dc53b2c319e70806e180aecbff8d90ea24de", - "sha256:f372cdbb240e09ee855735b9d85e7f50730dcfb6296b74b95a3e5dea0615c4c1" - ], - "index": "pypi", - "version": "==5.0.4" - }, - "coveralls": { - "hashes": [ - "sha256:41bd57b60321dfd5b56e990ab3f7ed876090691c21a9e3b005e1f6e42e6ba4b9", - "sha256:d213f5edd49053d03f0db316ccabfe17725f2758147afc9a37eaca9d8e8602b5" - ], - "index": "pypi", - "version": "==2.0.0" - }, - "cprofilev": { - "hashes": [ - "sha256:8791748b1f3d3468c2c927c3fd5f905080b84d8f2d217ca764b7d9d7a1fb9a77" - ], - "index": "pypi", - "version": "==1.0.7" - }, - "cryptography": { - "hashes": [ - "sha256:0cacd3ef5c604b8e5f59bf2582c076c98a37fe206b31430d0cd08138aff0986e", - "sha256:192ca04a36852a994ef21df13cca4d822adbbdc9d5009c0f96f1d2929e375d4f", - "sha256:19ae795137682a9778892fb4390c07811828b173741bce91e30f899424b3934d", - "sha256:1b9b535d6b55936a79dbe4990b64bb16048f48747c76c29713fea8c50eca2acf", - "sha256:2a2ad24d43398d89f92209289f15265107928f22a8d10385f70def7a698d6a02", - "sha256:3be7a5722d5bfe69894d3f7bbed15547b17619f3a88a318aab2e37f457524164", - "sha256:49870684da168b90110bbaf86140d4681032c5e6a2461adc7afdd93be5634216", - "sha256:587f98ce27ac4547177a0c6fe0986b8736058daffe9160dcf5f1bd411b7fbaa1", - "sha256:5aca6f00b2f42546b9bdf11a69f248d1881212ce5b9e2618b04935b87f6f82a1", - "sha256:6b744039b55988519cc183149cceb573189b3e46e16ccf6f8c46798bb767c9dc", - "sha256:6b91cab3841b4c7cb70e4db1697c69f036c8bc0a253edc0baa6783154f1301e4", - "sha256:7598974f6879a338c785c513e7c5a4329fbc58b9f6b9a6305035fca5b1076552", - "sha256:7a279f33a081d436e90e91d1a7c338553c04e464de1c9302311a5e7e4b746088", - "sha256:95e1296e0157361fe2f5f0ed307fd31f94b0ca13372e3673fa95095a627636a1", - "sha256:9fc9da390e98cb6975eadf251b6e5fa088820141061bf041cd5c72deba1dc526", - "sha256:cc20316e3f5a6b582fc3b029d8dc03aabeb645acfcb7fc1d9848841a33265748", - "sha256:d1bf5a1a0d60c7f9a78e448adcb99aa101f3f9588b16708044638881be15d6bc", - "sha256:ed1d0760c7e46436ec90834d6f10477ff09475c692ed1695329d324b2c5cd547", - "sha256:ef9a55013676907df6c9d7dd943eb1770d014f68beaa7e73250fb43c759f4585" - ], - "index": "pypi", - "version": "==2.9" - }, - "cycler": { - "hashes": [ - "sha256:1d8a5ae1ff6c5cf9b93e8811e581232ad8920aeec647c37316ceac982b08cb2d", - "sha256:cd7b2d1018258d7247a71425e9f26463dfb444d411c39569972f4ce586b0c9d8" - ], - "version": "==0.10.0" - }, - "distlib": { - "hashes": [ - "sha256:2e166e231a26b36d6dfe35a48c4464346620f8645ed0ace01ee31822b288de21" - ], - "version": "==0.3.0" - }, - "docopt": { - "hashes": [ - "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491" - ], - "version": "==0.6.2" - }, - "docutils": { - "hashes": [ - "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", - "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" - ], - "version": "==0.16" - }, - "entrypoints": { - "hashes": [ - "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", - "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451" - ], - "version": "==0.3" - }, - "filelock": { - "hashes": [ - "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59", - "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836" - ], - "version": "==3.0.12" - }, - "flake8": { - "hashes": [ - "sha256:45681a117ecc81e870cbf1262835ae4af5e7a8b08e40b944a8a6e6b895914cfb", - "sha256:49356e766643ad15072a789a20915d3c91dc89fd313ccd71802303fd67e4deca" - ], - "index": "pypi", - "version": "==3.7.9" - }, - "idna": { - "hashes": [ - "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb", - "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa" - ], - "version": "==2.9" - }, - "imagesize": { - "hashes": [ - "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1", - "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1" - ], - "version": "==1.2.0" - }, - "jinja2": { - "hashes": [ - "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250", - "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49" - ], - "version": "==2.11.1" - }, - "keyring": { - "hashes": [ - "sha256:197fd5903901030ef7b82fe247f43cfed2c157a28e7747d1cfcf4bc5e699dd03", - "sha256:8179b1cdcdcbc221456b5b74e6b7cfa06f8dd9f239eb81892166d9223d82c5ba" - ], - "version": "==21.2.0" - }, - "kiwisolver": { - "hashes": [ - "sha256:03662cbd3e6729f341a97dd2690b271e51a67a68322affab12a5b011344b973c", - "sha256:18d749f3e56c0480dccd1714230da0f328e6e4accf188dd4e6884bdd06bf02dd", - "sha256:247800260cd38160c362d211dcaf4ed0f7816afb5efe56544748b21d6ad6d17f", - "sha256:443c2320520eda0a5b930b2725b26f6175ca4453c61f739fef7a5847bd262f74", - "sha256:4eadb361baf3069f278b055e3bb53fa189cea2fd02cb2c353b7a99ebb4477ef1", - "sha256:556da0a5f60f6486ec4969abbc1dd83cf9b5c2deadc8288508e55c0f5f87d29c", - "sha256:603162139684ee56bcd57acc74035fceed7dd8d732f38c0959c8bd157f913fec", - "sha256:60a78858580761fe611d22127868f3dc9f98871e6fdf0a15cc4203ed9ba6179b", - "sha256:7cc095a4661bdd8a5742aaf7c10ea9fac142d76ff1770a0f84394038126d8fc7", - "sha256:c31bc3c8e903d60a1ea31a754c72559398d91b5929fcb329b1c3a3d3f6e72113", - "sha256:c955791d80e464da3b471ab41eb65cf5a40c15ce9b001fdc5bbc241170de58ec", - "sha256:d069ef4b20b1e6b19f790d00097a5d5d2c50871b66d10075dab78938dc2ee2cf", - "sha256:d52b989dc23cdaa92582ceb4af8d5bcc94d74b2c3e64cd6785558ec6a879793e", - "sha256:e586b28354d7b6584d8973656a7954b1c69c93f708c0c07b77884f91640b7657", - "sha256:efcf3397ae1e3c3a4a0a0636542bcad5adad3b1dd3e8e629d0b6e201347176c8", - "sha256:fccefc0d36a38c57b7bd233a9b485e2f1eb71903ca7ad7adacad6c28a56d62d2" - ], - "version": "==1.2.0" - }, - "livereload": { - "hashes": [ - "sha256:78d55f2c268a8823ba499305dcac64e28ddeb9a92571e12d543cd304faf5817b", - "sha256:89254f78d7529d7ea0a3417d224c34287ebfe266b05e67e51facaf82c27f0f66" - ], - "version": "==2.6.1" - }, - "markupsafe": { - "hashes": [ - "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", - "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", - "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", - "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", - "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", - "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", - "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", - "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", - "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", - "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", - "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", - "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", - "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", - "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", - "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", - "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", - "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", - "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", - "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", - "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", - "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", - "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", - "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", - "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", - "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", - "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", - "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", - "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", - "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", - "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", - "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", - "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", - "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" - ], - "version": "==1.1.1" - }, - "matplotlib": { - "hashes": [ - "sha256:2466d4dddeb0f5666fd1e6736cc5287a4f9f7ae6c1a9e0779deff798b28e1d35", - "sha256:282b3fc8023c4365bad924d1bb442ddc565c2d1635f210b700722776da466ca3", - "sha256:4bb50ee4755271a2017b070984bcb788d483a8ce3132fab68393d1555b62d4ba", - "sha256:56d3147714da5c7ac4bc452d041e70e0e0b07c763f604110bd4e2527f320b86d", - "sha256:7a9baefad265907c6f0b037c8c35a10cf437f7708c27415a5513cf09ac6d6ddd", - "sha256:aae7d107dc37b4bb72dcc45f70394e6df2e5e92ac4079761aacd0e2ad1d3b1f7", - "sha256:af14e77829c5b5d5be11858d042d6f2459878f8e296228c7ea13ec1fd308eb68", - "sha256:c1cf735970b7cd424502719b44288b21089863aaaab099f55e0283a721aaf781", - "sha256:ce378047902b7a05546b6485b14df77b2ff207a0054e60c10b5680132090c8ee", - "sha256:d35891a86a4388b6965c2d527b9a9f9e657d9e110b0575ca8a24ba0d4e34b8fc", - "sha256:e06304686209331f99640642dee08781a9d55c6e32abb45ed54f021f46ccae47", - "sha256:e20ba7fb37d4647ac38f3c6d8672dd8b62451ee16173a0711b37ba0ce42bf37d", - "sha256:f4412241e32d0f8d3713b68d3ca6430190a5e8a7c070f1c07d7833d8c5264398", - "sha256:ffe2f9cdcea1086fc414e82f42271ecf1976700b8edd16ca9d376189c6d93aee" - ], - "index": "pypi", - "version": "==3.2.1" - }, - "mccabe": { - "hashes": [ - "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", - "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" - ], - "version": "==0.6.1" - }, - "more-itertools": { - "hashes": [ - "sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c", - "sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507" - ], - "version": "==8.2.0" - }, - "nose": { - "hashes": [ - "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac", - "sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a", - "sha256:f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98" - ], - "index": "pypi", - "version": "==1.3.7" - }, - "numpy": { - "hashes": [ - "sha256:1598a6de323508cfeed6b7cd6c4efb43324f4692e20d1f76e1feec7f59013448", - "sha256:1b0ece94018ae21163d1f651b527156e1f03943b986188dd81bc7e066eae9d1c", - "sha256:2e40be731ad618cb4974d5ba60d373cdf4f1b8dcbf1dcf4d9dff5e212baf69c5", - "sha256:4ba59db1fcc27ea31368af524dcf874d9277f21fd2e1f7f1e2e0c75ee61419ed", - "sha256:59ca9c6592da581a03d42cc4e270732552243dc45e87248aa8d636d53812f6a5", - "sha256:5e0feb76849ca3e83dd396254e47c7dba65b3fa9ed3df67c2556293ae3e16de3", - "sha256:6d205249a0293e62bbb3898c4c2e1ff8a22f98375a34775a259a0523111a8f6c", - "sha256:6fcc5a3990e269f86d388f165a089259893851437b904f422d301cdce4ff25c8", - "sha256:82847f2765835c8e5308f136bc34018d09b49037ec23ecc42b246424c767056b", - "sha256:87902e5c03355335fc5992a74ba0247a70d937f326d852fc613b7f53516c0963", - "sha256:9ab21d1cb156a620d3999dd92f7d1c86824c622873841d6b080ca5495fa10fef", - "sha256:a1baa1dc8ecd88fb2d2a651671a84b9938461e8a8eed13e2f0a812a94084d1fa", - "sha256:a244f7af80dacf21054386539699ce29bcc64796ed9850c99a34b41305630286", - "sha256:a35af656a7ba1d3decdd4fae5322b87277de8ac98b7d9da657d9e212ece76a61", - "sha256:b1fe1a6f3a6f355f6c29789b5927f8bd4f134a4bd9a781099a7c4f66af8850f5", - "sha256:b5ad0adb51b2dee7d0ee75a69e9871e2ddfb061c73ea8bc439376298141f77f5", - "sha256:ba3c7a2814ec8a176bb71f91478293d633c08582119e713a0c5351c0f77698da", - "sha256:cd77d58fb2acf57c1d1ee2835567cd70e6f1835e32090538f17f8a3a99e5e34b", - "sha256:cdb3a70285e8220875e4d2bc394e49b4988bdb1298ffa4e0bd81b2f613be397c", - "sha256:deb529c40c3f1e38d53d5ae6cd077c21f1d49e13afc7936f7f868455e16b64a0", - "sha256:e7894793e6e8540dbeac77c87b489e331947813511108ae097f1715c018b8f3d" - ], - "index": "pypi", - "version": "==1.18.2" - }, - "packaging": { - "hashes": [ - "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3", - "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752" - ], - "version": "==20.3" - }, - "pandas": { - "hashes": [ - "sha256:07c1b58936b80eafdfe694ce964ac21567b80a48d972879a359b3ebb2ea76835", - "sha256:0ebe327fb088df4d06145227a4aa0998e4f80a9e6aed4b61c1f303bdfdf7c722", - "sha256:11c7cb654cd3a0e9c54d81761b5920cdc86b373510d829461d8f2ed6d5905266", - "sha256:12f492dd840e9db1688126216706aa2d1fcd3f4df68a195f9479272d50054645", - "sha256:167a1315367cea6ec6a5e11e791d9604f8e03f95b57ad227409de35cf850c9c5", - "sha256:1a7c56f1df8d5ad8571fa251b864231f26b47b59cbe41aa5c0983d17dbb7a8e4", - "sha256:1fa4bae1a6784aa550a1c9e168422798104a85bf9c77a1063ea77ee6f8452e3a", - "sha256:32f42e322fb903d0e189a4c10b75ba70d90958cc4f66a1781ed027f1a1d14586", - "sha256:387dc7b3c0424327fe3218f81e05fc27832772a5dffbed385013161be58df90b", - "sha256:6597df07ea361231e60c00692d8a8099b519ed741c04e65821e632bc9ccb924c", - "sha256:743bba36e99d4440403beb45a6f4f3a667c090c00394c176092b0b910666189b", - "sha256:858a0d890d957ae62338624e4aeaf1de436dba2c2c0772570a686eaca8b4fc85", - "sha256:863c3e4b7ae550749a0bb77fa22e601a36df9d2905afef34a6965bed092ba9e5", - "sha256:a210c91a02ec5ff05617a298ad6f137b9f6f5771bf31f2d6b6367d7f71486639", - "sha256:ca84a44cf727f211752e91eab2d1c6c1ab0f0540d5636a8382a3af428542826e", - "sha256:d234bcf669e8b4d6cbcd99e3ce7a8918414520aeb113e2a81aeb02d0a533d7f7" - ], - "index": "pypi", - "version": "==1.0.3" - }, - "pathtools": { - "hashes": [ - "sha256:7c35c5421a39bb82e58018febd90e3b6e5db34c5443aaaf742b3f33d4655f1c0" - ], - "version": "==0.1.2" - }, - "pillow": { - "hashes": [ - "sha256:04a10558320eba9137d6a78ca6fc8f4a5801f1b971152938851dc4629d903579", - "sha256:0f89ddc77cf421b8cd34ae852309501458942bf370831b4a9b406156b599a14e", - "sha256:251e5618125ec12ac800265d7048f5857a8f8f1979db9ea3e11382e159d17f68", - "sha256:291bad7097b06d648222b769bbfcd61e40d0abdfe10df686d20ede36eb8162b6", - "sha256:2f0b52a08d175f10c8ea36685115681a484c55d24d0933f9fd911e4111c04144", - "sha256:3713386d1e9e79cea1c5e6aaac042841d7eef838cc577a3ca153c8bedf570287", - "sha256:433bbc2469a2351bea53666d97bb1eb30f0d56461735be02ea6b27654569f80f", - "sha256:4510c6b33277970b1af83c987277f9a08ec2b02cc20ac0f9234e4026136bb137", - "sha256:50a10b048f4dd81c092adad99fa5f7ba941edaf2f9590510109ac2a15e706695", - "sha256:670e58d3643971f4afd79191abd21623761c2ebe61db1c2cb4797d817c4ba1a7", - "sha256:6c1924ed7dbc6ad0636907693bbbdd3fdae1d73072963e71f5644b864bb10b4d", - "sha256:721c04d3c77c38086f1f95d1cd8df87f2f9a505a780acf8575912b3206479da1", - "sha256:8d5799243050c2833c2662b824dfb16aa98e408d2092805edea4300a408490e7", - "sha256:90cd441a1638ae176eab4d8b6b94ab4ec24b212ed4c3fbee2a6e74672481d4f8", - "sha256:a5dc9f28c0239ec2742d4273bd85b2aa84655be2564db7ad1eb8f64b1efcdc4c", - "sha256:b2f3e8cc52ecd259b94ca880fea0d15f4ebc6da2cd3db515389bb878d800270f", - "sha256:b7453750cf911785009423789d2e4e5393aae9cbb8b3f471dab854b85a26cb89", - "sha256:b99b2607b6cd58396f363b448cbe71d3c35e28f03e442ab00806463439629c2c", - "sha256:cd47793f7bc9285a88c2b5551d3f16a2ddd005789614a34c5f4a598c2a162383", - "sha256:d6bf085f6f9ec6a1724c187083b37b58a8048f86036d42d21802ed5d1fae4853", - "sha256:da737ab273f4d60ae552f82ad83f7cbd0e173ca30ca20b160f708c92742ee212", - "sha256:eb84e7e5b07ff3725ab05977ac56d5eeb0c510795aeb48e8b691491be3c5745b" - ], - "version": "==7.1.1" - }, - "pkginfo": { - "hashes": [ - "sha256:7424f2c8511c186cd5424bbf31045b77435b37a8d604990b79d4e70d741148bb", - "sha256:a6d9e40ca61ad3ebd0b72fbadd4fba16e4c0e4df0428c041e01e06eb6ee71f32" - ], - "version": "==1.5.0.1" - }, - "pluggy": { - "hashes": [ - "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", - "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" - ], - "version": "==0.13.1" - }, - "pockets": { - "hashes": [ - "sha256:68597934193c08a08eb2bf6a1d85593f627c22f9b065cc727a4f03f669d96d86", - "sha256:9320f1a3c6f7a9133fe3b571f283bcf3353cd70249025ae8d618e40e9f7e92b3" - ], - "version": "==0.9.1" - }, - "port-for": { - "hashes": [ - "sha256:b16a84bb29c2954db44c29be38b17c659c9c27e33918dec16b90d375cc596f1c" - ], - "version": "==0.3.1" - }, - "py": { - "hashes": [ - "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa", - "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0" - ], - "version": "==1.8.1" - }, - "pycodestyle": { - "hashes": [ - "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", - "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" - ], - "index": "pypi", - "version": "==2.5.0" - }, - "pycparser": { - "hashes": [ - "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", - "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705" - ], - "version": "==2.20" - }, - "pyflakes": { - "hashes": [ - "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", - "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2" - ], - "version": "==2.1.1" - }, - "pygments": { - "hashes": [ - "sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44", - "sha256:ff7a40b4860b727ab48fad6360eb351cc1b33cbf9b15a0f689ca5353e9463324" - ], - "version": "==2.6.1" - }, - "pyparsing": { - "hashes": [ - "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", - "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" - ], - "version": "==2.4.7" - }, - "pytest": { - "hashes": [ - "sha256:0e5b30f5cb04e887b91b1ee519fa3d89049595f428c1db76e73bd7f17b09b172", - "sha256:84dde37075b8805f3d1f392cc47e38a0e59518fb46a431cfdaf7cf1ce805f970" - ], - "index": "pypi", - "version": "==5.4.1" - }, - "pytest-mpl": { - "hashes": [ - "sha256:26c5a47a8fdbc04652f18b65c587da642c6cc0354680ee44b16c161d9800a2ce", - "sha256:d9b8d7cbb9848cacb6aa291c14fdf61b6f8f585c8b1d2fb16b431a7404a3a5f6" - ], - "index": "pypi", - "version": "==0.11" - }, - "python-dateutil": { - "hashes": [ - "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", - "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" - ], - "index": "pypi", - "version": "==2.8.1" - }, - "pytz": { - "hashes": [ - "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d", - "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be" - ], - "version": "==2019.3" - }, - "pyyaml": { - "hashes": [ - "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97", - "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76", - "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2", - "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648", - "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf", - "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f", - "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2", - "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee", - "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d", - "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c", - "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a" - ], - "index": "pypi", - "version": "==5.3.1" - }, - "readme-renderer": { - "hashes": [ - "sha256:1b6d8dd1673a0b293766b4106af766b6eff3654605f9c4f239e65de6076bc222", - "sha256:e67d64242f0174a63c3b727801a2fff4c1f38ebe5d71d95ff7ece081945a6cd4" - ], - "version": "==25.0" - }, - "recommonmark": { - "hashes": [ - "sha256:29cd4faeb6c5268c633634f2d69aef9431e0f4d347f90659fd0aab20e541efeb", - "sha256:2ec4207a574289355d5b6ae4ae4abb29043346ca12cdd5f07d374dc5987d2852" - ], - "index": "pypi", - "version": "==0.6.0" - }, - "requests": { - "hashes": [ - "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee", - "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6" - ], - "version": "==2.23.0" - }, - "requests-toolbelt": { - "hashes": [ - "sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f", - "sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0" - ], - "version": "==0.9.1" - }, - "scipy": { - "hashes": [ - "sha256:00af72998a46c25bdb5824d2b729e7dabec0c765f9deb0b504f928591f5ff9d4", - "sha256:0902a620a381f101e184a958459b36d3ee50f5effd186db76e131cbefcbb96f7", - "sha256:1e3190466d669d658233e8a583b854f6386dd62d655539b77b3fa25bfb2abb70", - "sha256:2cce3f9847a1a51019e8c5b47620da93950e58ebc611f13e0d11f4980ca5fecb", - "sha256:3092857f36b690a321a662fe5496cb816a7f4eecd875e1d36793d92d3f884073", - "sha256:386086e2972ed2db17cebf88610aab7d7f6e2c0ca30042dc9a89cf18dcc363fa", - "sha256:71eb180f22c49066f25d6df16f8709f215723317cc951d99e54dc88020ea57be", - "sha256:770254a280d741dd3436919d47e35712fb081a6ff8bafc0f319382b954b77802", - "sha256:787cc50cab3020a865640aba3485e9fbd161d4d3b0d03a967df1a2881320512d", - "sha256:8a07760d5c7f3a92e440ad3aedcc98891e915ce857664282ae3c0220f3301eb6", - "sha256:8d3bc3993b8e4be7eade6dcc6fd59a412d96d3a33fa42b0fa45dc9e24495ede9", - "sha256:9508a7c628a165c2c835f2497837bf6ac80eb25291055f56c129df3c943cbaf8", - "sha256:a144811318853a23d32a07bc7fd5561ff0cac5da643d96ed94a4ffe967d89672", - "sha256:a1aae70d52d0b074d8121333bc807a485f9f1e6a69742010b33780df2e60cfe0", - "sha256:a2d6df9eb074af7f08866598e4ef068a2b310d98f87dc23bd1b90ec7bdcec802", - "sha256:bb517872058a1f087c4528e7429b4a44533a902644987e7b2fe35ecc223bc408", - "sha256:c5cac0c0387272ee0e789e94a570ac51deb01c796b37fb2aad1fb13f85e2f97d", - "sha256:cc971a82ea1170e677443108703a2ec9ff0f70752258d0e9f5433d00dda01f59", - "sha256:dba8306f6da99e37ea08c08fef6e274b5bf8567bb094d1dbe86a20e532aca088", - "sha256:dc60bb302f48acf6da8ca4444cfa17d52c63c5415302a9ee77b3b21618090521", - "sha256:dee1bbf3a6c8f73b6b218cb28eed8dd13347ea2f87d572ce19b289d6fd3fbc59" - ], - "index": "pypi", - "version": "==1.4.1" - }, - "six": { - "hashes": [ - "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", - "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" - ], - "version": "==1.14.0" - }, - "snowballstemmer": { - "hashes": [ - "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0", - "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52" - ], - "version": "==2.0.0" - }, - "sphinx": { - "hashes": [ - "sha256:6a099e6faffdc3ceba99ca8c2d09982d43022245e409249375edf111caf79ed3", - "sha256:b63a0c879c4ff9a4dffcb05217fa55672ce07abdeb81e33c73303a563f8d8901" - ], - "index": "pypi", - "version": "==3.0.0" - }, - "sphinx-autobuild": { - "hashes": [ - "sha256:66388f81884666e3821edbe05dd53a0cfb68093873d17320d0610de8db28c74e", - "sha256:e60aea0789cab02fa32ee63c7acae5ef41c06f1434d9fd0a74250a61f5994692" - ], - "index": "pypi", - "version": "==0.7.1" - }, - "sphinxcontrib-applehelp": { - "hashes": [ - "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a", - "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58" - ], - "version": "==1.0.2" - }, - "sphinxcontrib-devhelp": { - "hashes": [ - "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e", - "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4" - ], - "version": "==1.0.2" - }, - "sphinxcontrib-htmlhelp": { - "hashes": [ - "sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f", - "sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b" - ], - "version": "==1.0.3" - }, - "sphinxcontrib-jsmath": { - "hashes": [ - "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", - "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8" - ], - "version": "==1.0.1" - }, - "sphinxcontrib-napoleon": { - "hashes": [ - "sha256:407382beed396e9f2d7f3043fad6afda95719204a1e1a231ac865f40abcbfcf8", - "sha256:711e41a3974bdf110a484aec4c1a556799eb0b3f3b897521a018ad7e2db13fef" - ], - "index": "pypi", - "version": "==0.7" - }, - "sphinxcontrib-qthelp": { - "hashes": [ - "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72", - "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6" - ], - "version": "==1.0.3" - }, - "sphinxcontrib-serializinghtml": { - "hashes": [ - "sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc", - "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a" - ], - "version": "==1.1.4" - }, - "toml": { - "hashes": [ - "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", - "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e" - ], - "version": "==0.10.0" - }, - "tornado": { - "hashes": [ - "sha256:0fe2d45ba43b00a41cd73f8be321a44936dc1aba233dee979f17a042b83eb6dc", - "sha256:22aed82c2ea340c3771e3babc5ef220272f6fd06b5108a53b4976d0d722bcd52", - "sha256:2c027eb2a393d964b22b5c154d1a23a5f8727db6fda837118a776b29e2b8ebc6", - "sha256:5217e601700f24e966ddab689f90b7ea4bd91ff3357c3600fa1045e26d68e55d", - "sha256:5618f72e947533832cbc3dec54e1dffc1747a5cb17d1fd91577ed14fa0dc081b", - "sha256:5f6a07e62e799be5d2330e68d808c8ac41d4a259b9cea61da4101b83cb5dc673", - "sha256:c58d56003daf1b616336781b26d184023ea4af13ae143d9dda65e31e534940b9", - "sha256:c952975c8ba74f546ae6de2e226ab3cc3cc11ae47baf607459a6728585bb542a", - "sha256:c98232a3ac391f5faea6821b53db8db461157baa788f5d6222a193e9456e1740" - ], - "version": "==6.0.4" - }, - "tox": { - "hashes": [ - "sha256:a4a6689045d93c208d77230853b28058b7513f5123647b67bf012f82fa168303", - "sha256:b2c4b91c975ea5c11463d9ca00bebf82654439c5df0f614807b9bdec62cc9471" - ], - "index": "pypi", - "version": "==3.14.6" - }, - "tqdm": { - "hashes": [ - "sha256:00339634a22c10a7a22476ee946bbde2dbe48d042ded784e4d88e0236eca5d81", - "sha256:ea9e3fd6bd9a37e8783d75bfc4c1faf3c6813da6bd1c3e776488b41ec683af94" - ], - "version": "==4.45.0" - }, - "twine": { - "hashes": [ - "sha256:c1af8ca391e43b0a06bbc155f7f67db0bf0d19d284bfc88d1675da497a946124", - "sha256:d561a5e511f70275e5a485a6275ff61851c16ffcb3a95a602189161112d9f160" - ], - "index": "pypi", - "version": "==3.1.1" - }, - "urllib3": { - "hashes": [ - "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc", - "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc" - ], - "version": "==1.25.8" - }, - "virtualenv": { - "hashes": [ - "sha256:6ea131d41c477f6c4b7863948a9a54f7fa196854dbef73efbdff32b509f4d8bf", - "sha256:94f647e12d1e6ced2541b93215e51752aecbd1bbb18eb1816e2867f7532b1fe1" - ], - "version": "==20.0.16" - }, - "watchdog": { - "hashes": [ - "sha256:c560efb643faed5ef28784b2245cf8874f939569717a4a12826a173ac644456b" - ], - "version": "==0.10.2" - }, - "wcwidth": { - "hashes": [ - "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1", - "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1" - ], - "version": "==0.1.9" - }, - "webencodings": { - "hashes": [ - "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", - "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" - ], - "version": "==0.5.1" - }, - "wheel": { - "hashes": [ - "sha256:8788e9155fe14f54164c1b9eb0a319d98ef02c160725587ad60f14ddc57b6f96", - "sha256:df277cb51e61359aba502208d680f90c0493adec6f0e848af94948778aed386e" - ], - "index": "pypi", - "version": "==0.34.2" - } - } -} diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..197d20b --- /dev/null +++ b/poetry.lock @@ -0,0 +1,1953 @@ +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. + +[[package]] +name = "babel" +version = "2.14.0" +description = "Internationalization utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "Babel-2.14.0-py3-none-any.whl", hash = "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287"}, + {file = "Babel-2.14.0.tar.gz", hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363"}, +] + +[package.extras] +dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] + +[[package]] +name = "cachetools" +version = "5.3.2" +description = "Extensible memoizing collections and decorators" +optional = false +python-versions = ">=3.7" +files = [ + {file = "cachetools-5.3.2-py3-none-any.whl", hash = "sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1"}, + {file = "cachetools-5.3.2.tar.gz", hash = "sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2"}, +] + +[[package]] +name = "certifi" +version = "2024.2.2" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, +] + +[[package]] +name = "cfgv" +version = "3.4.0" +description = "Validate configuration and produce human readable error messages." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, + {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, +] + +[[package]] +name = "chardet" +version = "5.2.0" +description = "Universal encoding detector for Python 3" +optional = false +python-versions = ">=3.7" +files = [ + {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, + {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.3.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, +] + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "contourpy" +version = "1.2.0" +description = "Python library for calculating contours of 2D quadrilateral grids" +optional = false +python-versions = ">=3.9" +files = [ + {file = "contourpy-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0274c1cb63625972c0c007ab14dd9ba9e199c36ae1a231ce45d725cbcbfd10a8"}, + {file = "contourpy-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ab459a1cbbf18e8698399c595a01f6dcc5c138220ca3ea9e7e6126232d102bb4"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fdd887f17c2f4572ce548461e4f96396681212d858cae7bd52ba3310bc6f00f"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d16edfc3fc09968e09ddffada434b3bf989bf4911535e04eada58469873e28e"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c203f617abc0dde5792beb586f827021069fb6d403d7f4d5c2b543d87edceb9"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b69303ceb2e4d4f146bf82fda78891ef7bcd80c41bf16bfca3d0d7eb545448aa"}, + {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:884c3f9d42d7218304bc74a8a7693d172685c84bd7ab2bab1ee567b769696df9"}, + {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4a1b1208102be6e851f20066bf0e7a96b7d48a07c9b0cfe6d0d4545c2f6cadab"}, + {file = "contourpy-1.2.0-cp310-cp310-win32.whl", hash = "sha256:34b9071c040d6fe45d9826cbbe3727d20d83f1b6110d219b83eb0e2a01d79488"}, + {file = "contourpy-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:bd2f1ae63998da104f16a8b788f685e55d65760cd1929518fd94cd682bf03e41"}, + {file = "contourpy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dd10c26b4eadae44783c45ad6655220426f971c61d9b239e6f7b16d5cdaaa727"}, + {file = "contourpy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5c6b28956b7b232ae801406e529ad7b350d3f09a4fde958dfdf3c0520cdde0dd"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebeac59e9e1eb4b84940d076d9f9a6cec0064e241818bcb6e32124cc5c3e377a"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:139d8d2e1c1dd52d78682f505e980f592ba53c9f73bd6be102233e358b401063"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e9dc350fb4c58adc64df3e0703ab076f60aac06e67d48b3848c23647ae4310e"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18fc2b4ed8e4a8fe849d18dce4bd3c7ea637758c6343a1f2bae1e9bd4c9f4686"}, + {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:16a7380e943a6d52472096cb7ad5264ecee36ed60888e2a3d3814991a0107286"}, + {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8d8faf05be5ec8e02a4d86f616fc2a0322ff4a4ce26c0f09d9f7fb5330a35c95"}, + {file = "contourpy-1.2.0-cp311-cp311-win32.whl", hash = "sha256:67b7f17679fa62ec82b7e3e611c43a016b887bd64fb933b3ae8638583006c6d6"}, + {file = "contourpy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:99ad97258985328b4f207a5e777c1b44a83bfe7cf1f87b99f9c11d4ee477c4de"}, + {file = "contourpy-1.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:575bcaf957a25d1194903a10bc9f316c136c19f24e0985a2b9b5608bdf5dbfe0"}, + {file = "contourpy-1.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9e6c93b5b2dbcedad20a2f18ec22cae47da0d705d454308063421a3b290d9ea4"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:464b423bc2a009088f19bdf1f232299e8b6917963e2b7e1d277da5041f33a779"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:68ce4788b7d93e47f84edd3f1f95acdcd142ae60bc0e5493bfd120683d2d4316"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d7d1f8871998cdff5d2ff6a087e5e1780139abe2838e85b0b46b7ae6cc25399"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e739530c662a8d6d42c37c2ed52a6f0932c2d4a3e8c1f90692ad0ce1274abe0"}, + {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:247b9d16535acaa766d03037d8e8fb20866d054d3c7fbf6fd1f993f11fc60ca0"}, + {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:461e3ae84cd90b30f8d533f07d87c00379644205b1d33a5ea03381edc4b69431"}, + {file = "contourpy-1.2.0-cp312-cp312-win32.whl", hash = "sha256:1c2559d6cffc94890b0529ea7eeecc20d6fadc1539273aa27faf503eb4656d8f"}, + {file = "contourpy-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:491b1917afdd8638a05b611a56d46587d5a632cabead889a5440f7c638bc6ed9"}, + {file = "contourpy-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5fd1810973a375ca0e097dee059c407913ba35723b111df75671a1976efa04bc"}, + {file = "contourpy-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:999c71939aad2780f003979b25ac5b8f2df651dac7b38fb8ce6c46ba5abe6ae9"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7caf9b241464c404613512d5594a6e2ff0cc9cb5615c9475cc1d9b514218ae8"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:266270c6f6608340f6c9836a0fb9b367be61dde0c9a9a18d5ece97774105ff3e"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbd50d0a0539ae2e96e537553aff6d02c10ed165ef40c65b0e27e744a0f10af8"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11f8d2554e52f459918f7b8e6aa20ec2a3bce35ce95c1f0ef4ba36fbda306df5"}, + {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ce96dd400486e80ac7d195b2d800b03e3e6a787e2a522bfb83755938465a819e"}, + {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6d3364b999c62f539cd403f8123ae426da946e142312a514162adb2addd8d808"}, + {file = "contourpy-1.2.0-cp39-cp39-win32.whl", hash = "sha256:1c88dfb9e0c77612febebb6ac69d44a8d81e3dc60f993215425b62c1161353f4"}, + {file = "contourpy-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:78e6ad33cf2e2e80c5dfaaa0beec3d61face0fb650557100ee36db808bfa6843"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:be16975d94c320432657ad2402f6760990cb640c161ae6da1363051805fa8108"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b95a225d4948b26a28c08307a60ac00fb8671b14f2047fc5476613252a129776"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0d7e03c0f9a4f90dc18d4e77e9ef4ec7b7bbb437f7f675be8e530d65ae6ef956"}, + {file = "contourpy-1.2.0.tar.gz", hash = "sha256:171f311cb758de7da13fc53af221ae47a5877be5a0843a9fe150818c51ed276a"}, +] + +[package.dependencies] +numpy = ">=1.20,<2.0" + +[package.extras] +bokeh = ["bokeh", "selenium"] +docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] +mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.6.1)", "types-Pillow"] +test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] +test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"] + +[[package]] +name = "coverage" +version = "7.4.1" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "coverage-7.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:077d366e724f24fc02dbfe9d946534357fda71af9764ff99d73c3c596001bbd7"}, + {file = "coverage-7.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0193657651f5399d433c92f8ae264aff31fc1d066deee4b831549526433f3f61"}, + {file = "coverage-7.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d17bbc946f52ca67adf72a5ee783cd7cd3477f8f8796f59b4974a9b59cacc9ee"}, + {file = "coverage-7.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3277f5fa7483c927fe3a7b017b39351610265308f5267ac6d4c2b64cc1d8d25"}, + {file = "coverage-7.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dceb61d40cbfcf45f51e59933c784a50846dc03211054bd76b421a713dcdf19"}, + {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6008adeca04a445ea6ef31b2cbaf1d01d02986047606f7da266629afee982630"}, + {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c61f66d93d712f6e03369b6a7769233bfda880b12f417eefdd4f16d1deb2fc4c"}, + {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b9bb62fac84d5f2ff523304e59e5c439955fb3b7f44e3d7b2085184db74d733b"}, + {file = "coverage-7.4.1-cp310-cp310-win32.whl", hash = "sha256:f86f368e1c7ce897bf2457b9eb61169a44e2ef797099fb5728482b8d69f3f016"}, + {file = "coverage-7.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:869b5046d41abfea3e381dd143407b0d29b8282a904a19cb908fa24d090cc018"}, + {file = "coverage-7.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b8ffb498a83d7e0305968289441914154fb0ef5d8b3157df02a90c6695978295"}, + {file = "coverage-7.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3cacfaefe6089d477264001f90f55b7881ba615953414999c46cc9713ff93c8c"}, + {file = "coverage-7.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d6850e6e36e332d5511a48a251790ddc545e16e8beaf046c03985c69ccb2676"}, + {file = "coverage-7.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18e961aa13b6d47f758cc5879383d27b5b3f3dcd9ce8cdbfdc2571fe86feb4dd"}, + {file = "coverage-7.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfd1e1b9f0898817babf840b77ce9fe655ecbe8b1b327983df485b30df8cc011"}, + {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6b00e21f86598b6330f0019b40fb397e705135040dbedc2ca9a93c7441178e74"}, + {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:536d609c6963c50055bab766d9951b6c394759190d03311f3e9fcf194ca909e1"}, + {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7ac8f8eb153724f84885a1374999b7e45734bf93a87d8df1e7ce2146860edef6"}, + {file = "coverage-7.4.1-cp311-cp311-win32.whl", hash = "sha256:f3771b23bb3675a06f5d885c3630b1d01ea6cac9e84a01aaf5508706dba546c5"}, + {file = "coverage-7.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:9d2f9d4cc2a53b38cabc2d6d80f7f9b7e3da26b2f53d48f05876fef7956b6968"}, + {file = "coverage-7.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f68ef3660677e6624c8cace943e4765545f8191313a07288a53d3da188bd8581"}, + {file = "coverage-7.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:23b27b8a698e749b61809fb637eb98ebf0e505710ec46a8aa6f1be7dc0dc43a6"}, + {file = "coverage-7.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e3424c554391dc9ef4a92ad28665756566a28fecf47308f91841f6c49288e66"}, + {file = "coverage-7.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0860a348bf7004c812c8368d1fc7f77fe8e4c095d661a579196a9533778e156"}, + {file = "coverage-7.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe558371c1bdf3b8fa03e097c523fb9645b8730399c14fe7721ee9c9e2a545d3"}, + {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3468cc8720402af37b6c6e7e2a9cdb9f6c16c728638a2ebc768ba1ef6f26c3a1"}, + {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:02f2edb575d62172aa28fe00efe821ae31f25dc3d589055b3fb64d51e52e4ab1"}, + {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ca6e61dc52f601d1d224526360cdeab0d0712ec104a2ce6cc5ccef6ed9a233bc"}, + {file = "coverage-7.4.1-cp312-cp312-win32.whl", hash = "sha256:ca7b26a5e456a843b9b6683eada193fc1f65c761b3a473941efe5a291f604c74"}, + {file = "coverage-7.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:85ccc5fa54c2ed64bd91ed3b4a627b9cce04646a659512a051fa82a92c04a448"}, + {file = "coverage-7.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8bdb0285a0202888d19ec6b6d23d5990410decb932b709f2b0dfe216d031d218"}, + {file = "coverage-7.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:918440dea04521f499721c039863ef95433314b1db00ff826a02580c1f503e45"}, + {file = "coverage-7.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:379d4c7abad5afbe9d88cc31ea8ca262296480a86af945b08214eb1a556a3e4d"}, + {file = "coverage-7.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b094116f0b6155e36a304ff912f89bbb5067157aff5f94060ff20bbabdc8da06"}, + {file = "coverage-7.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2f5968608b1fe2a1d00d01ad1017ee27efd99b3437e08b83ded9b7af3f6f766"}, + {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:10e88e7f41e6197ea0429ae18f21ff521d4f4490aa33048f6c6f94c6045a6a75"}, + {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a4a3907011d39dbc3e37bdc5df0a8c93853c369039b59efa33a7b6669de04c60"}, + {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6d224f0c4c9c98290a6990259073f496fcec1b5cc613eecbd22786d398ded3ad"}, + {file = "coverage-7.4.1-cp38-cp38-win32.whl", hash = "sha256:23f5881362dcb0e1a92b84b3c2809bdc90db892332daab81ad8f642d8ed55042"}, + {file = "coverage-7.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:a07f61fc452c43cd5328b392e52555f7d1952400a1ad09086c4a8addccbd138d"}, + {file = "coverage-7.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8e738a492b6221f8dcf281b67129510835461132b03024830ac0e554311a5c54"}, + {file = "coverage-7.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46342fed0fff72efcda77040b14728049200cbba1279e0bf1188f1f2078c1d70"}, + {file = "coverage-7.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9641e21670c68c7e57d2053ddf6c443e4f0a6e18e547e86af3fad0795414a628"}, + {file = "coverage-7.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aeb2c2688ed93b027eb0d26aa188ada34acb22dceea256d76390eea135083950"}, + {file = "coverage-7.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d12c923757de24e4e2110cf8832d83a886a4cf215c6e61ed506006872b43a6d1"}, + {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0491275c3b9971cdbd28a4595c2cb5838f08036bca31765bad5e17edf900b2c7"}, + {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8dfc5e195bbef80aabd81596ef52a1277ee7143fe419efc3c4d8ba2754671756"}, + {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1a78b656a4d12b0490ca72651fe4d9f5e07e3c6461063a9b6265ee45eb2bdd35"}, + {file = "coverage-7.4.1-cp39-cp39-win32.whl", hash = "sha256:f90515974b39f4dea2f27c0959688621b46d96d5a626cf9c53dbc653a895c05c"}, + {file = "coverage-7.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:64e723ca82a84053dd7bfcc986bdb34af8d9da83c521c19d6b472bc6880e191a"}, + {file = "coverage-7.4.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:32a8d985462e37cfdab611a6f95b09d7c091d07668fdc26e47a725ee575fe166"}, + {file = "coverage-7.4.1.tar.gz", hash = "sha256:1ed4b95480952b1a26d863e546fa5094564aa0065e1e5f0d4d0041f293251d04"}, +] + +[package.dependencies] +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} + +[package.extras] +toml = ["tomli"] + +[[package]] +name = "cycler" +version = "0.12.1" +description = "Composable style cycles" +optional = false +python-versions = ">=3.8" +files = [ + {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, + {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, +] + +[package.extras] +docs = ["ipython", "matplotlib", "numpydoc", "sphinx"] +tests = ["pytest", "pytest-cov", "pytest-xdist"] + +[[package]] +name = "distlib" +version = "0.3.8" +description = "Distribution utilities" +optional = false +python-versions = "*" +files = [ + {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"}, + {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.2.0" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "filelock" +version = "3.13.1" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.8" +files = [ + {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"}, + {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +typing = ["typing-extensions (>=4.8)"] + +[[package]] +name = "fonttools" +version = "4.47.2" +description = "Tools to manipulate font files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fonttools-4.47.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3b629108351d25512d4ea1a8393a2dba325b7b7d7308116b605ea3f8e1be88df"}, + {file = "fonttools-4.47.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c19044256c44fe299d9a73456aabee4b4d06c6b930287be93b533b4737d70aa1"}, + {file = "fonttools-4.47.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8be28c036b9f186e8c7eaf8a11b42373e7e4949f9e9f370202b9da4c4c3f56c"}, + {file = "fonttools-4.47.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f83a4daef6d2a202acb9bf572958f91cfde5b10c8ee7fb1d09a4c81e5d851fd8"}, + {file = "fonttools-4.47.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a5a5318ba5365d992666ac4fe35365f93004109d18858a3e18ae46f67907670"}, + {file = "fonttools-4.47.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8f57ecd742545362a0f7186774b2d1c53423ed9ece67689c93a1055b236f638c"}, + {file = "fonttools-4.47.2-cp310-cp310-win32.whl", hash = "sha256:a1c154bb85dc9a4cf145250c88d112d88eb414bad81d4cb524d06258dea1bdc0"}, + {file = "fonttools-4.47.2-cp310-cp310-win_amd64.whl", hash = "sha256:3e2b95dce2ead58fb12524d0ca7d63a63459dd489e7e5838c3cd53557f8933e1"}, + {file = "fonttools-4.47.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:29495d6d109cdbabe73cfb6f419ce67080c3ef9ea1e08d5750240fd4b0c4763b"}, + {file = "fonttools-4.47.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0a1d313a415eaaba2b35d6cd33536560deeebd2ed758b9bfb89ab5d97dc5deac"}, + {file = "fonttools-4.47.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90f898cdd67f52f18049250a6474185ef6544c91f27a7bee70d87d77a8daf89c"}, + {file = "fonttools-4.47.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3480eeb52770ff75140fe7d9a2ec33fb67b07efea0ab5129c7e0c6a639c40c70"}, + {file = "fonttools-4.47.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0255dbc128fee75fb9be364806b940ed450dd6838672a150d501ee86523ac61e"}, + {file = "fonttools-4.47.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f791446ff297fd5f1e2247c188de53c1bfb9dd7f0549eba55b73a3c2087a2703"}, + {file = "fonttools-4.47.2-cp311-cp311-win32.whl", hash = "sha256:740947906590a878a4bde7dd748e85fefa4d470a268b964748403b3ab2aeed6c"}, + {file = "fonttools-4.47.2-cp311-cp311-win_amd64.whl", hash = "sha256:63fbed184979f09a65aa9c88b395ca539c94287ba3a364517698462e13e457c9"}, + {file = "fonttools-4.47.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4ec558c543609e71b2275c4894e93493f65d2f41c15fe1d089080c1d0bb4d635"}, + {file = "fonttools-4.47.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e040f905d542362e07e72e03612a6270c33d38281fd573160e1003e43718d68d"}, + {file = "fonttools-4.47.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6dd58cc03016b281bd2c74c84cdaa6bd3ce54c5a7f47478b7657b930ac3ed8eb"}, + {file = "fonttools-4.47.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32ab2e9702dff0dd4510c7bb958f265a8d3dd5c0e2547e7b5f7a3df4979abb07"}, + {file = "fonttools-4.47.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3a808f3c1d1df1f5bf39be869b6e0c263570cdafb5bdb2df66087733f566ea71"}, + {file = "fonttools-4.47.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ac71e2e201df041a2891067dc36256755b1229ae167edbdc419b16da78732c2f"}, + {file = "fonttools-4.47.2-cp312-cp312-win32.whl", hash = "sha256:69731e8bea0578b3c28fdb43dbf95b9386e2d49a399e9a4ad736b8e479b08085"}, + {file = "fonttools-4.47.2-cp312-cp312-win_amd64.whl", hash = "sha256:b3e1304e5f19ca861d86a72218ecce68f391646d85c851742d265787f55457a4"}, + {file = "fonttools-4.47.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:254d9a6f7be00212bf0c3159e0a420eb19c63793b2c05e049eb337f3023c5ecc"}, + {file = "fonttools-4.47.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eabae77a07c41ae0b35184894202305c3ad211a93b2eb53837c2a1143c8bc952"}, + {file = "fonttools-4.47.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a86a5ab2873ed2575d0fcdf1828143cfc6b977ac448e3dc616bb1e3d20efbafa"}, + {file = "fonttools-4.47.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13819db8445a0cec8c3ff5f243af6418ab19175072a9a92f6cc8ca7d1452754b"}, + {file = "fonttools-4.47.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4e743935139aa485fe3253fc33fe467eab6ea42583fa681223ea3f1a93dd01e6"}, + {file = "fonttools-4.47.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d49ce3ea7b7173faebc5664872243b40cf88814ca3eb135c4a3cdff66af71946"}, + {file = "fonttools-4.47.2-cp38-cp38-win32.whl", hash = "sha256:94208ea750e3f96e267f394d5588579bb64cc628e321dbb1d4243ffbc291b18b"}, + {file = "fonttools-4.47.2-cp38-cp38-win_amd64.whl", hash = "sha256:0f750037e02beb8b3569fbff701a572e62a685d2a0e840d75816592280e5feae"}, + {file = "fonttools-4.47.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3d71606c9321f6701642bd4746f99b6089e53d7e9817fc6b964e90d9c5f0ecc6"}, + {file = "fonttools-4.47.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:86e0427864c6c91cf77f16d1fb9bf1bbf7453e824589e8fb8461b6ee1144f506"}, + {file = "fonttools-4.47.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a00bd0e68e88987dcc047ea31c26d40a3c61185153b03457956a87e39d43c37"}, + {file = "fonttools-4.47.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5d77479fb885ef38a16a253a2f4096bc3d14e63a56d6246bfdb56365a12b20c"}, + {file = "fonttools-4.47.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5465df494f20a7d01712b072ae3ee9ad2887004701b95cb2cc6dcb9c2c97a899"}, + {file = "fonttools-4.47.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4c811d3c73b6abac275babb8aa439206288f56fdb2c6f8835e3d7b70de8937a7"}, + {file = "fonttools-4.47.2-cp39-cp39-win32.whl", hash = "sha256:5b60e3afa9635e3dfd3ace2757039593e3bd3cf128be0ddb7a1ff4ac45fa5a50"}, + {file = "fonttools-4.47.2-cp39-cp39-win_amd64.whl", hash = "sha256:7ee48bd9d6b7e8f66866c9090807e3a4a56cf43ffad48962725a190e0dd774c8"}, + {file = "fonttools-4.47.2-py3-none-any.whl", hash = "sha256:7eb7ad665258fba68fd22228a09f347469d95a97fb88198e133595947a20a184"}, + {file = "fonttools-4.47.2.tar.gz", hash = "sha256:7df26dd3650e98ca45f1e29883c96a0b9f5bb6af8d632a6a108bc744fa0bd9b3"}, +] + +[package.extras] +all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "pycairo", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0)", "xattr", "zopfli (>=0.1.4)"] +graphite = ["lz4 (>=1.7.4.2)"] +interpolatable = ["munkres", "pycairo", "scipy"] +lxml = ["lxml (>=4.0,<5)"] +pathops = ["skia-pathops (>=0.5.0)"] +plot = ["matplotlib"] +repacker = ["uharfbuzz (>=0.23.0)"] +symfont = ["sympy"] +type1 = ["xattr"] +ufo = ["fs (>=2.2.0,<3)"] +unicode = ["unicodedata2 (>=15.1.0)"] +woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] + +[[package]] +name = "ghp-import" +version = "2.1.0" +description = "Copy your docs directly to the gh-pages branch." +optional = false +python-versions = "*" +files = [ + {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"}, + {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"}, +] + +[package.dependencies] +python-dateutil = ">=2.8.1" + +[package.extras] +dev = ["flake8", "markdown", "twine", "wheel"] + +[[package]] +name = "griffe" +version = "0.40.0" +description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." +optional = false +python-versions = ">=3.8" +files = [ + {file = "griffe-0.40.0-py3-none-any.whl", hash = "sha256:db1da6d1d8e08cbb20f1a7dee8c09da940540c2d4c1bfa26a9091cf6fc36a9ec"}, + {file = "griffe-0.40.0.tar.gz", hash = "sha256:76c4439eaa2737af46ae003c331ab6ca79c5365b552f7b5aed263a3b4125735b"}, +] + +[package.dependencies] +colorama = ">=0.4" + +[[package]] +name = "identify" +version = "2.5.33" +description = "File identification library for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "identify-2.5.33-py2.py3-none-any.whl", hash = "sha256:d40ce5fcd762817627670da8a7d8d8e65f24342d14539c59488dc603bf662e34"}, + {file = "identify-2.5.33.tar.gz", hash = "sha256:161558f9fe4559e1557e1bff323e8631f6a0e4837f7497767c1782832f16b62d"}, +] + +[package.extras] +license = ["ukkonen"] + +[[package]] +name = "idna" +version = "3.6" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, + {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, +] + +[[package]] +name = "importlib-metadata" +version = "7.0.1" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-7.0.1-py3-none-any.whl", hash = "sha256:4805911c3a4ec7c3966410053e9ec6a1fecd629117df5adee56dfc9432a1081e"}, + {file = "importlib_metadata-7.0.1.tar.gz", hash = "sha256:f238736bb06590ae52ac1fab06a3a9ef1d8dce2b7a35b5ab329371d6c8f5d2cc"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] + +[[package]] +name = "importlib-resources" +version = "6.1.1" +description = "Read resources from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_resources-6.1.1-py3-none-any.whl", hash = "sha256:e8bf90d8213b486f428c9c39714b920041cb02c184686a3dee24905aaa8105d6"}, + {file = "importlib_resources-6.1.1.tar.gz", hash = "sha256:3893a00122eafde6894c59914446a512f728a0c1a45f9bb9b63721b6bacf0b4a"}, +] + +[package.dependencies] +zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff", "zipp (>=3.17)"] + +[[package]] +name = "infinity" +version = "1.5" +description = "All-in-one infinity value for Python. Can be compared to any object." +optional = false +python-versions = "*" +files = [ + {file = "infinity-1.5.tar.gz", hash = "sha256:8daa7c15ce2100fdccfde212337e0cd5cf085869f54dc2634b6c30d61461ecda"}, +] + +[package.extras] +test = ["Pygments (>=1.2)", "flake8 (>=2.4.0)", "isort (>=4.2.2)", "pytest (>=2.2.3)", "six (>=1.4.1)"] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "jinja2" +version = "3.1.3" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, + {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "kiwisolver" +version = "1.4.5" +description = "A fast implementation of the Cassowary constraint solver" +optional = false +python-versions = ">=3.7" +files = [ + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win32.whl", hash = "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win_amd64.whl", hash = "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win32.whl", hash = "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win32.whl", hash = "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win_amd64.whl", hash = "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3a2b053a0ab7a3960c98725cfb0bf5b48ba82f64ec95fe06f1d06c99b552e130"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cd32d6c13807e5c66a7cbb79f90b553642f296ae4518a60d8d76243b0ad2898"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59ec7b7c7e1a61061850d53aaf8e93db63dce0c936db1fda2658b70e4a1be709"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da4cfb373035def307905d05041c1d06d8936452fe89d464743ae7fb8371078b"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2400873bccc260b6ae184b2b8a4fec0e4082d30648eadb7c3d9a13405d861e89"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1b04139c4236a0f3aff534479b58f6f849a8b351e1314826c2d230849ed48985"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:4e66e81a5779b65ac21764c295087de82235597a2293d18d943f8e9e32746265"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7931d8f1f67c4be9ba1dd9c451fb0eeca1a25b89e4d3f89e828fe12a519b782a"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b3f7e75f3015df442238cca659f8baa5f42ce2a8582727981cbfa15fee0ee205"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:bbf1d63eef84b2e8c89011b7f2235b1e0bf7dacc11cac9431fc6468e99ac77fb"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4c380469bd3f970ef677bf2bcba2b6b0b4d5c75e7a020fb863ef75084efad66f"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win32.whl", hash = "sha256:9408acf3270c4b6baad483865191e3e582b638b1654a007c62e3efe96f09a9a3"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win_amd64.whl", hash = "sha256:5b94529f9b2591b7af5f3e0e730a4e0a41ea174af35a4fd067775f9bdfeee01a"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:11c7de8f692fc99816e8ac50d1d1aef4f75126eefc33ac79aac02c099fd3db71"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:53abb58632235cd154176ced1ae8f0d29a6657aa1aa9decf50b899b755bc2b93"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:88b9f257ca61b838b6f8094a62418421f87ac2a1069f7e896c36a7d86b5d4c29"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3195782b26fc03aa9c6913d5bad5aeb864bdc372924c093b0f1cebad603dd712"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc579bf0f502e54926519451b920e875f433aceb4624a3646b3252b5caa9e0b6"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a580c91d686376f0f7c295357595c5a026e6cbc3d77b7c36e290201e7c11ecb"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cfe6ab8da05c01ba6fbea630377b5da2cd9bcbc6338510116b01c1bc939a2c18"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d2e5a98f0ec99beb3c10e13b387f8db39106d53993f498b295f0c914328b1333"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a51a263952b1429e429ff236d2f5a21c5125437861baeed77f5e1cc2d2c7c6da"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3edd2fa14e68c9be82c5b16689e8d63d89fe927e56debd6e1dbce7a26a17f81b"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:74d1b44c6cfc897df648cc9fdaa09bc3e7679926e6f96df05775d4fb3946571c"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:76d9289ed3f7501012e05abb8358bbb129149dbd173f1f57a1bf1c22d19ab7cc"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:92dea1ffe3714fa8eb6a314d2b3c773208d865a0e0d35e713ec54eea08a66250"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win32.whl", hash = "sha256:5c90ae8c8d32e472be041e76f9d2f2dbff4d0b0be8bd4041770eddb18cf49a4e"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win_amd64.whl", hash = "sha256:c7940c1dc63eb37a67721b10d703247552416f719c4188c54e04334321351ced"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9407b6a5f0d675e8a827ad8742e1d6b49d9c1a1da5d952a67d50ef5f4170b18d"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15568384086b6df3c65353820a4473575dbad192e35010f622c6ce3eebd57af9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0dc9db8e79f0036e8173c466d21ef18e1befc02de8bf8aa8dc0813a6dc8a7046"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cdc8a402aaee9a798b50d8b827d7ecf75edc5fb35ea0f91f213ff927c15f4ff0"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6c3bd3cde54cafb87d74d8db50b909705c62b17c2099b8f2e25b461882e544ff"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:955e8513d07a283056b1396e9a57ceddbd272d9252c14f154d450d227606eb54"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:346f5343b9e3f00b8db8ba359350eb124b98c99efd0b408728ac6ebf38173958"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9098e0049e88c6a24ff64545cdfc50807818ba6c1b739cae221bbbcbc58aad3"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:00bd361b903dc4bbf4eb165f24d1acbee754fce22ded24c3d56eec268658a5cf"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7b8b454bac16428b22560d0a1cf0a09875339cab69df61d7805bf48919415901"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f1d072c2eb0ad60d4c183f3fb44ac6f73fb7a8f16a2694a91f988275cbf352f9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:31a82d498054cac9f6d0b53d02bb85811185bcb477d4b60144f915f3b3126342"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6512cb89e334e4700febbffaaa52761b65b4f5a3cf33f960213d5656cea36a77"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win32.whl", hash = "sha256:9db8ea4c388fdb0f780fe91346fd438657ea602d58348753d9fb265ce1bca67f"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win_amd64.whl", hash = "sha256:59415f46a37f7f2efeec758353dd2eae1b07640d8ca0f0c42548ec4125492635"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5c7b3b3a728dc6faf3fc372ef24f21d1e3cee2ac3e9596691d746e5a536de920"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:620ced262a86244e2be10a676b646f29c34537d0d9cc8eb26c08f53d98013390"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:378a214a1e3bbf5ac4a8708304318b4f890da88c9e6a07699c4ae7174c09a68d"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf7be1207676ac608a50cd08f102f6742dbfc70e8d60c4db1c6897f62f71523"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ba55dce0a9b8ff59495ddd050a0225d58bd0983d09f87cfe2b6aec4f2c1234e4"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd32ea360bcbb92d28933fc05ed09bffcb1704ba3fc7942e81db0fd4f81a7892"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5e7139af55d1688f8b960ee9ad5adafc4ac17c1c473fe07133ac092310d76544"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dced8146011d2bc2e883f9bd68618b8247387f4bbec46d7392b3c3b032640126"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9bf3325c47b11b2e51bca0824ea217c7cd84491d8ac4eefd1e409705ef092bd"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5794cf59533bc3f1b1c821f7206a3617999db9fbefc345360aafe2e067514929"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e368f200bbc2e4f905b8e71eb38b3c04333bddaa6a2464a6355487b02bb7fb09"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5d706eba36b4c4d5bc6c6377bb6568098765e990cfc21ee16d13963fab7b3e7"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85267bd1aa8880a9c88a8cb71e18d3d64d2751a790e6ca6c27b8ccc724bcd5ad"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210ef2c3a1f03272649aff1ef992df2e724748918c4bc2d5a90352849eb40bea"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11d011a7574eb3b82bcc9c1a1d35c1d7075677fdd15de527d91b46bd35e935ee"}, + {file = "kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec"}, +] + +[[package]] +name = "markdown" +version = "3.5.2" +description = "Python implementation of John Gruber's Markdown." +optional = false +python-versions = ">=3.8" +files = [ + {file = "Markdown-3.5.2-py3-none-any.whl", hash = "sha256:d43323865d89fc0cb9b20c75fc8ad313af307cc087e84b657d9eec768eddeadd"}, + {file = "Markdown-3.5.2.tar.gz", hash = "sha256:e1ac7b3dc550ee80e602e71c1d168002f062e49f1b11e26a36264dafd4df2ef8"}, +] + +[package.dependencies] +importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} + +[package.extras] +docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] +testing = ["coverage", "pyyaml"] + +[[package]] +name = "markupsafe" +version = "2.1.5" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, +] + +[[package]] +name = "matplotlib" +version = "3.8.2" +description = "Python plotting package" +optional = false +python-versions = ">=3.9" +files = [ + {file = "matplotlib-3.8.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:09796f89fb71a0c0e1e2f4bdaf63fb2cefc84446bb963ecdeb40dfee7dfa98c7"}, + {file = "matplotlib-3.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6f9c6976748a25e8b9be51ea028df49b8e561eed7809146da7a47dbecebab367"}, + {file = "matplotlib-3.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b78e4f2cedf303869b782071b55fdde5987fda3038e9d09e58c91cc261b5ad18"}, + {file = "matplotlib-3.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e208f46cf6576a7624195aa047cb344a7f802e113bb1a06cfd4bee431de5e31"}, + {file = "matplotlib-3.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:46a569130ff53798ea5f50afce7406e91fdc471ca1e0e26ba976a8c734c9427a"}, + {file = "matplotlib-3.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:830f00640c965c5b7f6bc32f0d4ce0c36dfe0379f7dd65b07a00c801713ec40a"}, + {file = "matplotlib-3.8.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d86593ccf546223eb75a39b44c32788e6f6440d13cfc4750c1c15d0fcb850b63"}, + {file = "matplotlib-3.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9a5430836811b7652991939012f43d2808a2db9b64ee240387e8c43e2e5578c8"}, + {file = "matplotlib-3.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9576723858a78751d5aacd2497b8aef29ffea6d1c95981505877f7ac28215c6"}, + {file = "matplotlib-3.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ba9cbd8ac6cf422f3102622b20f8552d601bf8837e49a3afed188d560152788"}, + {file = "matplotlib-3.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:03f9d160a29e0b65c0790bb07f4f45d6a181b1ac33eb1bb0dd225986450148f0"}, + {file = "matplotlib-3.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:3773002da767f0a9323ba1a9b9b5d00d6257dbd2a93107233167cfb581f64717"}, + {file = "matplotlib-3.8.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:4c318c1e95e2f5926fba326f68177dee364aa791d6df022ceb91b8221bd0a627"}, + {file = "matplotlib-3.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:091275d18d942cf1ee9609c830a1bc36610607d8223b1b981c37d5c9fc3e46a4"}, + {file = "matplotlib-3.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b0f3b8ea0e99e233a4bcc44590f01604840d833c280ebb8fe5554fd3e6cfe8d"}, + {file = "matplotlib-3.8.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7b1704a530395aaf73912be741c04d181f82ca78084fbd80bc737be04848331"}, + {file = "matplotlib-3.8.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:533b0e3b0c6768eef8cbe4b583731ce25a91ab54a22f830db2b031e83cca9213"}, + {file = "matplotlib-3.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:0f4fc5d72b75e2c18e55eb32292659cf731d9d5b312a6eb036506304f4675630"}, + {file = "matplotlib-3.8.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:deaed9ad4da0b1aea77fe0aa0cebb9ef611c70b3177be936a95e5d01fa05094f"}, + {file = "matplotlib-3.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:172f4d0fbac3383d39164c6caafd3255ce6fa58f08fc392513a0b1d3b89c4f89"}, + {file = "matplotlib-3.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7d36c2209d9136cd8e02fab1c0ddc185ce79bc914c45054a9f514e44c787917"}, + {file = "matplotlib-3.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5864bdd7da445e4e5e011b199bb67168cdad10b501750367c496420f2ad00843"}, + {file = "matplotlib-3.8.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ef8345b48e95cee45ff25192ed1f4857273117917a4dcd48e3905619bcd9c9b8"}, + {file = "matplotlib-3.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:7c48d9e221b637c017232e3760ed30b4e8d5dfd081daf327e829bf2a72c731b4"}, + {file = "matplotlib-3.8.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:aa11b3c6928a1e496c1a79917d51d4cd5d04f8a2e75f21df4949eeefdf697f4b"}, + {file = "matplotlib-3.8.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1095fecf99eeb7384dabad4bf44b965f929a5f6079654b681193edf7169ec20"}, + {file = "matplotlib-3.8.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:bddfb1db89bfaa855912261c805bd0e10218923cc262b9159a49c29a7a1c1afa"}, + {file = "matplotlib-3.8.2.tar.gz", hash = "sha256:01a978b871b881ee76017152f1f1a0cbf6bd5f7b8ff8c96df0df1bd57d8755a1"}, +] + +[package.dependencies] +contourpy = ">=1.0.1" +cycler = ">=0.10" +fonttools = ">=4.22.0" +importlib-resources = {version = ">=3.2.0", markers = "python_version < \"3.10\""} +kiwisolver = ">=1.3.1" +numpy = ">=1.21,<2" +packaging = ">=20.0" +pillow = ">=8" +pyparsing = ">=2.3.1" +python-dateutil = ">=2.7" + +[[package]] +name = "mergedeep" +version = "1.3.4" +description = "A deep merge function for 🐍." +optional = false +python-versions = ">=3.6" +files = [ + {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"}, + {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"}, +] + +[[package]] +name = "mkdocs" +version = "1.5.3" +description = "Project documentation with Markdown." +optional = false +python-versions = ">=3.7" +files = [ + {file = "mkdocs-1.5.3-py3-none-any.whl", hash = "sha256:3b3a78e736b31158d64dbb2f8ba29bd46a379d0c6e324c2246c3bc3d2189cfc1"}, + {file = "mkdocs-1.5.3.tar.gz", hash = "sha256:eb7c99214dcb945313ba30426c2451b735992c73c2e10838f76d09e39ff4d0e2"}, +] + +[package.dependencies] +click = ">=7.0" +colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} +ghp-import = ">=1.0" +importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""} +jinja2 = ">=2.11.1" +markdown = ">=3.2.1" +markupsafe = ">=2.0.1" +mergedeep = ">=1.3.4" +packaging = ">=20.5" +pathspec = ">=0.11.1" +platformdirs = ">=2.2.0" +pyyaml = ">=5.1" +pyyaml-env-tag = ">=0.1" +watchdog = ">=2.0" + +[package.extras] +i18n = ["babel (>=2.9.0)"] +min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.3)", "jinja2 (==2.11.1)", "markdown (==3.2.1)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "packaging (==20.5)", "pathspec (==0.11.1)", "platformdirs (==2.2.0)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "typing-extensions (==3.10)", "watchdog (==2.0)"] + +[[package]] +name = "mkdocs-autorefs" +version = "0.5.0" +description = "Automatically link across pages in MkDocs." +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs_autorefs-0.5.0-py3-none-any.whl", hash = "sha256:7930fcb8ac1249f10e683967aeaddc0af49d90702af111a5e390e8b20b3d97ff"}, + {file = "mkdocs_autorefs-0.5.0.tar.gz", hash = "sha256:9a5054a94c08d28855cfab967ada10ed5be76e2bfad642302a610b252c3274c0"}, +] + +[package.dependencies] +Markdown = ">=3.3" +mkdocs = ">=1.1" + +[[package]] +name = "mkdocs-material" +version = "9.5.6" +description = "Documentation that simply works" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs_material-9.5.6-py3-none-any.whl", hash = "sha256:e115b90fccf5cd7f5d15b0c2f8e6246b21041628b8f590630e7fca66ed7fcf6c"}, + {file = "mkdocs_material-9.5.6.tar.gz", hash = "sha256:5b24df36d8ac6cecd611241ce6f6423ccde3e1ad89f8360c3f76d5565fc2d82a"}, +] + +[package.dependencies] +babel = ">=2.10,<3.0" +colorama = ">=0.4,<1.0" +jinja2 = ">=3.0,<4.0" +markdown = ">=3.2,<4.0" +mkdocs = ">=1.5.3,<1.6.0" +mkdocs-material-extensions = ">=1.3,<2.0" +paginate = ">=0.5,<1.0" +pygments = ">=2.16,<3.0" +pymdown-extensions = ">=10.2,<11.0" +regex = ">=2022.4" +requests = ">=2.26,<3.0" + +[package.extras] +git = ["mkdocs-git-committers-plugin-2 (>=1.1,<2.0)", "mkdocs-git-revision-date-localized-plugin (>=1.2,<2.0)"] +imaging = ["cairosvg (>=2.6,<3.0)", "pillow (>=10.2,<11.0)"] +recommended = ["mkdocs-minify-plugin (>=0.7,<1.0)", "mkdocs-redirects (>=1.2,<2.0)", "mkdocs-rss-plugin (>=1.6,<2.0)"] + +[[package]] +name = "mkdocs-material-extensions" +version = "1.3.1" +description = "Extension pack for Python Markdown and MkDocs Material." +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31"}, + {file = "mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443"}, +] + +[[package]] +name = "mkdocstrings" +version = "0.23.0" +description = "Automatic documentation from sources, for MkDocs." +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocstrings-0.23.0-py3-none-any.whl", hash = "sha256:051fa4014dfcd9ed90254ae91de2dbb4f24e166347dae7be9a997fe16316c65e"}, + {file = "mkdocstrings-0.23.0.tar.gz", hash = "sha256:d9c6a37ffbe7c14a7a54ef1258c70b8d394e6a33a1c80832bce40b9567138d1c"}, +] + +[package.dependencies] +importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""} +Jinja2 = ">=2.11.1" +Markdown = ">=3.3" +MarkupSafe = ">=1.1" +mkdocs = ">=1.2" +mkdocs-autorefs = ">=0.3.1" +mkdocstrings-python = {version = ">=0.5.2", optional = true, markers = "extra == \"python\""} +pymdown-extensions = ">=6.3" +typing-extensions = {version = ">=4.1", markers = "python_version < \"3.10\""} + +[package.extras] +crystal = ["mkdocstrings-crystal (>=0.3.4)"] +python = ["mkdocstrings-python (>=0.5.2)"] +python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"] + +[[package]] +name = "mkdocstrings-python" +version = "1.8.0" +description = "A Python handler for mkdocstrings." +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocstrings_python-1.8.0-py3-none-any.whl", hash = "sha256:4209970cc90bec194568682a535848a8d8489516c6ed4adbe58bbc67b699ca9d"}, + {file = "mkdocstrings_python-1.8.0.tar.gz", hash = "sha256:1488bddf50ee42c07d9a488dddc197f8e8999c2899687043ec5dd1643d057192"}, +] + +[package.dependencies] +griffe = ">=0.37" +mkdocstrings = ">=0.20" + +[[package]] +name = "mypy" +version = "1.8.0" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485a8942f671120f76afffff70f259e1cd0f0cfe08f81c05d8816d958d4577d3"}, + {file = "mypy-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:df9824ac11deaf007443e7ed2a4a26bebff98d2bc43c6da21b2b64185da011c4"}, + {file = "mypy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2afecd6354bbfb6e0160f4e4ad9ba6e4e003b767dd80d85516e71f2e955ab50d"}, + {file = "mypy-1.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8963b83d53ee733a6e4196954502b33567ad07dfd74851f32be18eb932fb1cb9"}, + {file = "mypy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:e46f44b54ebddbeedbd3d5b289a893219065ef805d95094d16a0af6630f5d410"}, + {file = "mypy-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:855fe27b80375e5c5878492f0729540db47b186509c98dae341254c8f45f42ae"}, + {file = "mypy-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c886c6cce2d070bd7df4ec4a05a13ee20c0aa60cb587e8d1265b6c03cf91da3"}, + {file = "mypy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d19c413b3c07cbecf1f991e2221746b0d2a9410b59cb3f4fb9557f0365a1a817"}, + {file = "mypy-1.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9261ed810972061388918c83c3f5cd46079d875026ba97380f3e3978a72f503d"}, + {file = "mypy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:51720c776d148bad2372ca21ca29256ed483aa9a4cdefefcef49006dff2a6835"}, + {file = "mypy-1.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:52825b01f5c4c1c4eb0db253ec09c7aa17e1a7304d247c48b6f3599ef40db8bd"}, + {file = "mypy-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f5ac9a4eeb1ec0f1ccdc6f326bcdb464de5f80eb07fb38b5ddd7b0de6bc61e55"}, + {file = "mypy-1.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afe3fe972c645b4632c563d3f3eff1cdca2fa058f730df2b93a35e3b0c538218"}, + {file = "mypy-1.8.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:42c6680d256ab35637ef88891c6bd02514ccb7e1122133ac96055ff458f93fc3"}, + {file = "mypy-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:720a5ca70e136b675af3af63db533c1c8c9181314d207568bbe79051f122669e"}, + {file = "mypy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:028cf9f2cae89e202d7b6593cd98db6759379f17a319b5faf4f9978d7084cdc6"}, + {file = "mypy-1.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4e6d97288757e1ddba10dd9549ac27982e3e74a49d8d0179fc14d4365c7add66"}, + {file = "mypy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f1478736fcebb90f97e40aff11a5f253af890c845ee0c850fe80aa060a267c6"}, + {file = "mypy-1.8.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42419861b43e6962a649068a61f4a4839205a3ef525b858377a960b9e2de6e0d"}, + {file = "mypy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:2b5b6c721bd4aabaadead3a5e6fa85c11c6c795e0c81a7215776ef8afc66de02"}, + {file = "mypy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5c1538c38584029352878a0466f03a8ee7547d7bd9f641f57a0f3017a7c905b8"}, + {file = "mypy-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ef4be7baf08a203170f29e89d79064463b7fc7a0908b9d0d5114e8009c3a259"}, + {file = "mypy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7178def594014aa6c35a8ff411cf37d682f428b3b5617ca79029d8ae72f5402b"}, + {file = "mypy-1.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ab3c84fa13c04aeeeabb2a7f67a25ef5d77ac9d6486ff33ded762ef353aa5592"}, + {file = "mypy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:99b00bc72855812a60d253420d8a2eae839b0afa4938f09f4d2aa9bb4654263a"}, + {file = "mypy-1.8.0-py3-none-any.whl", hash = "sha256:538fd81bb5e430cc1381a443971c0475582ff9f434c16cd46d2c66763ce85d9d"}, + {file = "mypy-1.8.0.tar.gz", hash = "sha256:6ff8b244d7085a0b425b56d327b480c3b29cafbd2eff27316a004f9a7391ae07"}, +] + +[package.dependencies] +mypy-extensions = ">=1.0.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = ">=4.1.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +mypyc = ["setuptools (>=50)"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "nodeenv" +version = "1.8.0" +description = "Node.js virtual environment builder" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" +files = [ + {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, + {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, +] + +[package.dependencies] +setuptools = "*" + +[[package]] +name = "nose" +version = "1.3.7" +description = "nose extends unittest to make testing easier" +optional = false +python-versions = "*" +files = [ + {file = "nose-1.3.7-py2-none-any.whl", hash = "sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a"}, + {file = "nose-1.3.7-py3-none-any.whl", hash = "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac"}, + {file = "nose-1.3.7.tar.gz", hash = "sha256:f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98"}, +] + +[[package]] +name = "numpy" +version = "1.26.3" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "numpy-1.26.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:806dd64230dbbfaca8a27faa64e2f414bf1c6622ab78cc4264f7f5f028fee3bf"}, + {file = "numpy-1.26.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02f98011ba4ab17f46f80f7f8f1c291ee7d855fcef0a5a98db80767a468c85cd"}, + {file = "numpy-1.26.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d45b3ec2faed4baca41c76617fcdcfa4f684ff7a151ce6fc78ad3b6e85af0a6"}, + {file = "numpy-1.26.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdd2b45bf079d9ad90377048e2747a0c82351989a2165821f0c96831b4a2a54b"}, + {file = "numpy-1.26.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:211ddd1e94817ed2d175b60b6374120244a4dd2287f4ece45d49228b4d529178"}, + {file = "numpy-1.26.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b1240f767f69d7c4c8a29adde2310b871153df9b26b5cb2b54a561ac85146485"}, + {file = "numpy-1.26.3-cp310-cp310-win32.whl", hash = "sha256:21a9484e75ad018974a2fdaa216524d64ed4212e418e0a551a2d83403b0531d3"}, + {file = "numpy-1.26.3-cp310-cp310-win_amd64.whl", hash = "sha256:9e1591f6ae98bcfac2a4bbf9221c0b92ab49762228f38287f6eeb5f3f55905ce"}, + {file = "numpy-1.26.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b831295e5472954104ecb46cd98c08b98b49c69fdb7040483aff799a755a7374"}, + {file = "numpy-1.26.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9e87562b91f68dd8b1c39149d0323b42e0082db7ddb8e934ab4c292094d575d6"}, + {file = "numpy-1.26.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c66d6fec467e8c0f975818c1796d25c53521124b7cfb760114be0abad53a0a2"}, + {file = "numpy-1.26.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f25e2811a9c932e43943a2615e65fc487a0b6b49218899e62e426e7f0a57eeda"}, + {file = "numpy-1.26.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:af36e0aa45e25c9f57bf684b1175e59ea05d9a7d3e8e87b7ae1a1da246f2767e"}, + {file = "numpy-1.26.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:51c7f1b344f302067b02e0f5b5d2daa9ed4a721cf49f070280ac202738ea7f00"}, + {file = "numpy-1.26.3-cp311-cp311-win32.whl", hash = "sha256:7ca4f24341df071877849eb2034948459ce3a07915c2734f1abb4018d9c49d7b"}, + {file = "numpy-1.26.3-cp311-cp311-win_amd64.whl", hash = "sha256:39763aee6dfdd4878032361b30b2b12593fb445ddb66bbac802e2113eb8a6ac4"}, + {file = "numpy-1.26.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a7081fd19a6d573e1a05e600c82a1c421011db7935ed0d5c483e9dd96b99cf13"}, + {file = "numpy-1.26.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12c70ac274b32bc00c7f61b515126c9205323703abb99cd41836e8125ea0043e"}, + {file = "numpy-1.26.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f784e13e598e9594750b2ef6729bcd5a47f6cfe4a12cca13def35e06d8163e3"}, + {file = "numpy-1.26.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f24750ef94d56ce6e33e4019a8a4d68cfdb1ef661a52cdaee628a56d2437419"}, + {file = "numpy-1.26.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:77810ef29e0fb1d289d225cabb9ee6cf4d11978a00bb99f7f8ec2132a84e0166"}, + {file = "numpy-1.26.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8ed07a90f5450d99dad60d3799f9c03c6566709bd53b497eb9ccad9a55867f36"}, + {file = "numpy-1.26.3-cp312-cp312-win32.whl", hash = "sha256:f73497e8c38295aaa4741bdfa4fda1a5aedda5473074369eca10626835445511"}, + {file = "numpy-1.26.3-cp312-cp312-win_amd64.whl", hash = "sha256:da4b0c6c699a0ad73c810736303f7fbae483bcb012e38d7eb06a5e3b432c981b"}, + {file = "numpy-1.26.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1666f634cb3c80ccbd77ec97bc17337718f56d6658acf5d3b906ca03e90ce87f"}, + {file = "numpy-1.26.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18c3319a7d39b2c6a9e3bb75aab2304ab79a811ac0168a671a62e6346c29b03f"}, + {file = "numpy-1.26.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b7e807d6888da0db6e7e75838444d62495e2b588b99e90dd80c3459594e857b"}, + {file = "numpy-1.26.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4d362e17bcb0011738c2d83e0a65ea8ce627057b2fdda37678f4374a382a137"}, + {file = "numpy-1.26.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b8c275f0ae90069496068c714387b4a0eba5d531aace269559ff2b43655edd58"}, + {file = "numpy-1.26.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cc0743f0302b94f397a4a65a660d4cd24267439eb16493fb3caad2e4389bccbb"}, + {file = "numpy-1.26.3-cp39-cp39-win32.whl", hash = "sha256:9bc6d1a7f8cedd519c4b7b1156d98e051b726bf160715b769106661d567b3f03"}, + {file = "numpy-1.26.3-cp39-cp39-win_amd64.whl", hash = "sha256:867e3644e208c8922a3be26fc6bbf112a035f50f0a86497f98f228c50c607bb2"}, + {file = "numpy-1.26.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3c67423b3703f8fbd90f5adaa37f85b5794d3366948efe9a5190a5f3a83fc34e"}, + {file = "numpy-1.26.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46f47ee566d98849323f01b349d58f2557f02167ee301e5e28809a8c0e27a2d0"}, + {file = "numpy-1.26.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a8474703bffc65ca15853d5fd4d06b18138ae90c17c8d12169968e998e448bb5"}, + {file = "numpy-1.26.3.tar.gz", hash = "sha256:697df43e2b6310ecc9d95f05d5ef20eacc09c7c4ecc9da3f235d39e71b7da1e4"}, +] + +[[package]] +name = "packaging" +version = "23.2" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] + +[[package]] +name = "paginate" +version = "0.5.6" +description = "Divides large result sets into pages for easier browsing" +optional = false +python-versions = "*" +files = [ + {file = "paginate-0.5.6.tar.gz", hash = "sha256:5e6007b6a9398177a7e1648d04fdd9f8c9766a1a945bceac82f1929e8c78af2d"}, +] + +[[package]] +name = "pandas" +version = "2.2.0" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pandas-2.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8108ee1712bb4fa2c16981fba7e68b3f6ea330277f5ca34fa8d557e986a11670"}, + {file = "pandas-2.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:736da9ad4033aeab51d067fc3bd69a0ba36f5a60f66a527b3d72e2030e63280a"}, + {file = "pandas-2.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38e0b4fc3ddceb56ec8a287313bc22abe17ab0eb184069f08fc6a9352a769b18"}, + {file = "pandas-2.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20404d2adefe92aed3b38da41d0847a143a09be982a31b85bc7dd565bdba0f4e"}, + {file = "pandas-2.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7ea3ee3f125032bfcade3a4cf85131ed064b4f8dd23e5ce6fa16473e48ebcaf5"}, + {file = "pandas-2.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f9670b3ac00a387620489dfc1bca66db47a787f4e55911f1293063a78b108df1"}, + {file = "pandas-2.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:5a946f210383c7e6d16312d30b238fd508d80d927014f3b33fb5b15c2f895430"}, + {file = "pandas-2.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a1b438fa26b208005c997e78672f1aa8138f67002e833312e6230f3e57fa87d5"}, + {file = "pandas-2.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8ce2fbc8d9bf303ce54a476116165220a1fedf15985b09656b4b4275300e920b"}, + {file = "pandas-2.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2707514a7bec41a4ab81f2ccce8b382961a29fbe9492eab1305bb075b2b1ff4f"}, + {file = "pandas-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85793cbdc2d5bc32620dc8ffa715423f0c680dacacf55056ba13454a5be5de88"}, + {file = "pandas-2.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cfd6c2491dc821b10c716ad6776e7ab311f7df5d16038d0b7458bc0b67dc10f3"}, + {file = "pandas-2.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a146b9dcacc3123aa2b399df1a284de5f46287a4ab4fbfc237eac98a92ebcb71"}, + {file = "pandas-2.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbc1b53c0e1fdf16388c33c3cca160f798d38aea2978004dd3f4d3dec56454c9"}, + {file = "pandas-2.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a41d06f308a024981dcaa6c41f2f2be46a6b186b902c94c2674e8cb5c42985bc"}, + {file = "pandas-2.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:159205c99d7a5ce89ecfc37cb08ed179de7783737cea403b295b5eda8e9c56d1"}, + {file = "pandas-2.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb1e1f3861ea9132b32f2133788f3b14911b68102d562715d71bd0013bc45440"}, + {file = "pandas-2.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:761cb99b42a69005dec2b08854fb1d4888fdf7b05db23a8c5a099e4b886a2106"}, + {file = "pandas-2.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a20628faaf444da122b2a64b1e5360cde100ee6283ae8effa0d8745153809a2e"}, + {file = "pandas-2.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f5be5d03ea2073627e7111f61b9f1f0d9625dc3c4d8dda72cc827b0c58a1d042"}, + {file = "pandas-2.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:a626795722d893ed6aacb64d2401d017ddc8a2341b49e0384ab9bf7112bdec30"}, + {file = "pandas-2.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9f66419d4a41132eb7e9a73dcec9486cf5019f52d90dd35547af11bc58f8637d"}, + {file = "pandas-2.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:57abcaeda83fb80d447f28ab0cc7b32b13978f6f733875ebd1ed14f8fbc0f4ab"}, + {file = "pandas-2.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e60f1f7dba3c2d5ca159e18c46a34e7ca7247a73b5dd1a22b6d59707ed6b899a"}, + {file = "pandas-2.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb61dc8567b798b969bcc1fc964788f5a68214d333cade8319c7ab33e2b5d88a"}, + {file = "pandas-2.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:52826b5f4ed658fa2b729264d63f6732b8b29949c7fd234510d57c61dbeadfcd"}, + {file = "pandas-2.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bde2bc699dbd80d7bc7f9cab1e23a95c4375de615860ca089f34e7c64f4a8de7"}, + {file = "pandas-2.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:3de918a754bbf2da2381e8a3dcc45eede8cd7775b047b923f9006d5f876802ae"}, + {file = "pandas-2.2.0.tar.gz", hash = "sha256:30b83f7c3eb217fb4d1b494a57a2fda5444f17834f5df2de6b2ffff68dc3c8e2"}, +] + +[package.dependencies] +numpy = [ + {version = ">=1.22.4,<2", markers = "python_version < \"3.11\""}, + {version = ">=1.23.2,<2", markers = "python_version == \"3.11\""}, +] +python-dateutil = ">=2.8.2" +pytz = ">=2020.1" +tzdata = ">=2022.7" + +[package.extras] +all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] +aws = ["s3fs (>=2022.11.0)"] +clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] +compression = ["zstandard (>=0.19.0)"] +computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] +consortium-standard = ["dataframe-api-compat (>=0.1.7)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] +feather = ["pyarrow (>=10.0.1)"] +fss = ["fsspec (>=2022.11.0)"] +gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] +hdf5 = ["tables (>=3.8.0)"] +html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] +mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] +parquet = ["pyarrow (>=10.0.1)"] +performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] +plot = ["matplotlib (>=3.6.3)"] +postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] +spss = ["pyreadstat (>=1.2.0)"] +sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] +test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.9.2)"] + +[[package]] +name = "pathspec" +version = "0.12.1" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, +] + +[[package]] +name = "pillow" +version = "10.2.0" +description = "Python Imaging Library (Fork)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pillow-10.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:7823bdd049099efa16e4246bdf15e5a13dbb18a51b68fa06d6c1d4d8b99a796e"}, + {file = "pillow-10.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:83b2021f2ade7d1ed556bc50a399127d7fb245e725aa0113ebd05cfe88aaf588"}, + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fad5ff2f13d69b7e74ce5b4ecd12cc0ec530fcee76356cac6742785ff71c452"}, + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da2b52b37dad6d9ec64e653637a096905b258d2fc2b984c41ae7d08b938a67e4"}, + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:47c0995fc4e7f79b5cfcab1fc437ff2890b770440f7696a3ba065ee0fd496563"}, + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:322bdf3c9b556e9ffb18f93462e5f749d3444ce081290352c6070d014c93feb2"}, + {file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:51f1a1bffc50e2e9492e87d8e09a17c5eea8409cda8d3f277eb6edc82813c17c"}, + {file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:69ffdd6120a4737710a9eee73e1d2e37db89b620f702754b8f6e62594471dee0"}, + {file = "pillow-10.2.0-cp310-cp310-win32.whl", hash = "sha256:c6dafac9e0f2b3c78df97e79af707cdc5ef8e88208d686a4847bab8266870023"}, + {file = "pillow-10.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:aebb6044806f2e16ecc07b2a2637ee1ef67a11840a66752751714a0d924adf72"}, + {file = "pillow-10.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:7049e301399273a0136ff39b84c3678e314f2158f50f517bc50285fb5ec847ad"}, + {file = "pillow-10.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35bb52c37f256f662abdfa49d2dfa6ce5d93281d323a9af377a120e89a9eafb5"}, + {file = "pillow-10.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c23f307202661071d94b5e384e1e1dc7dfb972a28a2310e4ee16103e66ddb67"}, + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:773efe0603db30c281521a7c0214cad7836c03b8ccff897beae9b47c0b657d61"}, + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11fa2e5984b949b0dd6d7a94d967743d87c577ff0b83392f17cb3990d0d2fd6e"}, + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:716d30ed977be8b37d3ef185fecb9e5a1d62d110dfbdcd1e2a122ab46fddb03f"}, + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a086c2af425c5f62a65e12fbf385f7c9fcb8f107d0849dba5839461a129cf311"}, + {file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c8de2789052ed501dd829e9cae8d3dcce7acb4777ea4a479c14521c942d395b1"}, + {file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:609448742444d9290fd687940ac0b57fb35e6fd92bdb65386e08e99af60bf757"}, + {file = "pillow-10.2.0-cp311-cp311-win32.whl", hash = "sha256:823ef7a27cf86df6597fa0671066c1b596f69eba53efa3d1e1cb8b30f3533068"}, + {file = "pillow-10.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:1da3b2703afd040cf65ec97efea81cfba59cdbed9c11d8efc5ab09df9509fc56"}, + {file = "pillow-10.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:edca80cbfb2b68d7b56930b84a0e45ae1694aeba0541f798e908a49d66b837f1"}, + {file = "pillow-10.2.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:1b5e1b74d1bd1b78bc3477528919414874748dd363e6272efd5abf7654e68bef"}, + {file = "pillow-10.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0eae2073305f451d8ecacb5474997c08569fb4eb4ac231ffa4ad7d342fdc25ac"}, + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7c2286c23cd350b80d2fc9d424fc797575fb16f854b831d16fd47ceec078f2c"}, + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e23412b5c41e58cec602f1135c57dfcf15482013ce6e5f093a86db69646a5aa"}, + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:52a50aa3fb3acb9cf7213573ef55d31d6eca37f5709c69e6858fe3bc04a5c2a2"}, + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:127cee571038f252a552760076407f9cff79761c3d436a12af6000cd182a9d04"}, + {file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:8d12251f02d69d8310b046e82572ed486685c38f02176bd08baf216746eb947f"}, + {file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:54f1852cd531aa981bc0965b7d609f5f6cc8ce8c41b1139f6ed6b3c54ab82bfb"}, + {file = "pillow-10.2.0-cp312-cp312-win32.whl", hash = "sha256:257d8788df5ca62c980314053197f4d46eefedf4e6175bc9412f14412ec4ea2f"}, + {file = "pillow-10.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:154e939c5f0053a383de4fd3d3da48d9427a7e985f58af8e94d0b3c9fcfcf4f9"}, + {file = "pillow-10.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:f379abd2f1e3dddb2b61bc67977a6b5a0a3f7485538bcc6f39ec76163891ee48"}, + {file = "pillow-10.2.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8373c6c251f7ef8bda6675dd6d2b3a0fcc31edf1201266b5cf608b62a37407f9"}, + {file = "pillow-10.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:870ea1ada0899fd0b79643990809323b389d4d1d46c192f97342eeb6ee0b8483"}, + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4b6b1e20608493548b1f32bce8cca185bf0480983890403d3b8753e44077129"}, + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3031709084b6e7852d00479fd1d310b07d0ba82765f973b543c8af5061cf990e"}, + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:3ff074fc97dd4e80543a3e91f69d58889baf2002b6be64347ea8cf5533188213"}, + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:cb4c38abeef13c61d6916f264d4845fab99d7b711be96c326b84df9e3e0ff62d"}, + {file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b1b3020d90c2d8e1dae29cf3ce54f8094f7938460fb5ce8bc5c01450b01fbaf6"}, + {file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:170aeb00224ab3dc54230c797f8404507240dd868cf52066f66a41b33169bdbe"}, + {file = "pillow-10.2.0-cp38-cp38-win32.whl", hash = "sha256:c4225f5220f46b2fde568c74fca27ae9771536c2e29d7c04f4fb62c83275ac4e"}, + {file = "pillow-10.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:0689b5a8c5288bc0504d9fcee48f61a6a586b9b98514d7d29b840143d6734f39"}, + {file = "pillow-10.2.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:b792a349405fbc0163190fde0dc7b3fef3c9268292586cf5645598b48e63dc67"}, + {file = "pillow-10.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c570f24be1e468e3f0ce7ef56a89a60f0e05b30a3669a459e419c6eac2c35364"}, + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8ecd059fdaf60c1963c58ceb8997b32e9dc1b911f5da5307aab614f1ce5c2fb"}, + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c365fd1703040de1ec284b176d6af5abe21b427cb3a5ff68e0759e1e313a5e7e"}, + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:70c61d4c475835a19b3a5aa42492409878bbca7438554a1f89d20d58a7c75c01"}, + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b6f491cdf80ae540738859d9766783e3b3c8e5bd37f5dfa0b76abdecc5081f13"}, + {file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d189550615b4948f45252d7f005e53c2040cea1af5b60d6f79491a6e147eef7"}, + {file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:49d9ba1ed0ef3e061088cd1e7538a0759aab559e2e0a80a36f9fd9d8c0c21591"}, + {file = "pillow-10.2.0-cp39-cp39-win32.whl", hash = "sha256:babf5acfede515f176833ed6028754cbcd0d206f7f614ea3447d67c33be12516"}, + {file = "pillow-10.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:0304004f8067386b477d20a518b50f3fa658a28d44e4116970abfcd94fac34a8"}, + {file = "pillow-10.2.0-cp39-cp39-win_arm64.whl", hash = "sha256:0fb3e7fc88a14eacd303e90481ad983fd5b69c761e9e6ef94c983f91025da869"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:322209c642aabdd6207517e9739c704dc9f9db943015535783239022002f054a"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eedd52442c0a5ff4f887fab0c1c0bb164d8635b32c894bc1faf4c618dd89df2"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb28c753fd5eb3dd859b4ee95de66cc62af91bcff5db5f2571d32a520baf1f04"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:33870dc4653c5017bf4c8873e5488d8f8d5f8935e2f1fb9a2208c47cdd66efd2"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3c31822339516fb3c82d03f30e22b1d038da87ef27b6a78c9549888f8ceda39a"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a2b56ba36e05f973d450582fb015594aaa78834fefe8dfb8fcd79b93e64ba4c6"}, + {file = "pillow-10.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d8e6aeb9201e655354b3ad049cb77d19813ad4ece0df1249d3c793de3774f8c7"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:2247178effb34a77c11c0e8ac355c7a741ceca0a732b27bf11e747bbc950722f"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15587643b9e5eb26c48e49a7b33659790d28f190fc514a322d55da2fb5c2950e"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753cd8f2086b2b80180d9b3010dd4ed147efc167c90d3bf593fe2af21265e5a5"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7c8f97e8e7a9009bcacbe3766a36175056c12f9a44e6e6f2d5caad06dcfbf03b"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d1b35bcd6c5543b9cb547dee3150c93008f8dd0f1fef78fc0cd2b141c5baf58a"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe4c15f6c9285dc54ce6553a3ce908ed37c8f3825b5a51a15c91442bb955b868"}, + {file = "pillow-10.2.0.tar.gz", hash = "sha256:e87f0b2c78157e12d7686b27d63c070fd65d994e8ddae6f328e0dcf4a0cd007e"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] +fpx = ["olefile"] +mic = ["olefile"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +typing = ["typing-extensions"] +xmp = ["defusedxml"] + +[[package]] +name = "platformdirs" +version = "4.2.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"}, + {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] + +[[package]] +name = "pluggy" +version = "1.4.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pre-commit" +version = "3.5.0" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pre_commit-3.5.0-py2.py3-none-any.whl", hash = "sha256:841dc9aef25daba9a0238cd27984041fa0467b4199fc4852e27950664919f660"}, + {file = "pre_commit-3.5.0.tar.gz", hash = "sha256:5804465c675b659b0862f07907f96295d490822a450c4c40e747d0b1c6ebcb32"}, +] + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +virtualenv = ">=20.10.0" + +[[package]] +name = "pyarrow" +version = "15.0.0" +description = "Python library for Apache Arrow" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyarrow-15.0.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:0a524532fd6dd482edaa563b686d754c70417c2f72742a8c990b322d4c03a15d"}, + {file = "pyarrow-15.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:60a6bdb314affa9c2e0d5dddf3d9cbb9ef4a8dddaa68669975287d47ece67642"}, + {file = "pyarrow-15.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:66958fd1771a4d4b754cd385835e66a3ef6b12611e001d4e5edfcef5f30391e2"}, + {file = "pyarrow-15.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f500956a49aadd907eaa21d4fff75f73954605eaa41f61cb94fb008cf2e00c6"}, + {file = "pyarrow-15.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:6f87d9c4f09e049c2cade559643424da84c43a35068f2a1c4653dc5b1408a929"}, + {file = "pyarrow-15.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:85239b9f93278e130d86c0e6bb455dcb66fc3fd891398b9d45ace8799a871a1e"}, + {file = "pyarrow-15.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:5b8d43e31ca16aa6e12402fcb1e14352d0d809de70edd185c7650fe80e0769e3"}, + {file = "pyarrow-15.0.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:fa7cd198280dbd0c988df525e50e35b5d16873e2cdae2aaaa6363cdb64e3eec5"}, + {file = "pyarrow-15.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8780b1a29d3c8b21ba6b191305a2a607de2e30dab399776ff0aa09131e266340"}, + {file = "pyarrow-15.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe0ec198ccc680f6c92723fadcb97b74f07c45ff3fdec9dd765deb04955ccf19"}, + {file = "pyarrow-15.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:036a7209c235588c2f07477fe75c07e6caced9b7b61bb897c8d4e52c4b5f9555"}, + {file = "pyarrow-15.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:2bd8a0e5296797faf9a3294e9fa2dc67aa7f10ae2207920dbebb785c77e9dbe5"}, + {file = "pyarrow-15.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:e8ebed6053dbe76883a822d4e8da36860f479d55a762bd9e70d8494aed87113e"}, + {file = "pyarrow-15.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:17d53a9d1b2b5bd7d5e4cd84d018e2a45bc9baaa68f7e6e3ebed45649900ba99"}, + {file = "pyarrow-15.0.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:9950a9c9df24090d3d558b43b97753b8f5867fb8e521f29876aa021c52fda351"}, + {file = "pyarrow-15.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:003d680b5e422d0204e7287bb3fa775b332b3fce2996aa69e9adea23f5c8f970"}, + {file = "pyarrow-15.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f75fce89dad10c95f4bf590b765e3ae98bcc5ba9f6ce75adb828a334e26a3d40"}, + {file = "pyarrow-15.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca9cb0039923bec49b4fe23803807e4ef39576a2bec59c32b11296464623dc2"}, + {file = "pyarrow-15.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:9ed5a78ed29d171d0acc26a305a4b7f83c122d54ff5270810ac23c75813585e4"}, + {file = "pyarrow-15.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:6eda9e117f0402dfcd3cd6ec9bfee89ac5071c48fc83a84f3075b60efa96747f"}, + {file = "pyarrow-15.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:9a3a6180c0e8f2727e6f1b1c87c72d3254cac909e609f35f22532e4115461177"}, + {file = "pyarrow-15.0.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:19a8918045993349b207de72d4576af0191beef03ea655d8bdb13762f0cd6eac"}, + {file = "pyarrow-15.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d0ec076b32bacb6666e8813a22e6e5a7ef1314c8069d4ff345efa6246bc38593"}, + {file = "pyarrow-15.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5db1769e5d0a77eb92344c7382d6543bea1164cca3704f84aa44e26c67e320fb"}, + {file = "pyarrow-15.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2617e3bf9df2a00020dd1c1c6dce5cc343d979efe10bc401c0632b0eef6ef5b"}, + {file = "pyarrow-15.0.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:d31c1d45060180131caf10f0f698e3a782db333a422038bf7fe01dace18b3a31"}, + {file = "pyarrow-15.0.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:c8c287d1d479de8269398b34282e206844abb3208224dbdd7166d580804674b7"}, + {file = "pyarrow-15.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:07eb7f07dc9ecbb8dace0f58f009d3a29ee58682fcdc91337dfeb51ea618a75b"}, + {file = "pyarrow-15.0.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:47af7036f64fce990bb8a5948c04722e4e3ea3e13b1007ef52dfe0aa8f23cf7f"}, + {file = "pyarrow-15.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93768ccfff85cf044c418bfeeafce9a8bb0cee091bd8fd19011aff91e58de540"}, + {file = "pyarrow-15.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6ee87fd6892700960d90abb7b17a72a5abb3b64ee0fe8db6c782bcc2d0dc0b4"}, + {file = "pyarrow-15.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:001fca027738c5f6be0b7a3159cc7ba16a5c52486db18160909a0831b063c4e4"}, + {file = "pyarrow-15.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:d1c48648f64aec09accf44140dccb92f4f94394b8d79976c426a5b79b11d4fa7"}, + {file = "pyarrow-15.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:972a0141be402bb18e3201448c8ae62958c9c7923dfaa3b3d4530c835ac81aed"}, + {file = "pyarrow-15.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:f01fc5cf49081426429127aa2d427d9d98e1cb94a32cb961d583a70b7c4504e6"}, + {file = "pyarrow-15.0.0.tar.gz", hash = "sha256:876858f549d540898f927eba4ef77cd549ad8d24baa3207cf1b72e5788b50e83"}, +] + +[package.dependencies] +numpy = ">=1.16.6,<2" + +[[package]] +name = "pygments" +version = "2.17.2" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, + {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, +] + +[package.extras] +plugins = ["importlib-metadata"] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pymdown-extensions" +version = "10.7" +description = "Extension pack for Python Markdown." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pymdown_extensions-10.7-py3-none-any.whl", hash = "sha256:6ca215bc57bc12bf32b414887a68b810637d039124ed9b2e5bd3325cbb2c050c"}, + {file = "pymdown_extensions-10.7.tar.gz", hash = "sha256:c0d64d5cf62566f59e6b2b690a4095c931107c250a8c8e1351c1de5f6b036deb"}, +] + +[package.dependencies] +markdown = ">=3.5" +pyyaml = "*" + +[package.extras] +extra = ["pygments (>=2.12)"] + +[[package]] +name = "pyparsing" +version = "3.1.1" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +optional = false +python-versions = ">=3.6.8" +files = [ + {file = "pyparsing-3.1.1-py3-none-any.whl", hash = "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb"}, + {file = "pyparsing-3.1.1.tar.gz", hash = "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db"}, +] + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + +[[package]] +name = "pyproject-api" +version = "1.6.1" +description = "API to interact with the python pyproject.toml based projects" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyproject_api-1.6.1-py3-none-any.whl", hash = "sha256:4c0116d60476b0786c88692cf4e325a9814965e2469c5998b830bba16b183675"}, + {file = "pyproject_api-1.6.1.tar.gz", hash = "sha256:1817dc018adc0d1ff9ca1ed8c60e1623d5aaca40814b953af14a9cf9a5cae538"}, +] + +[package.dependencies] +packaging = ">=23.1" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} + +[package.extras] +docs = ["furo (>=2023.8.19)", "sphinx (<7.2)", "sphinx-autodoc-typehints (>=1.24)"] +testing = ["covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)", "setuptools (>=68.1.2)", "wheel (>=0.41.2)"] + +[[package]] +name = "pytest" +version = "7.4.4" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} + +[package.extras] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "4.1.0" +description = "Pytest plugin for measuring coverage." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, + {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, +] + +[package.dependencies] +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] + +[[package]] +name = "pytest-mpl" +version = "0.16.1" +description = "pytest plugin to help with testing figures output from Matplotlib" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pytest-mpl-0.16.1.tar.gz", hash = "sha256:2d571681124e8ff5f4e2b9c0d047d37d0499d6b6d8f2f49a1b50cdd993104469"}, + {file = "pytest_mpl-0.16.1-py3-none-any.whl", hash = "sha256:a830e6bcd218b7cdf968034095855527d8191da00c37770138eb72b9534aa228"}, +] + +[package.dependencies] +Jinja2 = "*" +matplotlib = "*" +packaging = "*" +Pillow = "*" +pytest = "*" + +[package.extras] +test = ["pytest-cov"] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pytz" +version = "2024.1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, +] + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "pyyaml-env-tag" +version = "0.1" +description = "A custom YAML tag for referencing environment variables in YAML files. " +optional = false +python-versions = ">=3.6" +files = [ + {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"}, + {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"}, +] + +[package.dependencies] +pyyaml = "*" + +[[package]] +name = "regex" +version = "2023.12.25" +description = "Alternative regular expression module, to replace re." +optional = false +python-versions = ">=3.7" +files = [ + {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5"}, + {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8"}, + {file = "regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f"}, + {file = "regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630"}, + {file = "regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105"}, + {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6"}, + {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97"}, + {file = "regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4"}, + {file = "regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87"}, + {file = "regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f"}, + {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715"}, + {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d"}, + {file = "regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d"}, + {file = "regex-2023.12.25-cp312-cp312-win32.whl", hash = "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5"}, + {file = "regex-2023.12.25-cp312-cp312-win_amd64.whl", hash = "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232"}, + {file = "regex-2023.12.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39"}, + {file = "regex-2023.12.25-cp37-cp37m-win32.whl", hash = "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c"}, + {file = "regex-2023.12.25-cp37-cp37m-win_amd64.whl", hash = "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445"}, + {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53"}, + {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64"}, + {file = "regex-2023.12.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2"}, + {file = "regex-2023.12.25-cp38-cp38-win32.whl", hash = "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb"}, + {file = "regex-2023.12.25-cp38-cp38-win_amd64.whl", hash = "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697"}, + {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31"}, + {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7"}, + {file = "regex-2023.12.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20"}, + {file = "regex-2023.12.25-cp39-cp39-win32.whl", hash = "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9"}, + {file = "regex-2023.12.25-cp39-cp39-win_amd64.whl", hash = "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91"}, + {file = "regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5"}, +] + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "scipy" +version = "1.12.0" +description = "Fundamental algorithms for scientific computing in Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "scipy-1.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:78e4402e140879387187f7f25d91cc592b3501a2e51dfb320f48dfb73565f10b"}, + {file = "scipy-1.12.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:f5f00ebaf8de24d14b8449981a2842d404152774c1a1d880c901bf454cb8e2a1"}, + {file = "scipy-1.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e53958531a7c695ff66c2e7bb7b79560ffdc562e2051644c5576c39ff8efb563"}, + {file = "scipy-1.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e32847e08da8d895ce09d108a494d9eb78974cf6de23063f93306a3e419960c"}, + {file = "scipy-1.12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4c1020cad92772bf44b8e4cdabc1df5d87376cb219742549ef69fc9fd86282dd"}, + {file = "scipy-1.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:75ea2a144096b5e39402e2ff53a36fecfd3b960d786b7efd3c180e29c39e53f2"}, + {file = "scipy-1.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:408c68423f9de16cb9e602528be4ce0d6312b05001f3de61fe9ec8b1263cad08"}, + {file = "scipy-1.12.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:5adfad5dbf0163397beb4aca679187d24aec085343755fcdbdeb32b3679f254c"}, + {file = "scipy-1.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3003652496f6e7c387b1cf63f4bb720951cfa18907e998ea551e6de51a04467"}, + {file = "scipy-1.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b8066bce124ee5531d12a74b617d9ac0ea59245246410e19bca549656d9a40a"}, + {file = "scipy-1.12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8bee4993817e204d761dba10dbab0774ba5a8612e57e81319ea04d84945375ba"}, + {file = "scipy-1.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:a24024d45ce9a675c1fb8494e8e5244efea1c7a09c60beb1eeb80373d0fecc70"}, + {file = "scipy-1.12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e7e76cc48638228212c747ada851ef355c2bb5e7f939e10952bc504c11f4e372"}, + {file = "scipy-1.12.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:f7ce148dffcd64ade37b2df9315541f9adad6efcaa86866ee7dd5db0c8f041c3"}, + {file = "scipy-1.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c39f92041f490422924dfdb782527a4abddf4707616e07b021de33467f917bc"}, + {file = "scipy-1.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7ebda398f86e56178c2fa94cad15bf457a218a54a35c2a7b4490b9f9cb2676c"}, + {file = "scipy-1.12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:95e5c750d55cf518c398a8240571b0e0782c2d5a703250872f36eaf737751338"}, + {file = "scipy-1.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:e646d8571804a304e1da01040d21577685ce8e2db08ac58e543eaca063453e1c"}, + {file = "scipy-1.12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:913d6e7956c3a671de3b05ccb66b11bc293f56bfdef040583a7221d9e22a2e35"}, + {file = "scipy-1.12.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba1b0c7256ad75401c73e4b3cf09d1f176e9bd4248f0d3112170fb2ec4db067"}, + {file = "scipy-1.12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:730badef9b827b368f351eacae2e82da414e13cf8bd5051b4bdfd720271a5371"}, + {file = "scipy-1.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6546dc2c11a9df6926afcbdd8a3edec28566e4e785b915e849348c6dd9f3f490"}, + {file = "scipy-1.12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:196ebad3a4882081f62a5bf4aeb7326aa34b110e533aab23e4374fcccb0890dc"}, + {file = "scipy-1.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:b360f1b6b2f742781299514e99ff560d1fe9bd1bff2712894b52abe528d1fd1e"}, + {file = "scipy-1.12.0.tar.gz", hash = "sha256:4bf5abab8a36d20193c698b0f1fc282c1d083c94723902c447e5d2f1780936a3"}, +] + +[package.dependencies] +numpy = ">=1.22.4,<1.29.0" + +[package.extras] +dev = ["click", "cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy", "pycodestyle", "pydevtool", "rich-click", "ruff", "types-psutil", "typing_extensions"] +doc = ["jupytext", "matplotlib (>2)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-design (>=0.2.0)"] +test = ["asv", "gmpy2", "hypothesis", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] + +[[package]] +name = "setuptools" +version = "69.0.3" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"}, + {file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "sortedcontainers" +version = "2.4.0" +description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +optional = false +python-versions = "*" +files = [ + {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, + {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, +] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "tox" +version = "4.12.1" +description = "tox is a generic virtualenv management and test command line tool" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tox-4.12.1-py3-none-any.whl", hash = "sha256:c07ea797880a44f3c4f200ad88ad92b446b83079d4ccef89585df64cc574375c"}, + {file = "tox-4.12.1.tar.gz", hash = "sha256:61aafbeff1bd8a5af84e54ef6e8402f53c6a6066d0782336171ddfbf5362122e"}, +] + +[package.dependencies] +cachetools = ">=5.3.2" +chardet = ">=5.2" +colorama = ">=0.4.6" +filelock = ">=3.13.1" +packaging = ">=23.2" +platformdirs = ">=4.1" +pluggy = ">=1.3" +pyproject-api = ">=1.6.1" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} +virtualenv = ">=20.25" + +[package.extras] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-argparse-cli (>=1.11.1)", "sphinx-autodoc-typehints (>=1.25.2)", "sphinx-copybutton (>=0.5.2)", "sphinx-inline-tabs (>=2023.4.21)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.11)"] +testing = ["build[virtualenv] (>=1.0.3)", "covdefaults (>=2.3)", "detect-test-pollution (>=1.2)", "devpi-process (>=1)", "diff-cover (>=8.0.2)", "distlib (>=0.3.8)", "flaky (>=3.7)", "hatch-vcs (>=0.4)", "hatchling (>=1.21)", "psutil (>=5.9.7)", "pytest (>=7.4.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-xdist (>=3.5)", "re-assert (>=1.1)", "time-machine (>=2.13)", "wheel (>=0.42)"] + +[[package]] +name = "typing-extensions" +version = "4.9.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, + {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, +] + +[[package]] +name = "tzdata" +version = "2023.4" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2023.4-py2.py3-none-any.whl", hash = "sha256:aa3ace4329eeacda5b7beb7ea08ece826c28d761cda36e747cfbf97996d39bf3"}, + {file = "tzdata-2023.4.tar.gz", hash = "sha256:dd54c94f294765522c77399649b4fefd95522479a664a0cec87f41bebc6148c9"}, +] + +[[package]] +name = "urllib3" +version = "2.2.0" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.0-py3-none-any.whl", hash = "sha256:ce3711610ddce217e6d113a2732fafad960a03fd0318c91faa79481e35c11224"}, + {file = "urllib3-2.2.0.tar.gz", hash = "sha256:051d961ad0c62a94e50ecf1af379c3aba230c66c710493493560c0c223c49f20"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "virtualenv" +version = "20.25.0" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.7" +files = [ + {file = "virtualenv-20.25.0-py3-none-any.whl", hash = "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3"}, + {file = "virtualenv-20.25.0.tar.gz", hash = "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b"}, +] + +[package.dependencies] +distlib = ">=0.3.7,<1" +filelock = ">=3.12.2,<4" +platformdirs = ">=3.9.1,<5" + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] + +[[package]] +name = "watchdog" +version = "3.0.0" +description = "Filesystem events monitoring" +optional = false +python-versions = ">=3.7" +files = [ + {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:336adfc6f5cc4e037d52db31194f7581ff744b67382eb6021c868322e32eef41"}, + {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a70a8dcde91be523c35b2bf96196edc5730edb347e374c7de7cd20c43ed95397"}, + {file = "watchdog-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:adfdeab2da79ea2f76f87eb42a3ab1966a5313e5a69a0213a3cc06ef692b0e96"}, + {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2b57a1e730af3156d13b7fdddfc23dea6487fceca29fc75c5a868beed29177ae"}, + {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7ade88d0d778b1b222adebcc0927428f883db07017618a5e684fd03b83342bd9"}, + {file = "watchdog-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7e447d172af52ad204d19982739aa2346245cc5ba6f579d16dac4bfec226d2e7"}, + {file = "watchdog-3.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9fac43a7466eb73e64a9940ac9ed6369baa39b3bf221ae23493a9ec4d0022674"}, + {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8ae9cda41fa114e28faf86cb137d751a17ffd0316d1c34ccf2235e8a84365c7f"}, + {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:25f70b4aa53bd743729c7475d7ec41093a580528b100e9a8c5b5efe8899592fc"}, + {file = "watchdog-3.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4f94069eb16657d2c6faada4624c39464f65c05606af50bb7902e036e3219be3"}, + {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7c5f84b5194c24dd573fa6472685b2a27cc5a17fe5f7b6fd40345378ca6812e3"}, + {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3aa7f6a12e831ddfe78cdd4f8996af9cf334fd6346531b16cec61c3b3c0d8da0"}, + {file = "watchdog-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:233b5817932685d39a7896b1090353fc8efc1ef99c9c054e46c8002561252fb8"}, + {file = "watchdog-3.0.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:13bbbb462ee42ec3c5723e1205be8ced776f05b100e4737518c67c8325cf6100"}, + {file = "watchdog-3.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8f3ceecd20d71067c7fd4c9e832d4e22584318983cabc013dbf3f70ea95de346"}, + {file = "watchdog-3.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c9d8c8ec7efb887333cf71e328e39cffbf771d8f8f95d308ea4125bf5f90ba64"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:0e06ab8858a76e1219e68c7573dfeba9dd1c0219476c5a44d5333b01d7e1743a"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:d00e6be486affb5781468457b21a6cbe848c33ef43f9ea4a73b4882e5f188a44"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:c07253088265c363d1ddf4b3cdb808d59a0468ecd017770ed716991620b8f77a"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:5113334cf8cf0ac8cd45e1f8309a603291b614191c9add34d33075727a967709"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:51f90f73b4697bac9c9a78394c3acbbd331ccd3655c11be1a15ae6fe289a8c83"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:ba07e92756c97e3aca0912b5cbc4e5ad802f4557212788e72a72a47ff376950d"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:d429c2430c93b7903914e4db9a966c7f2b068dd2ebdd2fa9b9ce094c7d459f33"}, + {file = "watchdog-3.0.0-py3-none-win32.whl", hash = "sha256:3ed7c71a9dccfe838c2f0b6314ed0d9b22e77d268c67e015450a29036a81f60f"}, + {file = "watchdog-3.0.0-py3-none-win_amd64.whl", hash = "sha256:4c9956d27be0bb08fc5f30d9d0179a855436e655f046d288e2bcc11adfae893c"}, + {file = "watchdog-3.0.0-py3-none-win_ia64.whl", hash = "sha256:5d9f3a10e02d7371cd929b5d8f11e87d4bad890212ed3901f9b4d68767bee759"}, + {file = "watchdog-3.0.0.tar.gz", hash = "sha256:4d98a320595da7a7c5a18fc48cb633c2e73cda78f93cac2ef42d42bf609a33f9"}, +] + +[package.extras] +watchmedo = ["PyYAML (>=3.10)"] + +[[package]] +name = "zipp" +version = "3.17.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, + {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] + +[metadata] +lock-version = "2.0" +python-versions = ">=3.9,<3.12" +content-hash = "10e0c47519e1b6f4779fa3e80797725177c90957d87ea5379ab19655335c4fe8" diff --git a/pyproject.toml b/pyproject.toml index bc4dabb..57eb4a5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,9 @@ packages = [ ] [tool.poetry.dependencies] -python = ">=3.8,<4.0" +python = ">=3.9,<3.12" +infinity = "^1.5" +sortedcontainers = "^2.4.0" [tool.poetry.group.dev.dependencies] pytest = "^7.2.0" @@ -19,6 +21,13 @@ pytest-cov = "^4.0.0" mypy = "^1.5.1" pre-commit = "^3.4.0" tox = "^4.11.1" +nose = "^1.3.7" +numpy = "^1.26.3" +pandas = "^2.2.0" +scipy = "^1.12.0" +matplotlib = "^3.8.2" +pytest-mpl = "^0.16.1" +pyarrow = "^15.0.0" [tool.poetry.group.docs.dependencies] mkdocs = "^1.4.2" diff --git a/tests/test_histogram.py b/tests/test_histogram.py index e72a2e9..05a00ab 100644 --- a/tests/test_histogram.py +++ b/tests/test_histogram.py @@ -1,4 +1,4 @@ -import nose +import pytest import traces @@ -50,19 +50,13 @@ def _test_statistics(normalized): else: n = len(data) - nose.tools.assert_almost_equal(histogram.total(), n) - nose.tools.assert_almost_equal(histogram.mean(), numpy.mean(data)) - nose.tools.assert_almost_equal(histogram.variance(), numpy.var(data)) - nose.tools.assert_almost_equal( - histogram.standard_deviation(), - numpy.std(data), - ) - nose.tools.assert_almost_equal(histogram.max(), numpy.max(data)) - nose.tools.assert_almost_equal(histogram.min(), numpy.min(data)) - nose.tools.assert_almost_equal( - histogram.quantile(0.5), - numpy.median(data), - ) + assert histogram.total() == pytest.approx(n) + assert histogram.mean() == pytest.approx(numpy.mean(data)) + assert histogram.variance() == pytest.approx(numpy.var(data)) + assert histogram.standard_deviation() == pytest.approx(numpy.std(data)) + assert histogram.max() == pytest.approx(numpy.max(data)) + assert histogram.min() == pytest.approx(numpy.min(data)) + assert histogram.quantile(0.5) == pytest.approx(numpy.median(data)) q_list = [0.001, 0.01, 0.05, 0.25, 0.5, 0.75, 0.95, 0.99, 0.999] # linear interpolation @@ -71,7 +65,7 @@ def _test_statistics(normalized): data, prob=q_list, alphap=0.5, betap=0.5, ) for i, j in zip(result, reference): - nose.tools.assert_almost_equal(i, j) + assert i == pytest.approx(j) # make sure ot throw an error for bad quantile values try: @@ -100,13 +94,13 @@ def test_quantile_interpolation(): result = histogram.quantiles(q_list, alpha=0, smallest_count=1) answer = [1.0, 1.0, 1.0, 1.0, 2.5, 5.5, 7.0, 7.0, 7.0] for i, j in zip(result, answer): - nose.tools.assert_almost_equal(i, j) + assert i == pytest.approx(j) # same thing with normalized result = normalized.quantiles( q_list, alpha=0, smallest_count=1.0 / len(data)) for i, j in zip(result, answer): - nose.tools.assert_almost_equal(i, j) + assert i == pytest.approx(j) # now do the linear interpolation method result = histogram.quantiles(q_list, alpha=0.5, smallest_count=1) @@ -114,14 +108,14 @@ def test_quantile_interpolation(): data, prob=q_list, alphap=0.5, betap=0.5, ) for i, j in zip(result, answer): - nose.tools.assert_almost_equal(i, j) + assert i == pytest.approx(j) # same thing with normalized result = normalized.quantiles( q_list, alpha=0.5, smallest_count=1.0 / len(data), ) for i, j in zip(result, answer): - nose.tools.assert_almost_equal(i, j) + assert i == pytest.approx(j) def test_addition(): @@ -142,29 +136,29 @@ def test_minmax_with_zeros(): histogram[2] += 1 histogram[3] += 0 - nose.tools.eq_(histogram.min(), 1) - nose.tools.eq_(histogram.max(), 2) + assert histogram.min() == 1 + assert histogram.max() == 2 def test_histogram_stats_with_nones(): histogram = traces.Histogram() - nose.tools.eq_(histogram.mean(), None) - nose.tools.eq_(histogram.variance(), None) - nose.tools.eq_(histogram.standard_deviation(), None) - nose.tools.eq_(histogram.min(), None) - nose.tools.eq_(histogram.max(), None) - nose.tools.eq_(histogram.median(), None) + assert histogram.mean() is None + assert histogram.variance() is None + assert histogram.standard_deviation() is None + assert histogram.min() is None + assert histogram.max() is None + assert histogram.median() is None histogram = traces.Histogram.from_dict({None: 1}, key=hash) - nose.tools.eq_(histogram.mean(), None) - nose.tools.eq_(histogram.variance(), None) - nose.tools.eq_(histogram.standard_deviation(), None) - nose.tools.eq_(histogram.min(), None) - nose.tools.eq_(histogram.max(), None) - nose.tools.eq_(histogram.median(), None) + assert histogram.mean() is None + assert histogram.variance() is None + assert histogram.standard_deviation() is None + assert histogram.min() is None + assert histogram.max() is None + assert histogram.median() is None ts = traces.TimeSeries() ts[0] = None @@ -175,4 +169,4 @@ def test_histogram_stats_with_nones(): ts[10] = None histogram = ts.distribution(start=0, end=10) - nose.tools.eq_(histogram.mean(), 6) + assert histogram.mean() == 6 From f4930ae4074dfd6e8922f85576ba2168cb837649 Mon Sep 17 00:00:00 2001 From: stringertheory Date: Fri, 2 Feb 2024 19:16:10 -0600 Subject: [PATCH 11/18] converted tests to pytest and removed nose --- poetry.lock | 14 +------ pyproject.toml | 1 - tests/test_distribution.py | 16 +++---- tests/test_iterators.py | 6 +-- tests/test_methods.py | 86 ++++++++++++++++---------------------- tests/test_missing.py | 1 - tests/test_operations.py | 6 +-- tests/test_traces.py | 8 ++-- tests/test_utils.py | 61 ++++++++++----------------- 9 files changed, 75 insertions(+), 124 deletions(-) diff --git a/poetry.lock b/poetry.lock index 197d20b..83f6f45 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1027,18 +1027,6 @@ files = [ [package.dependencies] setuptools = "*" -[[package]] -name = "nose" -version = "1.3.7" -description = "nose extends unittest to make testing easier" -optional = false -python-versions = "*" -files = [ - {file = "nose-1.3.7-py2-none-any.whl", hash = "sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a"}, - {file = "nose-1.3.7-py3-none-any.whl", hash = "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac"}, - {file = "nose-1.3.7.tar.gz", hash = "sha256:f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98"}, -] - [[package]] name = "numpy" version = "1.26.3" @@ -1950,4 +1938,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.12" -content-hash = "10e0c47519e1b6f4779fa3e80797725177c90957d87ea5379ab19655335c4fe8" +content-hash = "904f4b3ce375461e95c7903351c41402846eeb9aade3f2d0de1fda711a365f3a" diff --git a/pyproject.toml b/pyproject.toml index 57eb4a5..c94b8e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,6 @@ pytest-cov = "^4.0.0" mypy = "^1.5.1" pre-commit = "^3.4.0" tox = "^4.11.1" -nose = "^1.3.7" numpy = "^1.26.3" pandas = "^2.2.0" scipy = "^1.12.0" diff --git a/tests/test_distribution.py b/tests/test_distribution.py index 3693ae9..11d87e3 100644 --- a/tests/test_distribution.py +++ b/tests/test_distribution.py @@ -1,5 +1,5 @@ +import pytest import datetime -import nose from traces import TimeSeries, Histogram @@ -113,7 +113,7 @@ def test_distribution_empty(): # distribution with default args and no default value on empty # TimeSeries doesn't know what to do - nose.tools.assert_raises(KeyError, ts.distribution) + pytest.raises(KeyError, ts.distribution) # distribution with start and end, but no default value on empty # TimeSeries doesn't know what to do @@ -122,12 +122,12 @@ def test_distribution_empty(): # no matter what is passed in to distribution, if the default # value is not set on an empty TimeSeries this should be an error ts.distribution(mask=mask) == Histogram.from_dict({None: 1.0}) - # nose.tools.assert_raises(KeyError, ts.distribution, mask=mask) + # pytest.raises(KeyError, ts.distribution, mask=mask) ts = TimeSeries(default=0) # no mask or start/end on empty TimeSeries, don't know what to do - nose.tools.assert_raises(KeyError, ts.distribution) + pytest.raises(KeyError, ts.distribution) # start and end or mask given, is fine distribution = ts.distribution(0, 10) @@ -139,10 +139,10 @@ def test_distribution_empty(): # empty mask mask = TimeSeries(default=0) - with nose.tools.assert_raises(ValueError): + with pytest.raises(ValueError): ts.distribution(mask=mask) - with nose.tools.assert_raises(ValueError): + with pytest.raises(ValueError): ts.distribution(start=0, end=2, mask=mask) @@ -153,5 +153,5 @@ def test_none_handling(): ts[3] = (2, 0) # print(ts.distribution(normalized=False)) - assert(ts.distribution()[(0, 1)] == 0.5) - assert(ts.distribution()[(None, 0)] == 0.5) + assert ts.distribution()[(0, 1)] == 0.5 + assert ts.distribution()[(None, 0)] == 0.5 diff --git a/tests/test_iterators.py b/tests/test_iterators.py index 8fa6c0e..6d9e0b0 100644 --- a/tests/test_iterators.py +++ b/tests/test_iterators.py @@ -4,7 +4,7 @@ import pprint from infinity import inf -import nose +import pytest from traces import TimeSeries @@ -28,7 +28,7 @@ def test_iterperiods(): # timeseries with no points raises a KeyError ts = TimeSeries() - with nose.tools.assert_raises(KeyError): + with pytest.raises(KeyError): next(ts.iterperiods()) ts.set(datetime.datetime(2015, 3, 1), 1) @@ -90,7 +90,7 @@ def test_slice(): assert list(ts.slice(-1, 1).items()) == [(-1, 1), (0, 1), (1, 5)] assert list(ts.slice(-1, 0.5).items()) == [(-1, 1), (0, 1), (0.5, 1)] - nose.tools.assert_raises(ValueError, ts.slice, 2.5, 0) + pytest.raises(ValueError, ts.slice, 2.5, 0) def make_random_timeseries(): diff --git a/tests/test_methods.py b/tests/test_methods.py index 29b32ca..dd8351a 100644 --- a/tests/test_methods.py +++ b/tests/test_methods.py @@ -1,5 +1,5 @@ +import pytest import datetime -import nose import traces import pandas as pd import numpy as np @@ -58,15 +58,15 @@ def test_mean(): for type_, value_list in non_numeric_hashable_types.items(): ts = _make_ts(type_, key_list, value_list) ts.distribution(key_list[0], key_list[-1]) - nose.tools.assert_raises(TypeError, ts.mean, key_list[0], key_list[1]) + pytest.raises(TypeError, ts.mean, key_list[0], key_list[1]) # non-numeric unhashable types should raise error on distribution # and mean for type_, value_list in unhashable_types.items(): ts = _make_ts(type_, key_list, value_list) - nose.tools.assert_raises(TypeError, ts.distribution, + pytest.raises(TypeError, ts.distribution, key_list[0], key_list[1]) - nose.tools.assert_raises(TypeError, ts.mean, + pytest.raises(TypeError, ts.mean, key_list[0], key_list[1]) @@ -76,10 +76,7 @@ def test_mean_interpolate(): ts[0] = 0 ts[1] = 0 ts[3] = 20 - nose.tools.assert_almost_equal( - ts.mean(0, 2, interpolate='linear'), - 2.5, - ) + assert ts.mean(0, 2, interpolate='linear') == pytest.approx(2.5) assert ts.mean(0, 2, interpolate='linear') == 2.5 mask = traces.TimeSeries(default=False) @@ -87,14 +84,11 @@ def test_mean_interpolate(): mask[0.5] = False mask[1] = True mask[3] = False - nose.tools.assert_almost_equal( - ts.mean(0, 2, mask=mask, interpolate='linear'), - 10/3.0, - ) - nose.tools.assert_almost_equal( - ts.mean(0, 3, mask=mask, interpolate='linear'), - 8.0, - ) + + assert ts.mean(0, 2, mask=mask, interpolate='linear') == pytest.approx(10/3.0) + + assert ts.mean(0, 3, mask=mask, interpolate='linear') == pytest.approx(8.0) + def test_sample(): @@ -116,13 +110,13 @@ def curr_time(i): assert dict(ts.sample(2, time_list[0], time_list[-1])) == { curr_time(i): ts[curr_time(i)] for i in range(2, 11, 2)} - nose.tools.assert_raises( + pytest.raises( ValueError, ts.sample, -1, time_list[0], time_list[-1]) - nose.tools.assert_raises(ValueError, ts.sample, + pytest.raises(ValueError, ts.sample, 20, time_list[0], time_list[-1]) # Check second and third arguments - nose.tools.assert_raises(ValueError, ts.sample, + pytest.raises(ValueError, ts.sample, 1, time_list[3], time_list[0]) assert dict(ts.sample(1, curr_time(5), curr_time(10))) == { @@ -140,8 +134,8 @@ def curr_time(i): i: ts[i] for i in range(1, 9)} assert dict(ts.sample(0.5, 1, 8)) == { 1 + i / 2.: ts[1 + i / 2.] for i in range(0, 15)} - nose.tools.assert_raises(ValueError, ts.sample, 0.5, -traces.inf, 8) - nose.tools.assert_raises(ValueError, ts.sample, 0.5, 1, traces.inf) + pytest.raises(ValueError, ts.sample, 0.5, -traces.inf, 8) + pytest.raises(ValueError, ts.sample, 0.5, 1, traces.inf) # Test pandas compatibility pd_ts = pd.Series(dict(ts.sample(1, 1, 8))) @@ -189,7 +183,7 @@ def build_answer(step, interval): datetime.timedelta(seconds=0.1), (2, 11) ) - nose.tools.assert_raises( + pytest.raises( ValueError, ts.moving_average, 1, -1, time_list[0], time_list[-1]) # Check second arguments @@ -197,19 +191,19 @@ def build_answer(step, interval): assert output == build_answer( datetime.timedelta(seconds=.5), (2, 11, 2)) - nose.tools.assert_raises( + pytest.raises( ValueError, ts.moving_average, -1, 1, time_list[0], time_list[-1] ) - nose.tools.assert_raises( + pytest.raises( ValueError, ts.moving_average, 20, 1, time_list[0], time_list[-1] ) # Check third and fourth arguments - nose.tools.assert_raises( + pytest.raises( ValueError, ts.moving_average, 1, 1, time_list[3], time_list[0] @@ -298,7 +292,7 @@ def test_bin(): ts[start+span/3] = 5 ts[end - span/4] = 14 ts[end+span] = None - # nose.tools.assert_raises(KeyError, ts.bin, 'days') + # pytest.raises(KeyError, ts.bin, 'days') # make a mask mask = traces.TimeSeries(default=False) @@ -330,29 +324,21 @@ def test_npoints(): ts[5] = 2 ts[8] = 4 - nose.tools.eq_(ts.n_points(), 5) - nose.tools.eq_( - ts.n_points(start=0, end=8, include_start=False, include_end=False), 3) - nose.tools.eq_( - ts.n_points(start=0, end=8, include_start=False, include_end=True), 4) - nose.tools.eq_( - ts.n_points(start=0, end=8, include_start=True, include_end=False), 4) - nose.tools.eq_( - ts.n_points(start=0, end=8, include_start=True, include_end=True), 5) - nose.tools.eq_( - ts.n_points(start=1, end=8, include_start=False, include_end=False), 2) - nose.tools.eq_( - ts.n_points(start=1, end=8, include_start=False, include_end=True), 3) - nose.tools.eq_( - ts.n_points(start=1, end=8, include_start=True, include_end=False), 3) - nose.tools.eq_( - ts.n_points(start=1, end=8, include_start=True, include_end=True), 4) + assert ts.n_points() == 5 + assert ts.n_points(start=0, end=8, include_start=False, include_end=False) == 3 + assert ts.n_points(start=0, end=8, include_start=False, include_end=True) == 4 + assert ts.n_points(start=0, end=8, include_start=True, include_end=False) == 4 + assert ts.n_points(start=0, end=8, include_start=True, include_end=True) == 5 + assert ts.n_points(start=1, end=8, include_start=False, include_end=False) == 2 + assert ts.n_points(start=1, end=8, include_start=False, include_end=True) == 3 + assert ts.n_points(start=1, end=8, include_start=True, include_end=False) == 3 + assert ts.n_points(start=1, end=8, include_start=True, include_end=True) == 4 ts = traces.TimeSeries() - nose.tools.eq_(ts.n_points(), 0) - nose.tools.eq_(ts.n_points(include_start=False), 0) - nose.tools.eq_(ts.n_points(include_end=False), 0) + assert ts.n_points() == 0 + assert ts.n_points(include_start=False) == 0 + assert ts.n_points(include_end=False) == 0 def test_radd(): @@ -371,12 +357,10 @@ def test_radd(): ts3 = ts1 + ts2 - nose.tools.eq_( - list(ts3.items()), - [(-1, 1), (0, 2), (2, 0), (3, 2), (4, 0)] - ) + assert list(ts3.items()) == [(-1, 1), (0, 2), (2, 0), (3, 2), (4, 0)] + - nose.tools.assert_raises(TypeError, ts3.__radd__, 1) + pytest.raises(TypeError, ts3.__radd__, 1) def test_repr(): import traces diff --git a/tests/test_missing.py b/tests/test_missing.py index 8bd0c81..ed55210 100644 --- a/tests/test_missing.py +++ b/tests/test_missing.py @@ -1,4 +1,3 @@ -import nose import traces import unittest diff --git a/tests/test_operations.py b/tests/test_operations.py index 3a962bf..c8b0d12 100644 --- a/tests/test_operations.py +++ b/tests/test_operations.py @@ -1,7 +1,7 @@ import datetime -import nose from traces import TimeSeries from traces.decorators import ignorant, strict +import pytest def test_scalar_ops(): @@ -247,7 +247,7 @@ def test_interpolation(): assert ts.get(-1, interpolate='linear') is None assert ts.get(2, interpolate='linear') == 2 - nose.tools.assert_raises(ValueError, ts.get, 0.5, 'spline') + pytest.raises(ValueError, ts.get, 0.5, 'spline') def test_default(): @@ -268,4 +268,4 @@ def test_difference(): b = TimeSeries(data=[(1, 1), (3, 2)], default=0) c = a - b - nose.tools.eq_(list(c.items()), [(0, 0), (1, -1), (2, 1), (3, 0)]) + assert list(c.items()) == [(0, 0), (1, -1), (2, 1), (3, 0)] diff --git a/tests/test_traces.py b/tests/test_traces.py index 3372819..5f77805 100644 --- a/tests/test_traces.py +++ b/tests/test_traces.py @@ -1,7 +1,6 @@ from datetime import datetime import pickle -import nose - +import pytest from traces import TimeSeries import csv import os @@ -41,7 +40,6 @@ def test_init_data(): def test_get(): ts = TimeSeries() - # nose.tools.assert_raises(KeyError, ts.get, 0) assert ts[0] is None ts[1.2] = 1 @@ -117,7 +115,7 @@ def test_set_interval(): assert list(tsc.items()) == [(1.2, 1), (2, 5), (3, 4), (5, 0), (6, 2)] tsd = TimeSeries() - nose.tools.assert_raises(ValueError, tsd.set_interval, 4, 4, 4) + pytest.raises(ValueError, tsd.set_interval, 4, 4, 4) def test_set_interval_datetime(): @@ -206,7 +204,7 @@ def value_parse(value): assert ts[13.5] is None histogram = ts.distribution() - nose.tools.assert_almost_equal(histogram.mean(), (15 + 34 + 19 + 18) / 4.0) + assert histogram.mean() == pytest.approx((15 + 34 + 19 + 18) / 4.0) filename = 'sample.csv' with open(filename, 'w') as csvfile: diff --git a/tests/test_utils.py b/tests/test_utils.py index 358e52c..c06386e 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,6 +1,6 @@ from datetime import timedelta, datetime, date -import nose from infinity import inf +import pytest import traces.utils as utils @@ -25,7 +25,7 @@ def test_duration_to_number(): for tdelta in timedelta_list: assert utils.duration_to_number(tdelta) == tdelta.total_seconds() - nose.tools.assert_raises( + pytest.raises( NotImplementedError, utils.duration_to_number, tdelta, 'hours') for _type, item in numeric_types.items(): @@ -33,7 +33,7 @@ def test_duration_to_number(): assert utils.duration_to_number(num) == num for item in non_numeric_types: - nose.tools.assert_raises(TypeError, utils.duration_to_number, item) + pytest.raises(TypeError, utils.duration_to_number, item) def test_convert_args_to_list(): @@ -74,8 +74,8 @@ def test_convert_args_to_list(): for inputs, answers in zip(iterable_inputs, iterable_inputs_answers): assert utils.convert_args_to_list(inputs) == answers - nose.tools.assert_raises(TypeError, utils.convert_args_to_list, [2, 3, 4]) - nose.tools.assert_raises(TypeError, utils.convert_args_to_list, [2]) + pytest.raises(TypeError, utils.convert_args_to_list, [2, 3, 4]) + pytest.raises(TypeError, utils.convert_args_to_list, [2]) def test_datetime_range(): @@ -117,45 +117,28 @@ def test_datetime_range(): def test_datetime_floor(): # the date here is May 6th, 2016 (week 18) - nose.tools.eq_( - utils.datetime_floor(date(2016, 5, 6), 'years'), - datetime(2016, 1, 1) - ) - nose.tools.eq_(utils.datetime_floor(inf), inf) + assert utils.datetime_floor(date(2016, 5, 6), 'years') == datetime(2016, 1, 1) + + assert utils.datetime_floor(inf) == inf test_dt = datetime(2016, 5, 6, 11, 45, 6) - nose.tools.eq_( - utils.datetime_floor(test_dt, 'months', n_units=3), - datetime(2016, 4, 1) - ) - nose.tools.eq_( - utils.datetime_floor(test_dt, 'weeks', n_units=3), - datetime(2016, 4, 18) - ) - nose.tools.eq_( - utils.datetime_floor(test_dt, 'hours', n_units=10), - datetime(2016, 5, 6, 10) - ) - nose.tools.eq_( - utils.datetime_floor(test_dt, 'minutes', n_units=15), - datetime(2016, 5, 6, 11, 45) - ) - nose.tools.eq_( - utils.datetime_floor(test_dt, 'seconds', n_units=30), - datetime(2016, 5, 6, 11, 45) - ) - nose.tools.assert_raises( - ValueError, utils.datetime_floor, "2016-6-7" - ) - nose.tools.assert_raises( - ValueError, utils.datetime_floor, - test_dt, 'sleconds', n_units=3 - ) + assert utils.datetime_floor(test_dt, 'months', n_units=3) == datetime(2016, 4, 1) + + assert utils.datetime_floor(test_dt, 'weeks', n_units=3) == datetime(2016, 4, 18) + + assert utils.datetime_floor(test_dt, 'hours', n_units=10) == datetime(2016, 5, 6, 10) + + assert utils.datetime_floor(test_dt, 'minutes', n_units=15) == datetime(2016, 5, 6, 11, 45) + + assert utils.datetime_floor(test_dt, 'seconds', n_units=30) == datetime(2016, 5, 6, 11, 45) + + pytest.raises(ValueError, utils.datetime_floor, "2016-6-7") + pytest.raises(ValueError, utils.datetime_floor, test_dt, 'sleconds', n_units=3) def test_weekday_number(): assert utils.weekday_number(5) == 5 - nose.tools.assert_raises(ValueError, utils.weekday_number, 7) + pytest.raises(ValueError, utils.weekday_number, 7) print(utils.weekday_number("Tuesday")) assert utils.weekday_number("Tuesday") == 1 - nose.tools.assert_raises(ValueError, utils.weekday_number, 'Mooday') + pytest.raises(ValueError, utils.weekday_number, 'Mooday') From 193bbfafd8cabba38dea4f98e53b0a96df7c8843 Mon Sep 17 00:00:00 2001 From: stringertheory Date: Fri, 2 Feb 2024 19:20:27 -0600 Subject: [PATCH 12/18] allow 3.12 --- poetry.lock | 13 +++++++------ pyproject.toml | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/poetry.lock b/poetry.lock index 83f6f45..1c12658 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1135,6 +1135,7 @@ files = [ numpy = [ {version = ">=1.22.4,<2", markers = "python_version < \"3.11\""}, {version = ">=1.23.2,<2", markers = "python_version == \"3.11\""}, + {version = ">=1.26.0,<2", markers = "python_version >= \"3.12\""}, ] python-dateutil = ">=2.8.2" pytz = ">=2020.1" @@ -1292,13 +1293,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "3.5.0" +version = "3.6.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "pre_commit-3.5.0-py2.py3-none-any.whl", hash = "sha256:841dc9aef25daba9a0238cd27984041fa0467b4199fc4852e27950664919f660"}, - {file = "pre_commit-3.5.0.tar.gz", hash = "sha256:5804465c675b659b0862f07907f96295d490822a450c4c40e747d0b1c6ebcb32"}, + {file = "pre_commit-3.6.0-py2.py3-none-any.whl", hash = "sha256:c255039ef399049a5544b6ce13d135caba8f2c28c3b4033277a788f434308376"}, + {file = "pre_commit-3.6.0.tar.gz", hash = "sha256:d30bad9abf165f7785c15a21a1f46da7d0677cb00ee7ff4c579fd38922efe15d"}, ] [package.dependencies] @@ -1937,5 +1938,5 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" -python-versions = ">=3.9,<3.12" -content-hash = "904f4b3ce375461e95c7903351c41402846eeb9aade3f2d0de1fda711a365f3a" +python-versions = ">=3.9,<4.0" +content-hash = "ae356647081e9121d69ef69631a5fa01d3f03219dcdbd66d5a51e3522bdd962d" diff --git a/pyproject.toml b/pyproject.toml index c94b8e8..c3aa703 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ packages = [ ] [tool.poetry.dependencies] -python = ">=3.9,<3.12" +python = ">=3.9,<4.0" infinity = "^1.5" sortedcontainers = "^2.4.0" From 3b2900f015a41e32b41e24b2803f0e88bcfec0e4 Mon Sep 17 00:00:00 2001 From: stringertheory Date: Fri, 2 Feb 2024 19:24:12 -0600 Subject: [PATCH 13/18] running first part of pre-commit hooks --- .github/workflows/on-release-main.yml | 5 ++--- .pre-commit-config.yaml | 10 +++++----- LICENSE | 1 - Makefile | 4 ++-- docs/_themes/LICENSE | 4 ++-- docs/_themes/ms/static/flasky.css_t | 2 +- docs/_themes/ms/static/small_flask.css | 2 +- docs/_themes/ms/theme.conf | 2 +- docs/index.rst | 8 ++++---- examples/timing.py | 4 ++-- setup.cfg | 1 - tests/.coveragerc | 2 +- tests/test_methods.py | 8 +++----- tests/test_plot.py | 7 +++---- 14 files changed, 27 insertions(+), 33 deletions(-) diff --git a/.github/workflows/on-release-main.yml b/.github/workflows/on-release-main.yml index c2ac8b8..75f4e25 100644 --- a/.github/workflows/on-release-main.yml +++ b/.github/workflows/on-release-main.yml @@ -6,7 +6,7 @@ on: branches: [main] jobs: - + publish: runs-on: ubuntu-latest steps: @@ -28,7 +28,7 @@ jobs: env: PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} RELEASE_VERSION: ${{ steps.vars.outputs.tag }} - + deploy-docs: needs: publish runs-on: ubuntu-latest @@ -41,4 +41,3 @@ jobs: - name: Deploy documentation run: poetry run mkdocs gh-deploy --force - diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 91e1f3e..c1784bf 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,11 +3,11 @@ repos: rev: "v4.4.0" hooks: - id: check-case-conflict - # - id: check-merge-conflict - # - id: check-toml - # - id: check-yaml - # - id: end-of-file-fixer - # - id: trailing-whitespace + - id: check-merge-conflict + - id: check-toml + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace # - repo: https://github.com/astral-sh/ruff-pre-commit # rev: "v0.1.6" diff --git a/LICENSE b/LICENSE index 7a513dc..af7ef8d 100755 --- a/LICENSE +++ b/LICENSE @@ -8,4 +8,3 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/Makefile b/Makefile index 2a01119..b04ec8d 100644 --- a/Makefile +++ b/Makefile @@ -11,8 +11,8 @@ check: ## Run code quality tools. @poetry check --lock @echo "🚀 Linting code: Running pre-commit" @poetry run pre-commit run -a - @echo "🚀 Static type checking: Running mypy" - @poetry run mypy + # @echo "🚀 Static type checking: Running mypy" + # @poetry run mypy .PHONY: test test: ## Test the code with pytest diff --git a/docs/_themes/LICENSE b/docs/_themes/LICENSE index 77f0e21..6660860 100755 --- a/docs/_themes/LICENSE +++ b/docs/_themes/LICENSE @@ -1,10 +1,10 @@ -Modifications: +Modifications: Copyright (c) 2010 Kenneth Reitz. Copyright (c) 2016 Mike Stringer. -Original Project: +Original Project: Copyright (c) 2010 by Armin Ronacher. diff --git a/docs/_themes/ms/static/flasky.css_t b/docs/_themes/ms/static/flasky.css_t index 6cc5de0..080295d 100755 --- a/docs/_themes/ms/static/flasky.css_t +++ b/docs/_themes/ms/static/flasky.css_t @@ -459,4 +459,4 @@ a:hover tt { .revsys-inline { display: none!important; -} \ No newline at end of file +} diff --git a/docs/_themes/ms/static/small_flask.css b/docs/_themes/ms/static/small_flask.css index 8d55e95..a0af646 100755 --- a/docs/_themes/ms/static/small_flask.css +++ b/docs/_themes/ms/static/small_flask.css @@ -87,4 +87,4 @@ div.body { .github { display: none; -} \ No newline at end of file +} diff --git a/docs/_themes/ms/theme.conf b/docs/_themes/ms/theme.conf index 307a1f0..07698f6 100755 --- a/docs/_themes/ms/theme.conf +++ b/docs/_themes/ms/theme.conf @@ -4,4 +4,4 @@ stylesheet = flasky.css pygments_style = flask_theme_support.FlaskyStyle [options] -touch_icon = +touch_icon = diff --git a/docs/index.rst b/docs/index.rst index a43d3a6..7db8193 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -34,7 +34,7 @@ To install traces, run this command in your terminal: .. code:: bash $ pip install traces - + Quickstart: using traces ------------------------ @@ -99,7 +99,7 @@ one ``TimeSeries`` where the each value is a list of all lights. We also applied a ``sum`` operation to the list of states to get the ``TimeSeries`` of the number of lights that are on. - + .. figure:: _static/img/count.svg :alt: many light switch count @@ -120,7 +120,7 @@ that can be used to get summary metrics such as the mean or quantiles. It's flexible +++++++++++++ - + The measurements points (keys) in a ``TimeSeries`` can be in any units as long as they can be ordered. The values can be anything. @@ -137,7 +137,7 @@ of a grocery basket by the number of minutes within a shopping trip. To learn more, check the :ref:`examples ` and the detailed :ref:`reference `. - + More info --------- diff --git a/examples/timing.py b/examples/timing.py index 760c977..fdc0514 100644 --- a/examples/timing.py +++ b/examples/timing.py @@ -56,9 +56,9 @@ def print_results(*args): else: msg = '%s is %.1fx faster than %s' % (name_b, ratio, name_a) print >> sys.stderr, msg - + return result - + def timing_loop(n, mod=1000): for index, i in enumerate(range(n)): if not index % mod: diff --git a/setup.cfg b/setup.cfg index ad07026..a389edb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,4 +20,3 @@ universal = 1 [flake8] exclude = docs - diff --git a/tests/.coveragerc b/tests/.coveragerc index 40b3f80..a852abd 100644 --- a/tests/.coveragerc +++ b/tests/.coveragerc @@ -1,3 +1,3 @@ # .coveragerc [report] -show_missing = True \ No newline at end of file +show_missing = True diff --git a/tests/test_methods.py b/tests/test_methods.py index dd8351a..1271fe2 100644 --- a/tests/test_methods.py +++ b/tests/test_methods.py @@ -84,9 +84,9 @@ def test_mean_interpolate(): mask[0.5] = False mask[1] = True mask[3] = False - + assert ts.mean(0, 2, mask=mask, interpolate='linear') == pytest.approx(10/3.0) - + assert ts.mean(0, 3, mask=mask, interpolate='linear') == pytest.approx(8.0) @@ -358,7 +358,7 @@ def test_radd(): ts3 = ts1 + ts2 assert list(ts3.items()) == [(-1, 1), (0, 2), (2, 0), (3, 2), (4, 0)] - + pytest.raises(TypeError, ts3.__radd__, 1) @@ -376,5 +376,3 @@ def test_repr(): assert '<...' not in repr(ts) assert '<...' in str(ts) - - diff --git a/tests/test_plot.py b/tests/test_plot.py index 735de6d..5dec0f9 100644 --- a/tests/test_plot.py +++ b/tests/test_plot.py @@ -14,7 +14,7 @@ def test_plot(): ts[1] = 2 ts[3] = 1 ts[5] = 0 - + figure, axes = ts.plot() return figure @@ -29,7 +29,7 @@ def test_invalid_call(): ts = traces.TimeSeries() ts[0] = 0 ts[1] = 1 - + ts.plot(interpolate='previous') ts.plot(interpolate='linear') @@ -40,6 +40,5 @@ def test_invalid_call(): def test_empty(): ts = traces.TimeSeries() - + ts.plot() - From 0071e70bfd65ef97a1e5f0eab10332ed18544cc1 Mon Sep 17 00:00:00 2001 From: stringertheory Date: Fri, 2 Feb 2024 19:45:45 -0600 Subject: [PATCH 14/18] some ruffing, tests passing. now the harder stuff --- docs/conf.py | 69 ++++++------ examples/helloworld.py | 9 +- examples/stackystack.py | 27 +++-- examples/timing.py | 35 ++++--- pyproject.toml | 1 + setup.py | 62 ++++++----- tests/__init__.py | 1 - tests/test_compact.py | 8 +- tests/test_distribution.py | 34 +++--- tests/test_docs.py | 31 +++--- tests/test_eventseries.py | 109 ++++++++++--------- tests/test_histogram.py | 39 ++++--- tests/test_iterators.py | 49 ++++----- tests/test_methods.py | 171 ++++++++++-------------------- tests/test_missing.py | 21 +--- tests/test_operations.py | 52 +++++---- tests/test_plot.py | 17 ++- tests/test_something.py | 9 +- tests/test_traces.py | 72 ++++++------- tests/test_utils.py | 76 ++++++-------- traces/__init__.py | 11 +- traces/eventseries.py | 25 ++--- traces/histogram.py | 37 +++---- traces/plot.py | 17 ++- traces/timeseries.py | 209 +++++++++++-------------------------- traces/utils.py | 33 ++---- 26 files changed, 509 insertions(+), 715 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 6ea1049..2b197d1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # traces documentation build configuration file, created by # sphinx-quickstart @@ -16,48 +15,48 @@ # directory, add these directories to sys.path here. If the directory # is relative to the documentation root, use os.path.abspath to make # it absolute, like shown here. +import datetime import os import sys -import datetime -sys.path.insert(0, os.path.abspath('..')) + +sys.path.insert(0, os.path.abspath("..")) sys.path.append(os.path.abspath("_themes")) -import traces from recommonmark.parser import CommonMarkParser # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.mathjax', - 'sphinx.ext.viewcode', - 'sphinxcontrib.napoleon', + "sphinx.ext.autodoc", + "sphinx.ext.mathjax", + "sphinx.ext.viewcode", + "sphinxcontrib.napoleon", ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. You can specify multiple suffix # as a list of string: source_parsers = { - '.md': CommonMarkParser, + ".md": CommonMarkParser, } -source_suffix = ['.rst', '.md'] +source_suffix = [".rst", ".md"] # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = u'traces' -copyright = u'2016-{}, Mike Stringer'.format(datetime.date.today().year) -author = u'Mike Stringer' +project = "traces" +copyright = f"2016-{datetime.date.today().year}, Mike Stringer" +author = "Mike Stringer" # The version info for the project you're documenting, acts as # replacement for |version| and |release|, also used in various other # places throughout the built documents. The short X.Y version: -version = u'0.6.0' +version = "0.6.0" # The full version, including alpha/beta/rc tags: -release = u'0.6.0' +release = "0.6.0" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -69,30 +68,30 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'ms' +html_theme = "ms" # Add any paths that contain custom themes here, relative to this directory. -html_theme_path = ['_themes'] +html_theme_path = ["_themes"] # The name of an image file (relative to this directory) to use as a favicon of # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -html_favicon = '_static/img/favicon.ico' +html_favicon = "_static/img/favicon.ico" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. @@ -100,14 +99,14 @@ # Custom sidebar templates, maps document names to template names. html_sidebars = { - '**': ['side-primary.html'], + "**": ["side-primary.html"], } # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. html_show_copyright = True # Output file base name for HTML help builder. -htmlhelp_basename = 'tracesdoc' +htmlhelp_basename = "tracesdoc" latex_elements = {} @@ -115,22 +114,24 @@ # start file, target name, title, author, documentclass [howto, # manual, or own class]). latex_documents = [ - (master_doc, 'traces.tex', u'traces Documentation', - u'Mike Stringer', 'manual'), + (master_doc, "traces.tex", "traces Documentation", "Mike Stringer", "manual"), ] # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'traces', u'traces Documentation', - [author], 1) -] +man_pages = [(master_doc, "traces", "traces Documentation", [author], 1)] # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'traces', u'traces Documentation', - author, 'traces', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "traces", + "traces Documentation", + author, + "traces", + "One line description of project.", + "Miscellaneous", + ), ] diff --git a/examples/helloworld.py b/examples/helloworld.py index 48b900c..e5d8e56 100644 --- a/examples/helloworld.py +++ b/examples/helloworld.py @@ -1,6 +1,5 @@ -import sys import glob - +import sys from datetime import datetime, timedelta import traces @@ -11,14 +10,14 @@ def parse_iso_datetime(value): return datetime.strptime(value, "%Y-%m-%dT%H:%M:%S") -def read_all(pattern='data/lightbulb-*.csv'): +def read_all(pattern="data/lightbulb-*.csv"): """Read all of the CSVs in a directory matching the filename pattern as TimeSeries. """ result = [] for filename in glob.iglob(pattern): - print('reading', filename, file=sys.stderr) + print("reading", filename, file=sys.stderr) ts = traces.TimeSeries.from_csv( filename, time_column=0, @@ -54,7 +53,7 @@ def read_all(pattern='data/lightbulb-*.csv'): # look at the typical number of lights on during business hours # (8am-6pm) for each day in january -for t in datetime_range(datetime(2016, 1, 1), datetime(2016, 2, 1), 'days'): +for t in datetime_range(datetime(2016, 1, 1), datetime(2016, 2, 1), "days"): biz_start = t + timedelta(hours=8) biz_end = t + timedelta(hours=18) histogram = total_watts.distribution(start=biz_start, end=biz_end) diff --git a/examples/stackystack.py b/examples/stackystack.py index 3783955..cf07ccc 100644 --- a/examples/stackystack.py +++ b/examples/stackystack.py @@ -1,7 +1,7 @@ -import traces -import random import datetime -from infinity import inf +import random + +import traces def average(values): @@ -15,13 +15,12 @@ def average(values): class Test(traces.TimeSeries): - def stack(self, duration, start_times, operation): ts_list = [] for start in start_times: end = start + duration ts = traces.TimeSeries() - for t0, dur, value in self.iterperiods(start, end): + for t0, _dur, value in self.iterperiods(start, end): offset = t0 - start if isinstance(offset, datetime.timedelta): offset = offset.total_seconds() @@ -33,7 +32,7 @@ def stack(self, duration, start_times, operation): def xmprint(ts): for t, v in ts: # print t.isoformat(), v - print(t, v) + print((t, v)) def generate_ts(n_days): @@ -87,26 +86,26 @@ def hour_mask(n_days, hours): stack = ts.stack(datetime.timedelta(days=1), start_times, average) xmprint(stack) -print '' +print("") for hour in range(24): mask = hour_mask(n_days, hour) - print hour * 60 * 60, ts.distribution(mask=mask).mean() -print (hour + 1) * 60 * 60, ts.distribution(mask=mask).mean() + print(hour * 60 * 60, ts.distribution(mask=mask).mean()) +print((hour + 1) * 60 * 60, ts.distribution(mask=mask).mean()) -print '' +print("") unit = 60 * 60 start = 0 end = start + unit while end <= 24 * 60 * 60: value = stack.mean(start, end) - print start, value + print(start, value) start += unit end += unit -print start, value +print(start, value) -print '' +print("") for t, v in sorted(stack.moving_average(60 * 60, 60 * 60, 0, 24 * 60 * 60).items()): - print t, v + print(t, v) diff --git a/examples/timing.py b/examples/timing.py index fdc0514..65e2308 100644 --- a/examples/timing.py +++ b/examples/timing.py @@ -1,15 +1,15 @@ -import time -import pprint import collections -import sys import functools +import sys +import time TIMING_RESULTS = collections.defaultdict(list) -class timer(object): +class timer: def __call__(self, function): """Turn the object into a decorator""" + @functools.wraps(function) def wrapper(*arg, **kwargs): t1 = time.clock() @@ -17,8 +17,10 @@ def wrapper(*arg, **kwargs): t2 = time.clock() TIMING_RESULTS[function.__name__].append(t2 - t1) return result + return wrapper + def print_results(*args): args = sorted([f.__name__ for f in args]) focus = set(args) @@ -28,8 +30,8 @@ def print_results(*args): continue n = 0 sum_ = 0 - min_ = float('inf') - max_ = float('-inf') + min_ = float("inf") + max_ = float("-inf") for dt in timing_results: n += 1 sum_ += dt @@ -38,29 +40,28 @@ def print_results(*args): if dt > max_: max_ = dt avg = float(sum_) / n - msg = '{}: n={} avg={} min={} max={}'.format( - name, n, avg, min_, max_, - ) + msg = f"{name}: n={n} avg={avg} min={min_} max={max_}" result[name] = { - 'n': n, - 'avg': avg, - 'min': min_, - 'max': min_, + "n": n, + "avg": avg, + "min": min_, + "max": min_, } for i, name_a in enumerate(args): for j in range(i): name_b = args[j] - ratio = result[name_a]['min'] / result[name_b]['min'] + ratio = result[name_a]["min"] / result[name_b]["min"] if ratio <= 1: - msg = '%s is %.1fx faster than %s' % (name_a, 1 / ratio, name_b) + msg = f"{name_a} is {1 / ratio:.1f}x faster than {name_b}" else: - msg = '%s is %.1fx faster than %s' % (name_b, ratio, name_a) + msg = f"{name_b} is {ratio:.1f}x faster than {name_a}" print >> sys.stderr, msg return result + def timing_loop(n, mod=1000): for index, i in enumerate(range(n)): if not index % mod: - print >> sys.stderr, 'iteration %i' % index + print >> sys.stderr, "iteration %i" % index yield i diff --git a/pyproject.toml b/pyproject.toml index c3aa703..bed3045 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -106,3 +106,4 @@ source = ["traces"] [tool.ruff.per-file-ignores] "tests/*" = ["S101"] +"__init__.py" = ["F401"] diff --git a/setup.py b/setup.py index d4f1efd..b91b427 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- import os + from setuptools import setup @@ -14,70 +14,68 @@ def read_init(key): with open(filename) as stream: for line in stream: if key in line: - result = line.split('=')[-1].strip().replace("'", "") + result = line.split("=")[-1].strip().replace("'", "") # throw error if version isn't in __init__ file if result is None: - raise ValueError('must define %s in %s' % (key, filename)) + raise ValueError(f"must define {key} in {filename}") return result def read_author(): - return read_init('author') + return read_init("author") def read_author_email(): - return read_init('email') + return read_init("email") def read_dependencies(filename): - """Read in the dependencies from the virtualenv requirements file. - - """ + """Read in the dependencies from the virtualenv requirements file.""" dependencies = [] - filepath = os.path.join('requirements', filename) - with open(filepath, 'r') as stream: + filepath = os.path.join("requirements", filename) + with open(filepath) as stream: for line in stream: - package = line.strip().split('#')[0].strip() - if package and package.split(' ')[0] != '-r': + package = line.strip().split("#")[0].strip() + if package and package.split(" ")[0] != "-r": dependencies.append(package) return dependencies -with open("README.md", "r") as fh: +with open("README.md") as fh: long_description = fh.read() setup( - name='traces', - version='0.6.0', + name="traces", + version="0.6.0", description="A library for unevenly-spaced time series analysis.", long_description=long_description, long_description_content_type="text/markdown", author=read_author(), author_email=read_author_email(), - url='https://github.com/datascopeanalytics/traces', - packages=['traces'], - package_dir={'traces': 'traces'}, + url="https://github.com/datascopeanalytics/traces", + packages=["traces"], + package_dir={"traces": "traces"}, include_package_data=True, - install_requires=read_dependencies('python.txt'), + install_requires=read_dependencies("python.txt"), extras_require={ - 'test': read_dependencies('python-test.txt'), - 'doc': read_dependencies('python-doc.txt'), - 'dev': read_dependencies('python-dev.txt'), - 'pandas': ['pandas'], + "test": read_dependencies("python-test.txt"), + "doc": read_dependencies("python-doc.txt"), + "dev": read_dependencies("python-dev.txt"), + "pandas": ["pandas"], }, license="MIT license", zip_safe=False, - keywords='traces', + keywords="traces", classifiers=[ - 'Development Status :: 4 - Beta', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: MIT License', - 'Natural Language :: English', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Natural Language :: English", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", ], - test_suite='nose.collector', + test_suite="nose.collector", ) diff --git a/tests/__init__.py b/tests/__init__.py index 40a96af..e69de29 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/tests/test_compact.py b/tests/test_compact.py index 7782d0c..8e07e11 100644 --- a/tests/test_compact.py +++ b/tests/test_compact.py @@ -1,13 +1,11 @@ -import traces - import random +import traces + def test_compact(): - # since this is random, do it a bunch of times - for n_trial in range(100): - + for _n_trial in range(100): # make two time series, one compact and one not test_ts = traces.TimeSeries() compact_ts = traces.TimeSeries() diff --git a/tests/test_distribution.py b/tests/test_distribution.py index 11d87e3..b63b34a 100644 --- a/tests/test_distribution.py +++ b/tests/test_distribution.py @@ -1,10 +1,11 @@ -import pytest import datetime -from traces import TimeSeries, Histogram +import pytest -def test_distribution(): +from traces import Histogram, TimeSeries + +def test_distribution(): start = datetime.datetime(2015, 3, 1) # v. simple @@ -17,7 +18,9 @@ def test_distribution(): # not normalized distribution = a.distribution( - start=start, end=end, normalized=False, + start=start, + end=end, + normalized=False, ) assert distribution[0] == 24 * 60 * 60 * 2 # two days assert distribution[1] == 24 * 60 * 60 * 2 @@ -29,7 +32,6 @@ def test_distribution(): def test_default_values(): - # v. simple a = TimeSeries() a.set(datetime.datetime(2015, 3, 1), 1) @@ -47,7 +49,6 @@ def test_default_values(): def test_mask(): - start = datetime.datetime(2015, 3, 1) # v. simple @@ -64,21 +65,25 @@ def test_mask(): # not normalized distribution = a.distribution( - start=start, end=end, normalized=False, mask=mask, + start=start, + end=end, + normalized=False, + mask=mask, ) assert distribution[0] == 24 * 60 * 60 # one day assert distribution[1] == 24 * 60 * 60 # normalized distribution = a.distribution( - start=start, end=end, mask=mask, + start=start, + end=end, + mask=mask, ) assert distribution[0] == 0.5 assert distribution[1] == 0.5 def test_integer_times(): - # v. simple a = TimeSeries() a[0] = 1 @@ -94,17 +99,16 @@ def test_integer_times(): def test_distribution_set(): time_series = TimeSeries() - time_series[1.2] = {'broccoli'} - time_series[1.4] = {'broccoli', 'orange'} - time_series[1.7] = {'broccoli', 'orange', 'banana'} - time_series[2.2] = {'orange', 'banana'} - time_series[3.5] = {'orange', 'banana', 'beets'} + time_series[1.2] = {"broccoli"} + time_series[1.4] = {"broccoli", "orange"} + time_series[1.7] = {"broccoli", "orange", "banana"} + time_series[2.2] = {"orange", "banana"} + time_series[3.5] = {"orange", "banana", "beets"} # TODO: How to convert the set into multiple ts? def test_distribution_empty(): - ts = TimeSeries() mask = TimeSeries(default=0) diff --git a/tests/test_docs.py b/tests/test_docs.py index 7be7acb..38831d9 100644 --- a/tests/test_docs.py +++ b/tests/test_docs.py @@ -1,20 +1,21 @@ -import traces from datetime import datetime +import traces + def test_quickstart(): time_series = traces.TimeSeries() - time_series[datetime(2042, 2, 1, 6, 0, 0)] = 0 # 6:00:00am - time_series[datetime(2042, 2, 1, 7, 45, 56)] = 1 # 7:45:56am - time_series[datetime(2042, 2, 1, 8, 51, 42)] = 0 # 8:51:42am - time_series[datetime(2042, 2, 1, 12, 3, 56)] = 1 # 12:03:56am - time_series[datetime(2042, 2, 1, 12, 7, 13)] = 0 # 12:07:13am + time_series[datetime(2042, 2, 1, 6, 0, 0)] = 0 # 6:00:00am + time_series[datetime(2042, 2, 1, 7, 45, 56)] = 1 # 7:45:56am + time_series[datetime(2042, 2, 1, 8, 51, 42)] = 0 # 8:51:42am + time_series[datetime(2042, 2, 1, 12, 3, 56)] = 1 # 12:03:56am + time_series[datetime(2042, 2, 1, 12, 7, 13)] = 0 # 12:07:13am - assert time_series[datetime(2042, 2, 1, 11, 0, 0)] == 0 + assert time_series[datetime(2042, 2, 1, 11, 0, 0)] == 0 distribution = time_series.distribution( - start=datetime(2042, 2, 1, 6, 0, 0), # 6:00am - end=datetime(2042, 2, 1, 13, 0, 0) # 1:00pm + start=datetime(2042, 2, 1, 6, 0, 0), # 6:00am + end=datetime(2042, 2, 1, 13, 0, 0), # 1:00pm ) assert distribution[1] == 0.16440476190476191 @@ -22,13 +23,13 @@ def test_quickstart(): def test_reference(): cart = traces.TimeSeries() - cart[1.2] = {'broccoli'} - cart[1.7] = {'broccoli', 'apple'} - cart[2.2] = {'apple'} - cart[3.5] = {'apple', 'beets'} + cart[1.2] = {"broccoli"} + cart[1.7] = {"broccoli", "apple"} + cart[2.2] = {"apple"} + cart[3.5] = {"apple", "beets"} - assert cart[2] == {'broccoli', 'apple'} + assert cart[2] == {"broccoli", "apple"} assert cart[-1] is None cart = traces.TimeSeries(default=set()) - assert cart[-1] == set([]) + assert cart[-1] == set() diff --git a/tests/test_eventseries.py b/tests/test_eventseries.py index 10915c2..6d0ad71 100644 --- a/tests/test_eventseries.py +++ b/tests/test_eventseries.py @@ -1,6 +1,7 @@ -from traces import EventSeries, TimeSeries import pandas as pd +from traces import EventSeries, TimeSeries + def test_init_data(): es = EventSeries([0, 0, 6, 8.7, 10]) @@ -14,31 +15,41 @@ def test_init_data(): def test_cumsum(): # Test with basic timestamp data - data = ['2018-10-15T16:45:01', '2019-04-16T13:08:26', - '2019-02-22T12:05:08', '2019-04-16T13:09:06', - '2019-04-16T13:09:13', '2019-04-16T13:09:28', - '2019-04-16T13:09:29', '2019-04-16T13:10:20', - '2019-04-16T13:10:30', '2019-03-08T16:46:48', - '2019-04-16T13:09:29', '2019-04-16T13:10:20'] + data = [ + "2018-10-15T16:45:01", + "2019-04-16T13:08:26", + "2019-02-22T12:05:08", + "2019-04-16T13:09:06", + "2019-04-16T13:09:13", + "2019-04-16T13:09:28", + "2019-04-16T13:09:29", + "2019-04-16T13:10:20", + "2019-04-16T13:10:30", + "2019-03-08T16:46:48", + "2019-04-16T13:09:29", + "2019-04-16T13:10:20", + ] es = EventSeries(pd.to_datetime(data)) - ref = {pd.Timestamp('2018-10-15 16:45:01'): 1, - pd.Timestamp('2019-02-22 12:05:08'): 2, - pd.Timestamp('2019-03-08 16:46:48'): 3, - pd.Timestamp('2019-04-16 13:08:26'): 4, - pd.Timestamp('2019-04-16 13:09:06'): 5, - pd.Timestamp('2019-04-16 13:09:13'): 6, - pd.Timestamp('2019-04-16 13:09:28'): 7, - pd.Timestamp('2019-04-16 13:09:29'): 9, - pd.Timestamp('2019-04-16 13:10:20'): 11, - pd.Timestamp('2019-04-16 13:10:30'): 12} + ref = { + pd.Timestamp("2018-10-15 16:45:01"): 1, + pd.Timestamp("2019-02-22 12:05:08"): 2, + pd.Timestamp("2019-03-08 16:46:48"): 3, + pd.Timestamp("2019-04-16 13:08:26"): 4, + pd.Timestamp("2019-04-16 13:09:06"): 5, + pd.Timestamp("2019-04-16 13:09:13"): 6, + pd.Timestamp("2019-04-16 13:09:28"): 7, + pd.Timestamp("2019-04-16 13:09:29"): 9, + pd.Timestamp("2019-04-16 13:10:20"): 11, + pd.Timestamp("2019-04-16 13:10:30"): 12, + } reference = TimeSeries(ref, default=0) assert es.cumsum() == reference # check default is 0 - assert es.cumsum()[pd.Timestamp('2015-01-01')] == 0 + assert es.cumsum()[pd.Timestamp("2015-01-01")] == 0 # Test Empty Series es = EventSeries() @@ -46,52 +57,50 @@ def test_cumsum(): def test_events_between(): - data = ['2018-10-15T16:45:01', '2019-04-16T13:08:26', - '2019-02-22T12:05:08', '2019-04-16T13:09:06', - '2019-04-16T13:09:13', '2019-04-16T13:09:28', - '2019-04-16T13:09:29', '2019-04-16T13:10:20', - '2019-04-16T13:10:30', '2019-03-08T16:46:48', - '2019-04-16T13:09:29', '2019-04-16T13:10:20'] + data = [ + "2018-10-15T16:45:01", + "2019-04-16T13:08:26", + "2019-02-22T12:05:08", + "2019-04-16T13:09:06", + "2019-04-16T13:09:13", + "2019-04-16T13:09:28", + "2019-04-16T13:09:29", + "2019-04-16T13:10:20", + "2019-04-16T13:10:30", + "2019-03-08T16:46:48", + "2019-04-16T13:09:29", + "2019-04-16T13:10:20", + ] es = EventSeries(pd.to_datetime(data)) - assert es.events_between(pd.Timestamp( - '2018-01-01'), pd.Timestamp('2020-01-01')) == 12 - assert es.events_between(pd.Timestamp( - '2018-01-01'), pd.Timestamp('2019-01-01')) == 1 - assert es.events_between(pd.Timestamp( - '2020-01-01'), pd.Timestamp('2020-02-01')) == 0 - assert es.events_between(pd.Timestamp( - '2016-01-01'), pd.Timestamp('2017-02-01')) == 0 + assert es.events_between(pd.Timestamp("2018-01-01"), pd.Timestamp("2020-01-01")) == 12 + assert es.events_between(pd.Timestamp("2018-01-01"), pd.Timestamp("2019-01-01")) == 1 + assert es.events_between(pd.Timestamp("2020-01-01"), pd.Timestamp("2020-02-01")) == 0 + assert es.events_between(pd.Timestamp("2016-01-01"), pd.Timestamp("2017-02-01")) == 0 # Test closed boundaries on end points # left - assert es.events_between(pd.Timestamp('2018-10-15 16:45:01'), - pd.Timestamp('2019-04-15 12:00:00')) == 3 + assert es.events_between(pd.Timestamp("2018-10-15 16:45:01"), pd.Timestamp("2019-04-15 12:00:00")) == 3 # right - assert es.events_between(pd.Timestamp('2019-02-28 12:00:00'), - pd.Timestamp('2019-04-16 13:10:20')) == 9 + assert es.events_between(pd.Timestamp("2019-02-28 12:00:00"), pd.Timestamp("2019-04-16 13:10:20")) == 9 # both - assert es.events_between(pd.Timestamp('2019-02-22 12:05:08'), - pd.Timestamp('2019-04-16 13:10:20')) == 10 + assert es.events_between(pd.Timestamp("2019-02-22 12:05:08"), pd.Timestamp("2019-04-16 13:10:20")) == 10 def test_count_active(): - es_open = EventSeries( - ['08:00', '09:00', '13:00', '07:00', '06:30', '13:00']) - es_closed = EventSeries(['08:00', '08:30', '12:00', '12:00', '12:00']) + es_open = EventSeries(["08:00", "09:00", "13:00", "07:00", "06:30", "13:00"]) + es_closed = EventSeries(["08:00", "08:30", "12:00", "12:00", "12:00"]) ts = EventSeries.count_active(es_open, es_closed) - assert ts['06:30'] == 1 - assert ts['07:00'] == 2 - assert ts['08:00'] == 2 - assert ts['12:00'] == -1 - assert ts['13:00'] == 1 + assert ts["06:30"] == 1 + assert ts["07:00"] == 2 + assert ts["08:00"] == 2 + assert ts["12:00"] == -1 + assert ts["13:00"] == 1 def test_time_lag(): - data = ['2019-02-01', '2019-02-28', - '2019-02-22', '2019-02-16', - '2019-02-26', '2019-02-16'] + data = ["2019-02-01", "2019-02-28", "2019-02-22", "2019-02-16", "2019-02-26", "2019-02-16"] es = EventSeries(pd.to_datetime(data)) time_lag = es.time_lag() @@ -99,4 +108,4 @@ def test_time_lag(): assert time_lag[1] == pd.Timedelta(days=0) # Make sure we got the right shape - assert time_lag.shape[0] == len(data)-1 + assert time_lag.shape[0] == len(data) - 1 diff --git a/tests/test_histogram.py b/tests/test_histogram.py index 05a00ab..05abc0b 100644 --- a/tests/test_histogram.py +++ b/tests/test_histogram.py @@ -1,13 +1,13 @@ +import contextlib + +import numpy import pytest +from scipy import stats import traces -from scipy import stats -import numpy - def test_quantiles(): - data = [15, 15, 20, 20, 20, 35, 35, 40, 40, 50, 50] histogram = traces.Histogram(data) @@ -15,15 +15,13 @@ def test_quantiles(): alpha = 0.5 q_list = [0.05, 0.25, 0.5, 0.75, 0.95] q_values = histogram.quantiles(q_list, alpha=alpha, smallest_count=1) - reference = \ - stats.mstats.mquantiles(data, prob=q_list, alphap=0.5, betap=0.5) + reference = stats.mstats.mquantiles(data, prob=q_list, alphap=0.5, betap=0.5) for i, j in zip(q_values, reference): assert i == j def test_normalize(): - data = [15, 15, 20, 20, 20, 35, 35, 40, 40, 50, 50] histogram = traces.Histogram(data) normalized = histogram.normalized() @@ -32,7 +30,6 @@ def test_normalize(): def _test_statistics(normalized): - data_list = [ [1, 2, 3, 5, 6, 7], [1, 2, 3, 5, 6], @@ -42,7 +39,6 @@ def _test_statistics(normalized): ] for data in data_list: - histogram = traces.Histogram(data) if normalized: histogram = histogram.normalized() @@ -62,16 +58,17 @@ def _test_statistics(normalized): # linear interpolation result = histogram.quantiles(q_list) reference = stats.mstats.mquantiles( - data, prob=q_list, alphap=0.5, betap=0.5, + data, + prob=q_list, + alphap=0.5, + betap=0.5, ) for i, j in zip(result, reference): assert i == pytest.approx(j) # make sure ot throw an error for bad quantile values - try: + with contextlib.suppress(ValueError): histogram.quantile(-1) - except ValueError: - pass def test_statistics(): @@ -83,7 +80,6 @@ def test_normalized_statistics(): def test_quantile_interpolation(): - data = [1, 1, 1, 2, 3, 5, 6, 7] histogram = traces.Histogram(data) normalized = histogram.normalized() @@ -97,29 +93,32 @@ def test_quantile_interpolation(): assert i == pytest.approx(j) # same thing with normalized - result = normalized.quantiles( - q_list, alpha=0, smallest_count=1.0 / len(data)) + result = normalized.quantiles(q_list, alpha=0, smallest_count=1.0 / len(data)) for i, j in zip(result, answer): assert i == pytest.approx(j) # now do the linear interpolation method result = histogram.quantiles(q_list, alpha=0.5, smallest_count=1) answer = stats.mstats.mquantiles( - data, prob=q_list, alphap=0.5, betap=0.5, + data, + prob=q_list, + alphap=0.5, + betap=0.5, ) for i, j in zip(result, answer): assert i == pytest.approx(j) # same thing with normalized result = normalized.quantiles( - q_list, alpha=0.5, smallest_count=1.0 / len(data), + q_list, + alpha=0.5, + smallest_count=1.0 / len(data), ) for i, j in zip(result, answer): assert i == pytest.approx(j) def test_addition(): - hist_a = traces.Histogram([1, 1, 1, 2, 3, 5]) hist_b = traces.Histogram([0, 0, 1, 2, 2]) @@ -128,7 +127,6 @@ def test_addition(): def test_minmax_with_zeros(): - histogram = traces.Histogram() histogram[0] += 0 @@ -141,7 +139,6 @@ def test_minmax_with_zeros(): def test_histogram_stats_with_nones(): - histogram = traces.Histogram() assert histogram.mean() is None diff --git a/tests/test_iterators.py b/tests/test_iterators.py index 6d9e0b0..d7d59d3 100644 --- a/tests/test_iterators.py +++ b/tests/test_iterators.py @@ -1,16 +1,13 @@ import datetime -import random -import sys import pprint +import random -from infinity import inf import pytest from traces import TimeSeries def test_iterintervals(): - ts = TimeSeries() ts.set(datetime.datetime(2015, 3, 1), 1) ts.set(datetime.datetime(2015, 3, 2), 0) @@ -19,13 +16,12 @@ def test_iterintervals(): answer = [(1, 0), (0, 1), (1, 2)] result = [] - for (t0, v0), (t1, v1) in ts.iterintervals(): + for (_t0, v0), (_t1, v1) in ts.iterintervals(): result.append((v0, v1)) assert answer == result def test_iterperiods(): - # timeseries with no points raises a KeyError ts = TimeSeries() with pytest.raises(KeyError): @@ -39,12 +35,10 @@ def test_iterperiods(): answer = [ (datetime.datetime(2015, 3, 1), datetime.datetime(2015, 3, 2), 1), (datetime.datetime(2015, 3, 2), datetime.datetime(2015, 3, 3), 0), - (datetime.datetime(2015, 3, 3), datetime.datetime(2015, 3, 4), 1)] + (datetime.datetime(2015, 3, 3), datetime.datetime(2015, 3, 4), 1), + ] result = [] - for (t0, t1, v0) in ts.iterperiods( - start=datetime.datetime(2015, 3, 1), - end=datetime.datetime(2015, 3, 4) - ): + for t0, t1, v0 in ts.iterperiods(start=datetime.datetime(2015, 3, 1), end=datetime.datetime(2015, 3, 4)): result.append((t0, t1, v0)) assert answer == result @@ -53,32 +47,31 @@ def test_iterperiods(): (datetime.datetime(2015, 3, 3), datetime.datetime(2015, 3, 4), 1), ] result = [] - for (t0, t1, v0) in ts.iterperiods( - start=datetime.datetime(2015, 3, 1), - end=datetime.datetime(2015, 3, 4), - value=1, + for t0, t1, v0 in ts.iterperiods( + start=datetime.datetime(2015, 3, 1), + end=datetime.datetime(2015, 3, 4), + value=1, ): result.append((t0, t1, v0)) assert answer == result def filter(t0, t1, value): - return True if not value else False + return bool(not value) answer = [ (datetime.datetime(2015, 3, 2), datetime.datetime(2015, 3, 3), 0), ] result = [] - for (t0, t1, v0) in ts.iterperiods( - start=datetime.datetime(2015, 3, 1), - end=datetime.datetime(2015, 3, 4), - value=filter, + for t0, t1, v0 in ts.iterperiods( + start=datetime.datetime(2015, 3, 1), + end=datetime.datetime(2015, 3, 4), + value=filter, ): result.append((t0, t1, v0)) assert answer == result def test_slice(): - ts = TimeSeries(default=1) ts[0] = 1 ts[1] = 5 @@ -97,7 +90,7 @@ def make_random_timeseries(): length = random.randint(1, 10) result = TimeSeries() t = 0 - for i in range(length): + for _i in range(length): t += random.randint(0, 5) x = random.randint(0, 5) result[t] = x @@ -105,26 +98,23 @@ def make_random_timeseries(): def test_merge(): - # since this is random, do it a bunch of times - for n_trial in range(1000): - + for _n_trial in range(1000): # make a list of TimeSeries that is anywhere from 0 to 5 # long. Each TimeSeries is of random length between 0 and 20, # with random time points and random values. ts_list = [] - for i in range(random.randint(1, 5)): + for _i in range(random.randint(1, 5)): ts_list.append(make_random_timeseries()) method_a = list(TimeSeries.merge(ts_list, compact=False)) method_b = list(TimeSeries.iter_merge(ts_list)) - msg = '%s != %s' % (pprint.pformat(method_a), pprint.pformat(method_b)) + msg = f"{pprint.pformat(method_a)} != {pprint.pformat(method_b)}" assert method_a == method_b, msg def test_single_merges(): - # a single empty time series ts = TimeSeries() assert TimeSeries.merge([ts]) == TimeSeries(default=[None]) @@ -132,8 +122,7 @@ def test_single_merges(): # multiple empty time series ts_a = TimeSeries() ts_b = TimeSeries() - assert TimeSeries.merge([ts_a, ts_b]) == \ - TimeSeries(default=[None, None]) + assert TimeSeries.merge([ts_a, ts_b]) == TimeSeries(default=[None, None]) # test a single time series with only one measurement ts = TimeSeries() diff --git a/tests/test_methods.py b/tests/test_methods.py index 1271fe2..3e82f22 100644 --- a/tests/test_methods.py +++ b/tests/test_methods.py @@ -1,9 +1,10 @@ -import pytest import datetime -import traces -import pandas as pd + import numpy as np +import pandas as pd +import pytest +import traces key_list = [ datetime.datetime(2012, 1, 7), @@ -11,24 +12,18 @@ datetime.datetime(2012, 3, 20), datetime.datetime(2012, 4, 10), ] -numeric_types = { - int: [1, 2, 3, 0], - float: [1.0, 2.0, 3.0, 0.0], - bool: [True, False, True, False] -} +numeric_types = {int: [1, 2, 3, 0], float: [1.0, 2.0, 3.0, 0.0], bool: [True, False, True, False]} non_numeric_hashable_types = { - str: ['a', 'b', 'c', ''], - tuple: [('a', 1), ('b', 2), ('c', 3), ()], + str: ["a", "b", "c", ""], + tuple: [("a", 1), ("b", 2), ("c", 3), ()], } unhashable_types = { list: [[1, 1], [2, 2], [3, 3], []], - dict: [{'a': 1}, {'b': 2}, {'c': 3}, {}], + dict: [{"a": 1}, {"b": 2}, {"c": 3}, {}], set: [{1}, {1, 2}, {1, 2, 3}, set()], } all_types = dict( - list(numeric_types.items()) + - list(non_numeric_hashable_types.items()) + - list(unhashable_types.items()) + list(numeric_types.items()) + list(non_numeric_hashable_types.items()) + list(unhashable_types.items()) ) @@ -46,7 +41,6 @@ def frange(x, y, jump): def test_mean(): - # numeric hashable types should work for type_, value_list in numeric_types.items(): ts = _make_ts(type_, key_list, value_list) @@ -64,20 +58,17 @@ def test_mean(): # and mean for type_, value_list in unhashable_types.items(): ts = _make_ts(type_, key_list, value_list) - pytest.raises(TypeError, ts.distribution, - key_list[0], key_list[1]) - pytest.raises(TypeError, ts.mean, - key_list[0], key_list[1]) + pytest.raises(TypeError, ts.distribution, key_list[0], key_list[1]) + pytest.raises(TypeError, ts.mean, key_list[0], key_list[1]) def test_mean_interpolate(): - ts = traces.TimeSeries() ts[0] = 0 ts[1] = 0 ts[3] = 20 - assert ts.mean(0, 2, interpolate='linear') == pytest.approx(2.5) - assert ts.mean(0, 2, interpolate='linear') == 2.5 + assert ts.mean(0, 2, interpolate="linear") == pytest.approx(2.5) + assert ts.mean(0, 2, interpolate="linear") == 2.5 mask = traces.TimeSeries(default=False) mask[0] = True @@ -85,10 +76,9 @@ def test_mean_interpolate(): mask[1] = True mask[3] = False - assert ts.mean(0, 2, mask=mask, interpolate='linear') == pytest.approx(10/3.0) - - assert ts.mean(0, 3, mask=mask, interpolate='linear') == pytest.approx(8.0) + assert ts.mean(0, 2, mask=mask, interpolate="linear") == pytest.approx(10 / 3.0) + assert ts.mean(0, 3, mask=mask, interpolate="linear") == pytest.approx(8.0) def test_sample(): @@ -96,7 +86,7 @@ def test_sample(): datetime.datetime(2016, 1, 1, 1, 1, 2), datetime.datetime(2016, 1, 1, 1, 1, 3), datetime.datetime(2016, 1, 1, 1, 1, 8), - datetime.datetime(2016, 1, 1, 1, 1, 10) + datetime.datetime(2016, 1, 1, 1, 1, 10), ] ts = _make_ts(int, time_list, [1, 2, 3, 0]) @@ -104,36 +94,26 @@ def curr_time(i): return datetime.datetime(2016, 1, 1, 1, 1, i) # Check first arguments - assert dict(ts.sample(1, time_list[0], time_list[-1])) == { - curr_time(i): ts[curr_time(i)] for i in range(2, 11)} + assert dict(ts.sample(1, time_list[0], time_list[-1])) == {curr_time(i): ts[curr_time(i)] for i in range(2, 11)} - assert dict(ts.sample(2, time_list[0], time_list[-1])) == { - curr_time(i): ts[curr_time(i)] for i in range(2, 11, 2)} + assert dict(ts.sample(2, time_list[0], time_list[-1])) == {curr_time(i): ts[curr_time(i)] for i in range(2, 11, 2)} - pytest.raises( - ValueError, ts.sample, -1, time_list[0], time_list[-1]) - pytest.raises(ValueError, ts.sample, - 20, time_list[0], time_list[-1]) + pytest.raises(ValueError, ts.sample, -1, time_list[0], time_list[-1]) + pytest.raises(ValueError, ts.sample, 20, time_list[0], time_list[-1]) # Check second and third arguments - pytest.raises(ValueError, ts.sample, - 1, time_list[3], time_list[0]) + pytest.raises(ValueError, ts.sample, 1, time_list[3], time_list[0]) - assert dict(ts.sample(1, curr_time(5), curr_time(10))) == { - curr_time(i): ts[curr_time(i)] for i in range(5, 11)} + assert dict(ts.sample(1, curr_time(5), curr_time(10))) == {curr_time(i): ts[curr_time(i)] for i in range(5, 11)} - assert dict(ts.sample(1, curr_time(2), curr_time(5))) == { - curr_time(i): ts[curr_time(i)] for i in range(2, 6)} + assert dict(ts.sample(1, curr_time(2), curr_time(5))) == {curr_time(i): ts[curr_time(i)] for i in range(2, 6)} - assert dict(ts.sample(1, curr_time(0), curr_time(13))) == { - curr_time(i): ts[curr_time(i)] for i in range(0, 14)} + assert dict(ts.sample(1, curr_time(0), curr_time(13))) == {curr_time(i): ts[curr_time(i)] for i in range(0, 14)} # Check using int ts = traces.TimeSeries([[1, 2], [2, 3], [6, 1], [8, 4]]) - assert dict(ts.sample(1, 1, 8)) == { - i: ts[i] for i in range(1, 9)} - assert dict(ts.sample(0.5, 1, 8)) == { - 1 + i / 2.: ts[1 + i / 2.] for i in range(0, 15)} + assert dict(ts.sample(1, 1, 8)) == {i: ts[i] for i in range(1, 9)} + assert dict(ts.sample(0.5, 1, 8)) == {1 + i / 2.0: ts[1 + i / 2.0] for i in range(0, 15)} pytest.raises(ValueError, ts.sample, 0.5, -traces.inf, 8) pytest.raises(ValueError, ts.sample, 0.5, 1, traces.inf) @@ -148,7 +128,7 @@ def test_moving_average(): datetime.datetime(2016, 1, 1, 1, 1, 2), datetime.datetime(2016, 1, 1, 1, 1, 3), datetime.datetime(2016, 1, 1, 1, 1, 8), - datetime.datetime(2016, 1, 1, 1, 1, 10) + datetime.datetime(2016, 1, 1, 1, 1, 10), ] ts = _make_ts(int, time_list, [1, 2, 3, 0]) @@ -162,98 +142,66 @@ def build_answer(step, interval): try: answer[t] = ts.mean(t - step, t + step) except TypeError as e: - if 'NoneType' in str(e): + if "NoneType" in str(e): answer[t] = None else: - raise e + raise return answer # Check first arguments - output = dict( - ts.moving_average( - sampling_period=1, - window_size=2, - start=time_list[0], - end=time_list[-1] - )) + output = dict(ts.moving_average(sampling_period=1, window_size=2, start=time_list[0], end=time_list[-1])) assert output == build_answer(datetime.timedelta(seconds=1), (2, 11)) output = dict(ts.moving_average(1, 0.2, time_list[0], time_list[-1])) - assert output == build_answer( - datetime.timedelta(seconds=0.1), (2, 11) - ) + assert output == build_answer(datetime.timedelta(seconds=0.1), (2, 11)) - pytest.raises( - ValueError, ts.moving_average, 1, -1, time_list[0], time_list[-1]) + pytest.raises(ValueError, ts.moving_average, 1, -1, time_list[0], time_list[-1]) # Check second arguments output = dict(ts.moving_average(2, 1, time_list[0], time_list[-1])) - assert output == build_answer( - datetime.timedelta(seconds=.5), (2, 11, 2)) - - pytest.raises( - ValueError, - ts.moving_average, - -1, 1, time_list[0], time_list[-1] - ) - pytest.raises( - ValueError, - ts.moving_average, - 20, 1, time_list[0], time_list[-1] - ) + assert output == build_answer(datetime.timedelta(seconds=0.5), (2, 11, 2)) + + pytest.raises(ValueError, ts.moving_average, -1, 1, time_list[0], time_list[-1]) + pytest.raises(ValueError, ts.moving_average, 20, 1, time_list[0], time_list[-1]) # Check third and fourth arguments - pytest.raises( - ValueError, - ts.moving_average, - 1, 1, time_list[3], time_list[0] - ) + pytest.raises(ValueError, ts.moving_average, 1, 1, time_list[3], time_list[0]) output = dict(ts.moving_average(1, 2, curr_time(5), curr_time(10))) - assert output == build_answer( - datetime.timedelta(seconds=1), (5, 11) - ) + assert output == build_answer(datetime.timedelta(seconds=1), (5, 11)) output = dict(ts.moving_average(1, 2, curr_time(2), curr_time(5))) - assert output == build_answer( - datetime.timedelta(seconds=1), (2, 6) - ) + assert output == build_answer(datetime.timedelta(seconds=1), (2, 6)) output = dict(ts.moving_average(1, 2, curr_time(0), curr_time(13))) - assert output == build_answer( - datetime.timedelta(seconds=1), (0, 14) - ) + assert output == build_answer(datetime.timedelta(seconds=1), (0, 14)) # Check using int ts = traces.TimeSeries([[1, 2], [2, 3], [6, 1], [8, 4]]) - assert dict(ts.moving_average(1, 2, 2, 8)) == { - i: ts.mean(i - 1, i + 1) for i in range(2, 9)} + assert dict(ts.moving_average(1, 2, 2, 8)) == {i: ts.mean(i - 1, i + 1) for i in range(2, 9)} assert dict(ts.moving_average(0.5, 2, 2, 8)) == { - 1 + i / 2.: ts.mean(1 + i / 2. - 1, 1 + i / 2. + 1) - for i in range(2, 15) + 1 + i / 2.0: ts.mean(1 + i / 2.0 - 1, 1 + i / 2.0 + 1) for i in range(2, 15) } # Test pandas compatibility pd_ts = pd.Series(dict(ts.moving_average(1, 2, 0, 8))) assert all(pd_ts.index[i] == i for i in range(1, 9)) assert np.isnan(pd_ts.values[0]) - assert all(pd_ts.values[i] == ts.mean(i - 1, i + 1) - for i in range(2, 9)) + assert all(pd_ts.values[i] == ts.mean(i - 1, i + 1) for i in range(2, 9)) # Test using timedelta as sampling_period ts = _make_ts(int, time_list, [1, 2, 3, 0]) sampling_period = datetime.timedelta(seconds=1) output = dict(ts.moving_average(sampling_period)) - answer = build_answer(datetime.timedelta(seconds=1), (2, 11)) + build_answer(datetime.timedelta(seconds=1), (2, 11)) assert output == build_answer(datetime.timedelta(seconds=1), (2, 11)) def test_to_bool(): - answer = {} for type_, value_list in all_types.items(): - answer[type_] = [True if i else False for i in value_list] + answer[type_] = [bool(i) for i in value_list] # numeric hashable types should work for type_, value_list in all_types.items(): @@ -264,7 +212,6 @@ def test_to_bool(): def test_get_item_by_index(): - ts = traces.TimeSeries(default=0) ts[0] = 1 ts[2] = 3 @@ -285,23 +232,23 @@ def test_bin(): end = datetime.datetime(2019, 2, 3, 8, 45, 10) # make a timeseries - span = end-start + span = end - start ts = traces.TimeSeries() - ts[start-span/2] = 2 + ts[start - span / 2] = 2 ts[start] = 12 - ts[start+span/3] = 5 - ts[end - span/4] = 14 - ts[end+span] = None + ts[start + span / 3] = 5 + ts[end - span / 4] = 14 + ts[end + span] = None # pytest.raises(KeyError, ts.bin, 'days') # make a mask mask = traces.TimeSeries(default=False) mask[start] = True mask[end] = False - mask[start + 3*span/10] = False - mask[start + 5*span/10] = True + mask[start + 3 * span / 10] = False + mask[start + 5 * span / 10] = True - binned = ts.bin('weeks', mask=mask) + binned = ts.bin("weeks", mask=mask) first = binned.peekitem(0) last = binned.peekitem() @@ -316,7 +263,6 @@ def test_rebin(): def test_npoints(): - ts = traces.TimeSeries() ts[0] = 4 ts[1] = 2 @@ -342,7 +288,6 @@ def test_npoints(): def test_radd(): - ts1 = traces.TimeSeries(default=0) ts1[0] = 1 ts1[2] = 0 @@ -359,20 +304,20 @@ def test_radd(): assert list(ts3.items()) == [(-1, 1), (0, 2), (2, 0), (3, 2), (4, 0)] - pytest.raises(TypeError, ts3.__radd__, 1) + def test_repr(): - import traces - import random import datetime + import traces + ts = traces.TimeSeries() t = datetime.date(2000, 1, 1) for i in range(1000): ts[t] = i t += datetime.timedelta(days=i) - assert '<...' not in repr(ts) + assert "<..." not in repr(ts) - assert '<...' in str(ts) + assert "<..." in str(ts) diff --git a/tests/test_missing.py b/tests/test_missing.py index ed55210..f056fb7 100644 --- a/tests/test_missing.py +++ b/tests/test_missing.py @@ -1,22 +1,17 @@ import traces -import unittest # @unittest.skip("not fully fleshed out yet") def test_missing(): """example code for dealing with missing datapoints""" - router_a = traces.TimeSeries([ - (-10, 0), (-7, 1), (-5, None), (0, 3), (1, 3), (5, None) - ]) + router_a = traces.TimeSeries([(-10, 0), (-7, 1), (-5, None), (0, 3), (1, 3), (5, None)]) assert router_a[-6] == 1 assert router_a[-15] is None assert not router_a[15] - router_b = traces.TimeSeries([ - (-8, 0), (-5, 0), (-2, 1), (5, 3) - ], default=0) + router_b = traces.TimeSeries([(-8, 0), (-5, 0), (-2, 1), (5, 3)], default=0) assert router_b[7] == 3 @@ -25,7 +20,7 @@ def test_missing(): for timestamp in [-10, -1, 10]: if timestamp < router_b.first_key(): router_b.default = None - for start, end, value in router_b.iterperiods(): + for start, end, _value in router_b.iterperiods(): if timestamp >= start and timestamp < end: router_b[timestamp] = None if timestamp >= router_b.last_key(): @@ -40,10 +35,7 @@ def test_missing(): # the default here should be the element returned by `count_merge([])` - clients = traces.TimeSeries.merge( - router_list, - operation=traces.operations.strict_sum - ) + clients = traces.TimeSeries.merge(router_list, operation=traces.operations.strict_sum) assert clients[-15] is None assert clients[-6] == 1 assert clients[-0.5] is None @@ -55,10 +47,7 @@ def test_missing(): assert system_uptime[-6] is True assert system_uptime[-1] is False - clients = traces.TimeSeries.merge( - router_list, - operation=traces.operations.ignorant_sum - ) + clients = traces.TimeSeries.merge(router_list, operation=traces.operations.ignorant_sum) assert clients[-15] == 0 assert clients[-6] == 1 assert clients[-0.5] == 0 diff --git a/tests/test_operations.py b/tests/test_operations.py index c8b0d12..a32efb6 100644 --- a/tests/test_operations.py +++ b/tests/test_operations.py @@ -1,8 +1,12 @@ import datetime -from traces import TimeSeries -from traces.decorators import ignorant, strict +import math +import random + import pytest +from traces import TimeSeries +from traces.decorators import ignorant + def test_scalar_ops(): a = TimeSeries() @@ -40,7 +44,6 @@ def test_scalar_ops(): def test_sum(): - a = TimeSeries() a.set(datetime.datetime(2015, 3, 1), 1) a.set(datetime.datetime(2015, 3, 2), 0) @@ -84,7 +87,6 @@ def test_sum(): def example_dictlike(): - # test overwriting keys ts = TimeSeries() ts[datetime.datetime(2010, 1, 1)] = 5 @@ -117,7 +119,6 @@ def example_dictlike(): def example_mean(): - ts = TimeSeries() ts[datetime.datetime(2010, 1, 1)] = 0 ts[datetime.datetime(2010, 1, 3, 10)] = 1 @@ -134,16 +135,16 @@ def example_mean(): for time, value in ts: print(time.isoformat(), 0.1 * value + 1.1) - print('') + print("") - timestep = {'hours': 25} + timestep = {"hours": 25} start = datetime.datetime(2010, 1, 1) while start <= datetime.datetime(2010, 2, 5): end = start + datetime.timedelta(**timestep) print(start.isoformat(), ts.mean(start, end)) start = end - print('') + print("") start = datetime.datetime(2010, 1, 1) while start <= datetime.datetime(2010, 2, 5): @@ -154,6 +155,7 @@ def example_mean(): def example_arrow(): + import arrow ts = TimeSeries() ts[arrow.Arrow(2010, 1, 1)] = 0 @@ -171,15 +173,15 @@ def example_arrow(): for time, value in ts: print(time.naive.isoformat(), 0.1 * value + 1.1) - print('') + print("") start = arrow.Arrow(2010, 1, 1) end = arrow.Arrow(2010, 2, 5) - unit = {'hours': 25} + unit = {"hours": 25} for start, end in span_range(start, end, unit): print(start.naive.isoformat(), ts.mean(start, end)) - print('') + print("") for start, end in span_range(start, end, unit): print(start.naive.isoformat(), -0.2) @@ -187,7 +189,6 @@ def example_arrow(): def example_sum(): - a = TimeSeries() a.set(datetime.datetime(2015, 3, 1), 1) a.set(datetime.datetime(2015, 3, 2), 0) @@ -213,18 +214,17 @@ def example_sum(): # output the three time series for i, ts in enumerate([a, b, c]): - - for (t0, v0), (t1, v1) in ts.iterintervals(1): + for (t0, _v0), (t1, _v1) in ts.iterintervals(1): print(t0.isoformat(), i) print(t1.isoformat(), i) - print('') + print("") - for (t0, v0), (t1, v1) in ts.iterintervals(0): + for (t0, _v0), (t1, _v1) in ts.iterintervals(0): print(t0.isoformat(), i) print(t1.isoformat(), i) - print('') + print("") # output the sum # for dt, i in sum([a, b, c]): @@ -235,19 +235,18 @@ def example_sum(): def test_interpolation(): - ts = TimeSeries(data=[(0, 0), (1, 2)]) - assert ts.get(0, interpolate='linear') == 0 - assert ts.get(0.25, interpolate='linear') == 0.5 - assert ts.get(0.5, interpolate='linear') == 1.0 - assert ts.get(0.75, interpolate='linear') == 1.5 - assert ts.get(1, interpolate='linear') == 2 + assert ts.get(0, interpolate="linear") == 0 + assert ts.get(0.25, interpolate="linear") == 0.5 + assert ts.get(0.5, interpolate="linear") == 1.0 + assert ts.get(0.75, interpolate="linear") == 1.5 + assert ts.get(1, interpolate="linear") == 2 - assert ts.get(-1, interpolate='linear') is None - assert ts.get(2, interpolate='linear') == 2 + assert ts.get(-1, interpolate="linear") is None + assert ts.get(2, interpolate="linear") == 2 - pytest.raises(ValueError, ts.get, 0.5, 'spline') + pytest.raises(ValueError, ts.get, 0.5, "spline") def test_default(): @@ -263,7 +262,6 @@ def test_default(): def test_difference(): - a = TimeSeries(data=[(0, 0), (2, 2)], default=0) b = TimeSeries(data=[(1, 1), (3, 2)], default=0) diff --git a/tests/test_plot.py b/tests/test_plot.py index 5dec0f9..b2e6697 100644 --- a/tests/test_plot.py +++ b/tests/test_plot.py @@ -1,14 +1,15 @@ -import traces import pytest +import traces + + @pytest.mark.mpl_image_compare( - savefig_kwargs={'bbox_inches': 'tight', 'dpi': 300}, + savefig_kwargs={"bbox_inches": "tight", "dpi": 300}, remove_text=True, - style='ggplot', + style="ggplot", tolerance=20, ) def test_plot(): - ts = traces.TimeSeries() ts[0] = 0 ts[1] = 2 @@ -25,20 +26,18 @@ def test_optional_import(): def test_invalid_call(): - ts = traces.TimeSeries() ts[0] = 0 ts[1] = 1 - ts.plot(interpolate='previous') - ts.plot(interpolate='linear') + ts.plot(interpolate="previous") + ts.plot(interpolate="linear") with pytest.raises(ValueError): - ts.plot(interpolate='yomama') + ts.plot(interpolate="yomama") def test_empty(): - ts = traces.TimeSeries() ts.plot() diff --git a/tests/test_something.py b/tests/test_something.py index 0ae74c1..53a5295 100644 --- a/tests/test_something.py +++ b/tests/test_something.py @@ -1,8 +1,9 @@ +import contextlib + import traces def test_compact(): - # make a v. simple time series ts = traces.TimeSeries() ts[0] = 42 @@ -24,7 +25,6 @@ def test_compact(): def test_remove(): - # v. simple time series ts = traces.TimeSeries() ts[0] = 42 @@ -32,10 +32,8 @@ def test_remove(): # asser that trying to delete a non-existent entry raises a # KeyError - try: + with contextlib.suppress(KeyError): del ts[2] - except KeyError: - pass # now delete the measurement at t=1 del ts[1] @@ -47,7 +45,6 @@ def test_remove(): def test_last_item(): - # v. simple time series ts = traces.TimeSeries() ts[0] = 42 diff --git a/tests/test_traces.py b/tests/test_traces.py index 5f77805..2d350e1 100644 --- a/tests/test_traces.py +++ b/tests/test_traces.py @@ -1,9 +1,11 @@ -from datetime import datetime +import csv +import os import pickle +from datetime import datetime + import pytest + from traces import TimeSeries -import csv -import os def test_init_data(): @@ -52,9 +54,7 @@ def test_get(): def test_exists(): - ts = TimeSeries([ - (-5, 0), (0, 23), (5, None) - ]) + ts = TimeSeries([(-5, 0), (0, 23), (5, None)]) ts_exists = ts.exists() assert ts_exists[-10] is False @@ -108,8 +108,7 @@ def test_set_interval(): tsc = TimeSeries(ts) ts.set_interval(3, 4, 4) - assert list(ts.items()) == [(1.2, 1), (2, 5), - (3, 4), (4, 4), (5, 0), (6, 2)] + assert list(ts.items()) == [(1.2, 1), (2, 5), (3, 4), (4, 4), (5, 0), (6, 2)] tsc.set_interval(3, 4, 4, compact=True) assert list(tsc.items()) == [(1.2, 1), (2, 5), (3, 4), (5, 0), (6, 2)] @@ -122,11 +121,13 @@ def test_set_interval_datetime(): ts = TimeSeries(default=400) ts[datetime(2012, 1, 4, 12)] = 5 ts[datetime(2012, 1, 9, 18)] = 10 - ts[datetime(2012, 1, 8):datetime(2012, 1, 10)] = 100 + ts[datetime(2012, 1, 8) : datetime(2012, 1, 10)] = 100 - assert list(ts.items()) == [(datetime(2012, 1, 4, 12, 0), 5), - (datetime(2012, 1, 8, 0, 0), 100), - (datetime(2012, 1, 10, 0, 0), 10)] + assert list(ts.items()) == [ + (datetime(2012, 1, 4, 12, 0), 5), + (datetime(2012, 1, 8, 0, 0), 100), + (datetime(2012, 1, 10, 0, 0), 10), + ] def test_remove_points_from_interval(): @@ -178,24 +179,19 @@ def value_parse(value): except ValueError: return None - filename = 'sample.csv' - with open(filename, 'w') as csvfile: + filename = "sample.csv" + with open(filename, "w") as csvfile: writer = csv.writer(csvfile) - writer.writerow(['hour', 'value']) - writer.writerow(['10', '15']) - writer.writerow(['11', '34']) - writer.writerow(['12', '19']) - writer.writerow(['13', 'nan']) - writer.writerow(['14', '18']) - writer.writerow(['15', 'nan']) + writer.writerow(["hour", "value"]) + writer.writerow(["10", "15"]) + writer.writerow(["11", "34"]) + writer.writerow(["12", "19"]) + writer.writerow(["13", "nan"]) + writer.writerow(["14", "18"]) + writer.writerow(["15", "nan"]) ts = TimeSeries.from_csv( - filename, - time_column=0, - time_transform=time_parse, - value_column=1, - value_transform=value_parse, - default=None + filename, time_column=0, time_transform=time_parse, value_column=1, value_transform=value_parse, default=None ) os.remove(filename) @@ -206,20 +202,20 @@ def value_parse(value): histogram = ts.distribution() assert histogram.mean() == pytest.approx((15 + 34 + 19 + 18) / 4.0) - filename = 'sample.csv' - with open(filename, 'w') as csvfile: + filename = "sample.csv" + with open(filename, "w") as csvfile: writer = csv.writer(csvfile) - writer.writerow(['hour', 'value']) - writer.writerow(['2000-01-01 10:00:00', '15']) - writer.writerow(['2000-01-01 11:00:00', '34']) - writer.writerow(['2000-01-01 12:00:00', '19']) - writer.writerow(['2000-01-01 13:00:00', 'nan']) - writer.writerow(['2000-01-01 14:00:00', '18']) - writer.writerow(['2000-01-01 15:00:00', 'nan']) + writer.writerow(["hour", "value"]) + writer.writerow(["2000-01-01 10:00:00", "15"]) + writer.writerow(["2000-01-01 11:00:00", "34"]) + writer.writerow(["2000-01-01 12:00:00", "19"]) + writer.writerow(["2000-01-01 13:00:00", "nan"]) + writer.writerow(["2000-01-01 14:00:00", "18"]) + writer.writerow(["2000-01-01 15:00:00", "nan"]) ts = TimeSeries.from_csv(filename) os.remove(filename) assert ts[datetime(2000, 1, 1, 9)] is None - assert ts[datetime(2000, 1, 1, 10, 30)] == '15' - assert ts[datetime(2000, 1, 1, 20)] == 'nan' + assert ts[datetime(2000, 1, 1, 10, 30)] == "15" + assert ts[datetime(2000, 1, 1, 20)] == "nan" diff --git a/tests/test_utils.py b/tests/test_utils.py index c06386e..0b24fa1 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,32 +1,21 @@ -from datetime import timedelta, datetime, date -from infinity import inf +from datetime import date, datetime, timedelta + import pytest +from infinity import inf import traces.utils as utils +timedelta_list = [timedelta(hours=1), timedelta(minutes=2), timedelta(seconds=5), timedelta(milliseconds=5)] -timedelta_list = [ - timedelta(hours=1), - timedelta(minutes=2), - timedelta(seconds=5), - timedelta(milliseconds=5) -] +numeric_types = {int: [1, 2, 3, 0], float: [1.0, 2.0, 3.0, 0.0]} -numeric_types = { - int: [1, 2, 3, 0], - float: [1.0, 2.0, 3.0, 0.0] -} - -non_numeric_types = [ - [2], {'a': 4}, (2, 4), 'df', 'a' -] +non_numeric_types = [[2], {"a": 4}, (2, 4), "df", "a"] def test_duration_to_number(): for tdelta in timedelta_list: assert utils.duration_to_number(tdelta) == tdelta.total_seconds() - pytest.raises( - NotImplementedError, utils.duration_to_number, tdelta, 'hours') + pytest.raises(NotImplementedError, utils.duration_to_number, tdelta, "hours") for _type, item in numeric_types.items(): for num in item: @@ -51,7 +40,7 @@ def test_convert_args_to_list(): [[[1, 2], [4, 5], [6, 7]]], [[(1, 2), (4, 5), (6, 7)]], [([1, 2], [4, 5], [6, 7])], - [((1, 2), (4, 5), (6, 7))] + [((1, 2), (4, 5), (6, 7))], ] iterable_inputs_answers = [ @@ -68,7 +57,7 @@ def test_convert_args_to_list(): [[1, 2], [4, 5], [6, 7]], [[1, 2], [4, 5], [6, 7]], [[1, 2], [4, 5], [6, 7]], - [[1, 2], [4, 5], [6, 7]] + [[1, 2], [4, 5], [6, 7]], ] for inputs, answers in zip(iterable_inputs, iterable_inputs_answers): @@ -80,60 +69,57 @@ def test_convert_args_to_list(): def test_datetime_range(): # test default options - dt_range = list(utils.datetime_range( - datetime(2016, 1, 1), datetime(2016, 2, 1), 'days')) + dt_range = list(utils.datetime_range(datetime(2016, 1, 1), datetime(2016, 2, 1), "days")) assert dt_range[0] == datetime(2016, 1, 1) assert dt_range[-1] == datetime(2016, 1, 31) assert dt_range[10] == datetime(2016, 1, 11) # test non-default options - dt_range = list(utils.datetime_range( - datetime(2016, 1, 2), - datetime(2016, 2, 1), - 'days', n_units=2, inclusive_end=True)) + dt_range = list( + utils.datetime_range(datetime(2016, 1, 2), datetime(2016, 2, 1), "days", n_units=2, inclusive_end=True) + ) assert dt_range[0] == datetime(2016, 1, 2) assert dt_range[-1] == datetime(2016, 2, 1) assert dt_range[10] == datetime(2016, 1, 22) # test units - dt_range = list(utils.datetime_range( - datetime(2016, 1, 1), datetime(2016, 2, 1), 'hours')) + dt_range = list(utils.datetime_range(datetime(2016, 1, 1), datetime(2016, 2, 1), "hours")) assert dt_range[1] - dt_range[0] == timedelta(hours=1) - dt_range = list(utils.datetime_range( - datetime(2016, 1, 1), - datetime(2016, 2, 1), - 'minutes', - n_units=10, - )) + dt_range = list( + utils.datetime_range( + datetime(2016, 1, 1), + datetime(2016, 2, 1), + "minutes", + n_units=10, + ) + ) assert dt_range[1] - dt_range[0] == timedelta(minutes=10) # test end < start - dt_range = list(utils.datetime_range( - datetime(2016, 2, 1), datetime(2016, 1, 1), 'days' - )) + dt_range = list(utils.datetime_range(datetime(2016, 2, 1), datetime(2016, 1, 1), "days")) assert dt_range == [] def test_datetime_floor(): # the date here is May 6th, 2016 (week 18) - assert utils.datetime_floor(date(2016, 5, 6), 'years') == datetime(2016, 1, 1) + assert utils.datetime_floor(date(2016, 5, 6), "years") == datetime(2016, 1, 1) assert utils.datetime_floor(inf) == inf test_dt = datetime(2016, 5, 6, 11, 45, 6) - assert utils.datetime_floor(test_dt, 'months', n_units=3) == datetime(2016, 4, 1) + assert utils.datetime_floor(test_dt, "months", n_units=3) == datetime(2016, 4, 1) - assert utils.datetime_floor(test_dt, 'weeks', n_units=3) == datetime(2016, 4, 18) + assert utils.datetime_floor(test_dt, "weeks", n_units=3) == datetime(2016, 4, 18) - assert utils.datetime_floor(test_dt, 'hours', n_units=10) == datetime(2016, 5, 6, 10) + assert utils.datetime_floor(test_dt, "hours", n_units=10) == datetime(2016, 5, 6, 10) - assert utils.datetime_floor(test_dt, 'minutes', n_units=15) == datetime(2016, 5, 6, 11, 45) + assert utils.datetime_floor(test_dt, "minutes", n_units=15) == datetime(2016, 5, 6, 11, 45) - assert utils.datetime_floor(test_dt, 'seconds', n_units=30) == datetime(2016, 5, 6, 11, 45) + assert utils.datetime_floor(test_dt, "seconds", n_units=30) == datetime(2016, 5, 6, 11, 45) pytest.raises(ValueError, utils.datetime_floor, "2016-6-7") - pytest.raises(ValueError, utils.datetime_floor, test_dt, 'sleconds', n_units=3) + pytest.raises(ValueError, utils.datetime_floor, test_dt, "sleconds", n_units=3) def test_weekday_number(): @@ -141,4 +127,4 @@ def test_weekday_number(): pytest.raises(ValueError, utils.weekday_number, 7) print(utils.weekday_number("Tuesday")) assert utils.weekday_number("Tuesday") == 1 - pytest.raises(ValueError, utils.weekday_number, 'Mooday') + pytest.raises(ValueError, utils.weekday_number, "Mooday") diff --git a/traces/__init__.py b/traces/__init__.py index ade756d..86823e3 100644 --- a/traces/__init__.py +++ b/traces/__init__.py @@ -1,13 +1,12 @@ -# -*- coding: utf-8 -*- - from infinity import inf + from traces import decorators, operations +from .eventseries import EventSeries from .histogram import Histogram from .timeseries import TimeSeries from .utils import datetime_range -from .eventseries import EventSeries -__author__ = 'Mike Stringer' -__email__ = 'mike.stringer@datascopeanalytics.com' -__version__ = '0.6.0' +__author__ = "Mike Stringer" +__email__ = "mike.stringer@datascopeanalytics.com" +__version__ = "0.6.0" diff --git a/traces/eventseries.py b/traces/eventseries.py index 8919f12..9efaaeb 100644 --- a/traces/eventseries.py +++ b/traces/eventseries.py @@ -1,8 +1,7 @@ -import sortedcontainers -import numpy as np import collections -from . import TimeSeries +import numpy as np +import sortedcontainers class EventSeries(sortedcontainers.SortedList): @@ -10,11 +9,13 @@ def __init__(self, data=None): super().__init__(data) def cumsum(self): - ''' + """ Returns a TimeSeries with each unique time in the EventSeries as an index point and with the cumulative number of events that have occured since the earliest time in the EventSeries as the value - ''' + """ + from traces import TimeSeries + # Multiple events can happen at the same time so we need to hash them # as counts c = collections.Counter(self) @@ -26,30 +27,30 @@ def cumsum(self): return TimeSeries(zip(keys, values), default=0) def events_between(self, start, end): - ''' + """ Returns the number of events that occured between `start and `end. Calculates on a closed interval, so start and end are included in the range - ''' + """ start_idx = self.bisect_left(start) end_idx = self.bisect_right(end) return end_idx - start_idx def time_lag(self): - ''' + """ Returns a `np.array` of inter event arrival times. This will only work for EventSeries of a type that have a minus operation implemented. - ''' - return (np.array(self[1:]) - np.array(self[0:-1])) + """ + return np.array(self[1:]) - np.array(self[0:-1]) @staticmethod def count_active(es_open, es_closed): - ''' + """ Calculates the running difference from two event series `es_open` is an EventSeries that adds to the cumulative sum and `es_closed` is an EventSeries of subtracts from it Returns a TimeSeries of the number of open cases at any given time, assuming 0 open cases at the earliest time in either EventSeries - ''' + """ return es_open.cumsum() - es_closed.cumsum() diff --git a/traces/histogram.py b/traces/histogram.py index 1fedfc2..1c3d042 100644 --- a/traces/histogram.py +++ b/traces/histogram.py @@ -21,37 +21,33 @@ def from_dict(cls, in_dict, *args, **kwargs): def __init__(self, data=(), **kwargs): if "key" in kwargs: - super(Histogram, self).__init__(kwargs["key"]) + super().__init__(kwargs["key"]) else: - super(Histogram, self).__init__() + super().__init__() for datum in data: self[datum] += 1 def __getitem__(self, key): try: - result = super(Histogram, self).__getitem__(key) + result = super().__getitem__(key) except KeyError: result = 0 except TypeError as error: - if "unorderable" in str(error): raise UnorderableElements(error) if "unhashable" in str(error): - msg = "Can't make histogram of unhashable type ({})".format( - type(key) - ) + msg = f"Can't make histogram of unhashable type ({type(key)})" raise UnhashableType(msg) - raise error + raise return result def __setitem__(self, key, value): try: - result = super(Histogram, self).__setitem__(key, value) + result = super().__setitem__(key, value) except TypeError as error: - if "unorderable" in str(error): raise UnorderableElements(error) @@ -59,12 +55,10 @@ def __setitem__(self, key, value): raise UnorderableElements(error) if "unhashable" in str(error): - msg = "Can't make histogram of unhashable type ({})".format( - type(key) - ) + msg = f"Can't make histogram of unhashable type ({type(key)})" raise UnhashableType(msg) - raise error + raise return result def total(self): @@ -93,9 +87,7 @@ def variance(self): return None mean = self.mean() - weighted_central_moment = sum( - count * (value - mean) ** 2 for value, count in clean.items() - ) + weighted_central_moment = sum(count * (value - mean) ** 2 for value, count in clean.items()) return weighted_central_moment / total def standard_deviation(self): @@ -125,9 +117,7 @@ def _discard_value(self, value): if value not in self: return self else: - return self.__class__.from_dict( - {k: v for k, v in self.items() if k is not value} - ) + return self.__class__.from_dict({k: v for k, v in self.items() if k is not value}) def max(self, include_zero=False): """Maximum observed value with non-zero count.""" @@ -181,9 +171,8 @@ def _quantile_function(self, alpha=0.5, smallest_count=None): # print '' def function(q): - if q < 0.0 or q > 1.0: - msg = "invalid quantile {}, need `0 <= q <= 1`".format(q) + msg = f"invalid quantile {q}, need `0 <= q <= 1`" raise ValueError(msg) elif q < q_min: q = q_min @@ -228,7 +217,9 @@ def quantiles(self, q_list, alpha=0.5, smallest_count=None): def quantile(self, q, alpha=0.5, smallest_count=None): return self.quantiles( - [q], alpha=alpha, smallest_count=smallest_count, + [q], + alpha=alpha, + smallest_count=smallest_count, )[0] def add(self, other): diff --git a/traces/plot.py b/traces/plot.py index 62ffb76..7babff0 100644 --- a/traces/plot.py +++ b/traces/plot.py @@ -58,7 +58,6 @@ def plot( aspect_ratio=None, font=None, ): - try: import matplotlib.pyplot as plt from matplotlib import font_manager @@ -67,7 +66,7 @@ def plot( raise ImportError(msg) if font is None: - available_fonts = set(f.name for f in font_manager.fontManager.ttflist) + available_fonts = {f.name for f in font_manager.fontManager.ttflist} for font in FONTS: if font in available_fonts: break @@ -78,20 +77,16 @@ def plot( except KeyError: n_unique_values = 0 scaled = min(MAX_ASPECT_POINTS, max(2, n_unique_values) - 2) - aspect_ratio = MIN_ASPECT_RATIO + ( - MAX_ASPECT_RATIO - MIN_ASPECT_RATIO - ) * (scaled / MAX_ASPECT_POINTS) + aspect_ratio = MIN_ASPECT_RATIO + (MAX_ASPECT_RATIO - MIN_ASPECT_RATIO) * (scaled / MAX_ASPECT_POINTS) try: drawstyle = INTERPOLATE_DRAWSTYLE[interpolate] except KeyError: - raise ValueError(( - "invalid value for interpolate='{}', " - "must be in {}" - ).format(interpolate, set(INTERPOLATE_DRAWSTYLE.keys()))) + raise ValueError( + f"invalid value for interpolate='{interpolate}', " f"must be in {set(INTERPOLATE_DRAWSTYLE.keys())}" + ) with plt.style.context(PLOT_STYLE): - figure, axes = plt.subplots( figsize=(figure_width, aspect_ratio * figure_width), ) @@ -102,7 +97,7 @@ def plot( else: x, y = [], [] - plot = axes.plot( + axes.plot( x, y, linewidth=linewidth, diff --git a/traces/timeseries.py b/traces/timeseries.py index ad099fa..856b30f 100644 --- a/traces/timeseries.py +++ b/traces/timeseries.py @@ -4,20 +4,21 @@ http://en.wikipedia.org/wiki/Unevenly_spaced_time_series """ + +import contextlib import csv import datetime import itertools -import pprint from queue import PriorityQueue import sortedcontainers from dateutil.parser import parse as date_parse from infinity import inf -from . import histogram, operations, utils, plot +from . import histogram, operations, plot, utils -class TimeSeries(object): +class TimeSeries: """A class to help manipulate and analyze time series that are the result of taking measurements at irregular points in time. For example, here would be a simple time series that starts at 8am and @@ -112,23 +113,20 @@ def _get_previous(self, time): return self.default else: msg = ( - "self._d.bisect_right({}) returned a negative value. " + f"self._d.bisect_right({time}) returned a negative value. " """This "can't" happen: please file an issue at """ "https://github.com/datascopeanalytics/traces/issues" - ).format(time) + ) raise ValueError(msg) def get(self, time, interpolate="previous"): - """Get the value of the time series, even in-between measured values. - - """ + """Get the value of the time series, even in-between measured values.""" try: getter = self.getter_functions[interpolate] except KeyError: - msg = ( - "unknown value '{}' for interpolate, " - "valid values are in [{}]" - ).format(interpolate, ", ".join(self.getter_functions)) + msg = ("unknown value '{}' for interpolate, " "valid values are in [{}]").format( + interpolate, ", ".join(self.getter_functions) + ) raise ValueError(msg) else: return getter(time) @@ -166,11 +164,7 @@ def set(self, time, value, compact=False): value if it's different from what it would be anyway. """ - if ( - (len(self) == 0) - or (not compact) - or (compact and self.get(time) != value) - ): + if (len(self) == 0) or (not compact) or (compact and self.get(time) != value): self._d[time] = value def set_interval(self, start, end, value, compact=False): @@ -180,7 +174,7 @@ def set_interval(self, start, end, value, compact=False): """ # for each interval to render - for i, (s, e, v) in enumerate(self.iterperiods(start, end)): + for i, (s, _e, v) in enumerate(self.iterperiods(start, end)): # look at all intervals included in the current interval # (always at least 1) if i == 0: @@ -216,9 +210,9 @@ def exists(self): otherwise """ - result = TimeSeries(default=False if self.default is None else True) + result = TimeSeries(default=self.default is not None) for t, v in self: - result[t] = False if v is None else True + result[t] = v is not None return result def remove(self, time): @@ -229,18 +223,16 @@ def remove(self, time): try: del self._d[time] except KeyError: - raise KeyError("no measurement at {}".format(time)) + raise KeyError(f"no measurement at {time}") def remove_points_from_interval(self, start, end): """Allow removal of all points from the time series within a interval [start:end]. """ - for s, e, v in self.iterperiods(start, end): - try: + for s, _e, _v in self.iterperiods(start, end): + with contextlib.suppress(KeyError): del self._d[s] - except KeyError: - pass def n_measurements(self): """Return the number of measurements in the time series.""" @@ -274,20 +266,16 @@ def format_item(item): half = MAX_LENGTH // 2 if len(self) > MAX_LENGTH: one = ", ".join(format_item(_) for _ in self._d.items()[:half]) - two = ", ".join( - format_item(_) for _ in self._d.items()[half:-half] - ) + two = ", ".join(format_item(_) for _ in self._d.items()[half:-half]) three = ", ".join(format_item(_) for _ in self._d.items()[-half:]) - truncate_string = "<...{} items...>".format(len(self) - MAX_LENGTH) + truncate_string = f"<...{len(self) - MAX_LENGTH} items...>" if len(truncate_string) < len(two): two = truncate_string items = ", ".join([one, two, three]) else: items = ", ".join(format_item(_) for _ in self._d.items()) - return "{name}({{{items}}})".format( - name=type(self).__name__, items=items, - ) + return f"{type(self).__name__}({{{items}}})" def iterintervals(self, n=2): """Iterate over groups of `n` consecutive measurement points in the @@ -311,12 +299,10 @@ def iterintervals(self, n=2): # now, zip the offset streams back together to yield tuples, # in the n=3 example it would yield: # (a, b, c), (b, c, d), ..., (w, x, y), (x, y, z) - for intervals in zip(*streams): - yield intervals + yield from zip(*streams) @staticmethod def _value_function(value): - # if value is None, don't filter if value is None: @@ -344,9 +330,7 @@ def iterperiods(self, start=None, end=None, value=None): TODO: add mask argument here. """ - start, end, mask = self._check_boundaries( - start, end, allow_infinite=False - ) + start, end, mask = self._check_boundaries(start, end, allow_infinite=False) value_function = self._value_function(value) @@ -363,7 +347,6 @@ def iterperiods(self, start=None, end=None, value=None): interval_t0, interval_value = start, start_value for interval_t1 in self._d.islice(start_index, end_index): - if value_function(interval_t0, interval_t1, interval_value): yield interval_t0, interval_t1, interval_value @@ -373,18 +356,15 @@ def iterperiods(self, start=None, end=None, value=None): interval_value = self[interval_t0] # yield the time, duration, and value of the final period - if interval_t0 < end: - if value_function(interval_t0, end, interval_value): - yield interval_t0, end, interval_value + if interval_t0 < end and value_function(interval_t0, end, interval_value): + yield interval_t0, end, interval_value def slice(self, start, end): """Return an equivalent TimeSeries that only has points between `start` and `end` (always starting at `start`) """ - start, end, mask = self._check_boundaries( - start, end, allow_infinite=True - ) + start, end, mask = self._check_boundaries(start, end, allow_infinite=True) result = TimeSeries(default=self.default) for t0, t1, value in self.iterperiods(start, end): @@ -395,50 +375,33 @@ def slice(self, start, end): return result def _check_regularization(self, start, end, sampling_period=None): - # only do these checks if sampling period is given if sampling_period is not None: - # cast to both seconds and timedelta for error checking if isinstance(sampling_period, datetime.timedelta): sampling_period_seconds = sampling_period.total_seconds() sampling_period_timedelta = sampling_period else: sampling_period_seconds = sampling_period - sampling_period_timedelta = datetime.timedelta( - seconds=sampling_period - ) + sampling_period_timedelta = datetime.timedelta(seconds=sampling_period) if sampling_period_seconds <= 0: msg = "sampling_period must be > 0" raise ValueError(msg) if sampling_period_seconds > utils.duration_to_number(end - start): - msg = ( - "sampling_period " - "is greater than the duration between " - "start and end." - ) + msg = "sampling_period " "is greater than the duration between " "start and end." raise ValueError(msg) - if isinstance(start, datetime.date): - sampling_period = sampling_period_timedelta - else: - sampling_period = sampling_period_seconds + sampling_period = sampling_period_timedelta if isinstance(start, datetime.date) else sampling_period_seconds return sampling_period - def sample( - self, sampling_period, start=None, end=None, interpolate="previous" - ): - """Sampling at regular time periods. - - """ + def sample(self, sampling_period, start=None, end=None, interpolate="previous"): + """Sampling at regular time periods.""" start, end, mask = self._check_boundaries(start, end) - sampling_period = self._check_regularization( - start, end, sampling_period - ) + sampling_period = self._check_regularization(start, end, sampling_period) result = [] current_time = start @@ -457,31 +420,25 @@ def moving_average( placement="center", pandas=False, ): - """Averaging over regular intervals - """ + """Averaging over regular intervals""" start, end, mask = self._check_boundaries(start, end) # default to sampling_period if not given if window_size is None: window_size = sampling_period - sampling_period = self._check_regularization( - start, end, sampling_period - ) + sampling_period = self._check_regularization(start, end, sampling_period) # convert to datetime if the times are datetimes full_window = window_size * 1.0 half_window = full_window / 2 - if isinstance(start, datetime.date) and not isinstance( - full_window, datetime.timedelta - ): + if isinstance(start, datetime.date) and not isinstance(full_window, datetime.timedelta): half_window = datetime.timedelta(seconds=half_window) full_window = datetime.timedelta(seconds=full_window) result = [] current_time = start while current_time <= end: - if placement == "center": window_start = current_time - half_window window_end = current_time + half_window @@ -492,7 +449,7 @@ def moving_average( window_start = current_time - full_window window_end = current_time else: - msg = 'unknown placement "{}"'.format(placement) + msg = f'unknown placement "{placement}"' raise ValueError(msg) # calculate mean over window and add (t, v) tuple to list @@ -502,14 +459,13 @@ def moving_average( if "NoneType" in str(e): mean = None else: - raise e + raise result.append((current_time, mean)) current_time += sampling_period # convert to pandas Series if pandas=True if pandas: - try: import pandas as pd except ImportError: @@ -517,14 +473,14 @@ def moving_average( raise ImportError(msg) result = pd.Series( - [v for t, v in result], index=[t for t, v in result], + [v for t, v in result], + index=[t for t, v in result], ) return result @staticmethod def rebin(binned, key_function): - result = sortedcontainers.SortedDict() for bin_start, value in binned.items(): new_bin_start = key_function(bin_start) @@ -545,7 +501,6 @@ def bin( smaller=None, transform="distribution", ): - # return an empty sorted dictionary if there is no time span if mask is not None and mask.is_empty(): return sortedcontainers.SortedDict() @@ -555,7 +510,8 @@ def bin( # use smaller if available if smaller: return self.rebin( - smaller, lambda x: utils.datetime_floor(x, unit, n_units), + smaller, + lambda x: utils.datetime_floor(x, unit, n_units), ) start, end, mask = self._check_boundaries(start, end, mask=mask) @@ -566,9 +522,7 @@ def bin( result = sortedcontainers.SortedDict() dt_range = utils.datetime_range(start, end, unit, n_units=n_units) for bin_start, bin_end in utils.pairwise(dt_range): - result[bin_start] = function( - bin_start, bin_end, mask=mask, normalized=False - ) + result[bin_start] = function(bin_start, bin_end, mask=mask, normalized=False) return result @@ -577,9 +531,7 @@ def mean(self, start=None, end=None, mask=None, interpolate="previous"): time range from `start` to `end`, when `mask` is truthy. """ - return self.distribution( - start=start, end=end, mask=mask, interpolate=interpolate - ).mean() + return self.distribution(start=start, end=end, mask=mask, interpolate=interpolate).mean() def distribution( self, @@ -629,16 +581,16 @@ def distribution( counter = histogram.Histogram() for i_start, i_end, _ in mask.iterperiods(value=True): for t0, t1, _ in self.iterperiods(i_start, i_end): - duration = utils.duration_to_number(t1 - t0, units="seconds",) + duration = utils.duration_to_number( + t1 - t0, + units="seconds", + ) midpoint = utils.time_midpoint(t0, t1) value = self.get(midpoint, interpolate=interpolate) try: counter[value] += duration except histogram.UnorderableElements: - - counter = histogram.Histogram.from_dict( - dict(counter), key=hash - ) + counter = histogram.Histogram.from_dict(dict(counter), key=hash) counter[value] += duration # divide by total duration if result needs to be normalized @@ -686,16 +638,9 @@ def n_points( count = 0 for i_start, i_end, _ in mask.iterperiods(value=True): + end_count = self._d.bisect_right(i_end) if include_end else self._d.bisect_left(i_end) - if include_end: - end_count = self._d.bisect_right(i_end) - else: - end_count = self._d.bisect_left(i_end) - - if include_start: - start_count = self._d.bisect_left(i_start) - else: - start_count = self._d.bisect_right(i_start) + start_count = self._d.bisect_left(i_start) if include_start else self._d.bisect_right(i_start) count += end_count - start_count @@ -710,10 +655,7 @@ def _check_time_series(self, other): """ if not isinstance(other, TimeSeries): - msg = "unsupported operand types(s) for +: %s and %s" % ( - type(self), - type(other), - ) + msg = f"unsupported operand types(s) for +: {type(self)} and {type(other)}" raise TypeError(msg) @staticmethod @@ -745,7 +687,6 @@ def _iter_merge(timeseries_list): # of the default value for each individual TimeSeries. state = [ts.default for ts in timeseries_list] while not queue.empty(): - # get the next time with a measurement from queue t, index, next_value, iterator = queue.get() @@ -815,10 +756,7 @@ def merge(cls, ts_list, compact=True, operation=None): result = cls(default=default) for t, merged in cls.iter_merge(ts_list): - if operation is None: - value = merged - else: - value = operation(merged) + value = merged if operation is None else operation(merged) result.set(t, value, compact=compact) return result @@ -841,7 +779,6 @@ def from_csv( skip_header=True, default=None, ): - # use default on class if not given if time_transform is None: time_transform = cls.csv_time_transform @@ -919,9 +856,7 @@ def function(x, y): def sum(self, other): """sum(x, y) = x(t) + y(t).""" - return TimeSeries.merge( - [self, other], operation=operations.ignorant_sum - ) + return TimeSeries.merge([self, other], operation=operations.ignorant_sum) def difference(self, other): """difference(x, y) = x(t) - y(t).""" @@ -974,7 +909,7 @@ def __radd__(self, other): """ # skip type check if other is the integer 0 - if not other == 0: + if other != 0: self._check_time_series(other) # 0 + self = self @@ -1007,7 +942,6 @@ def __ne__(self, other): return not (self == other) def _check_boundary(self, value, allow_infinite, lower_or_upper): - if lower_or_upper == "lower": infinity_value = -inf method_name = "first_key" @@ -1015,9 +949,7 @@ def _check_boundary(self, value, allow_infinite, lower_or_upper): infinity_value = inf method_name = "last_key" else: - msg = '`lower_or_upper` must be "lower" or "upper", got {}'.format( - lower_or_upper, - ) + msg = f'`lower_or_upper` must be "lower" or "upper", got {lower_or_upper}' raise ValueError(msg) if value is None: @@ -1027,16 +959,12 @@ def _check_boundary(self, value, allow_infinite, lower_or_upper): try: return getattr(self, method_name)() except IndexError: - msg = ( - "can't use '{}' for default {} boundary " - "of empty TimeSeries" - ).format(method_name, lower_or_upper) + msg = f"can't use '{method_name}' for default {lower_or_upper} boundary " "of empty TimeSeries" raise KeyError(msg) else: return value def _check_boundaries(self, start, end, mask=None, allow_infinite=False): - if mask is not None and mask.is_empty(): raise ValueError("mask can not be empty") @@ -1049,24 +977,18 @@ def _check_boundaries(self, start, end, mask=None, allow_infinite=False): end = self._check_boundary(end, allow_infinite, "upper") if start >= end: - msg = "start can't be >= end ({} >= {})".format(start, end) + msg = f"start can't be >= end ({start} >= {end})" raise ValueError(msg) start_end_mask = TimeSeries(default=False) start_end_mask[start] = True start_end_mask[end] = False - if mask is None: - mask = start_end_mask - else: - mask = mask & start_end_mask + mask = start_end_mask if mask is None else mask & start_end_mask return start, end, mask - def distribution_by_hour_of_day( - self, first=0, last=23, start=None, end=None - ): - + def distribution_by_hour_of_day(self, first=0, last=23, start=None, end=None): start, end, mask = self._check_boundaries(start, end) result = [] @@ -1076,10 +998,7 @@ def distribution_by_hour_of_day( return result - def distribution_by_day_of_week( - self, first=0, last=6, start=None, end=None - ): - + def distribution_by_day_of_week(self, first=0, last=6, start=None, end=None): start, end, mask = self._check_boundaries(start, end) result = [] @@ -1110,14 +1029,11 @@ def plot( def hour_of_day(start, end, hour): - # start should be date, or if datetime, will use date of datetime floored = utils.datetime_floor(start) domain = TimeSeries(default=False) - for day_start in utils.datetime_range( - floored, end, "days", inclusive_end=True - ): + for day_start in utils.datetime_range(floored, end, "days", inclusive_end=True): interval_start = day_start + datetime.timedelta(hours=hour) interval_end = interval_start + datetime.timedelta(hours=1) domain[interval_start] = True @@ -1129,7 +1045,6 @@ def hour_of_day(start, end, hour): def day_of_week(start, end, weekday): - # allow weekday name or number number = utils.weekday_number(weekday) @@ -1143,9 +1058,7 @@ def day_of_week(start, end, weekday): break domain = TimeSeries(default=False) - for week_start in utils.datetime_range( - first_day, end, "weeks", inclusive_end=True - ): + for week_start in utils.datetime_range(first_day, end, "weeks", inclusive_end=True): interval_start = week_start interval_end = interval_start + datetime.timedelta(days=1) domain[interval_start] = True diff --git a/traces/utils.py b/traces/utils.py index 00bd166..8c0cc51 100644 --- a/traces/utils.py +++ b/traces/utils.py @@ -1,3 +1,4 @@ +import contextlib import datetime from infinity import inf @@ -48,9 +49,7 @@ def convert_args_to_list(args): # Domain([(1, 4)]) # Domain([(1, 4), (5, 8)]) # Domain([[1, 4], [5, 8]]) - if len(args) == 1 and any( - isinstance(arg, (list, tuple)) for arg in args[0] - ): + if len(args) == 1 and any(isinstance(arg, (list, tuple)) for arg in args[0]): for item in args[0]: list_of_pairs.append(list(item)) else: @@ -65,7 +64,7 @@ def convert_args_to_list(args): if len(args) == 2: list_of_pairs.append(list(args)) else: - msg = "The argument type is invalid. {}".format(args) + msg = f"The argument type is invalid. {args}" raise TypeError(msg) return list_of_pairs @@ -102,9 +101,7 @@ def floor_datetime(dt, unit, n_units=1): elif unit == "weeks": _, isoweek, _ = dt.isocalendar() new_week = isoweek - (isoweek - 1) % n_units - return datetime.datetime.strptime( - "%d %02d 1" % (dt.year, new_week), "%Y %W %w" - ) + return datetime.datetime.strptime("%d %02d 1" % (dt.year, new_week), "%Y %W %w") elif unit == "days": new_day = dt.day - dt.day % n_units return datetime.datetime(dt.year, dt.month, new_day, 0, 0, 0) @@ -113,21 +110,16 @@ def floor_datetime(dt, unit, n_units=1): return datetime.datetime(dt.year, dt.month, dt.day, new_hour, 0, 0) elif unit == "minutes": new_minute = dt.minute - dt.minute % n_units - return datetime.datetime( - dt.year, dt.month, dt.day, dt.hour, new_minute, 0 - ) + return datetime.datetime(dt.year, dt.month, dt.day, dt.hour, new_minute, 0) elif unit == "seconds": new_second = dt.second - dt.second % n_units - return datetime.datetime( - dt.year, dt.month, dt.day, dt.hour, dt.minute, new_second - ) + return datetime.datetime(dt.year, dt.month, dt.day, dt.hour, dt.minute, new_second) else: - msg = "Unknown unit type {}".format(unit) + msg = f"Unknown unit type {unit}" raise ValueError(msg) def datetime_floor(value, unit="days", n_units=1): - # if it's a date, convert to datetime at start of day if type(value) is datetime.date: value = datetime.datetime.combine(value, datetime.time()) @@ -139,7 +131,7 @@ def datetime_floor(value, unit="days", n_units=1): elif value == inf: return inf else: - msg = "must be date, datetime, or inf; got {}".format(value) + msg = f"must be date, datetime, or inf; got {value}" raise ValueError(msg) @@ -155,7 +147,6 @@ def datetime_floor(value, unit="days", n_units=1): def weekday_number(value): - if isinstance(value, int): if 0 <= value < 7: return value @@ -168,18 +159,16 @@ def weekday_number(value): if result: return result else: - try: + with contextlib.suppress(TypeError): result = WEEKDAY_LOOKUP.get(value.lower()) - except TypeError: - pass if result: return result - msg = "must be a valid weekday, got {}".format(value) + msg = f"must be a valid weekday, got {value}" raise ValueError(msg) def pairwise(iterable): - """ given an interable `p1, p2, p3, ...` + """given an interable `p1, p2, p3, ...` it iterates through pairwise tuples `(p0, p1), (p1, p2), ...`""" it = iter(iterable) a = next(it, None) From 89e3599183bd83bfa0cbba27dfd997ad43814860 Mon Sep 17 00:00:00 2001 From: stringertheory Date: Fri, 2 Feb 2024 23:25:23 -0600 Subject: [PATCH 15/18] ruff passing --- .pre-commit-config.yaml | 12 +-- docs/conf.py | 12 ++- examples/stackystack.py | 6 +- examples/timing.py | 4 +- pyproject.toml | 7 +- setup.py | 81 -------------------- tests/test_distribution.py | 3 +- tests/test_eventseries.py | 65 +++++++++++++--- tests/test_histogram.py | 8 +- tests/test_iterators.py | 8 +- tests/test_methods.py | 102 +++++++++++++++++++------ tests/test_missing.py | 12 ++- tests/test_operations.py | 150 ------------------------------------- tests/test_traces.py | 18 ++++- tests/test_utils.py | 61 +++++++++++---- traces/histogram.py | 20 +++-- traces/plot.py | 16 ++-- traces/timeseries.py | 146 ++++++++++++++++++++++++++---------- traces/utils.py | 16 +++- 19 files changed, 383 insertions(+), 364 deletions(-) delete mode 100644 setup.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c1784bf..df6d201 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,12 +9,12 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - # - repo: https://github.com/astral-sh/ruff-pre-commit - # rev: "v0.1.6" - # hooks: - # - id: ruff - # args: [--exit-non-zero-on-fix] - # - id: ruff-format + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: "v0.1.6" + hooks: + - id: ruff + args: [--exit-non-zero-on-fix] + - id: ruff-format # - repo: https://github.com/pre-commit/mirrors-prettier # rev: "v3.0.3" diff --git a/docs/conf.py b/docs/conf.py index 2b197d1..2c6259c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -21,7 +21,7 @@ sys.path.insert(0, os.path.abspath("..")) sys.path.append(os.path.abspath("_themes")) -from recommonmark.parser import CommonMarkParser +from recommonmark.parser import CommonMarkParser # noqa: E402 # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom @@ -48,7 +48,7 @@ # General information about the project. project = "traces" -copyright = f"2016-{datetime.date.today().year}, Mike Stringer" +copyright = f"2016-{datetime.date.today().year}, Mike Stringer" # noqa: A001 author = "Mike Stringer" # The version info for the project you're documenting, acts as @@ -114,7 +114,13 @@ # start file, target name, title, author, documentclass [howto, # manual, or own class]). latex_documents = [ - (master_doc, "traces.tex", "traces Documentation", "Mike Stringer", "manual"), + ( + master_doc, + "traces.tex", + "traces Documentation", + "Mike Stringer", + "manual", + ), ] # One entry per manual page. List of tuples diff --git a/examples/stackystack.py b/examples/stackystack.py index cf07ccc..cf32b7d 100644 --- a/examples/stackystack.py +++ b/examples/stackystack.py @@ -54,7 +54,7 @@ def generate_ts(n_days): def hour_mask(n_days, hours): start_time = datetime.datetime(2016, 1, 1) - domain = TimeSeries(default=False) + domain = traces.TimeSeries(default=False) for day in range(n_days): start = start_time + datetime.timedelta(days=day, hours=hours) end = start + datetime.timedelta(hours=1) @@ -107,5 +107,7 @@ def hour_mask(n_days, hours): print("") -for t, v in sorted(stack.moving_average(60 * 60, 60 * 60, 0, 24 * 60 * 60).items()): +for t, v in sorted( + stack.moving_average(60 * 60, 60 * 60, 0, 24 * 60 * 60).items() +): print(t, v) diff --git a/examples/timing.py b/examples/timing.py index 65e2308..5e68619 100644 --- a/examples/timing.py +++ b/examples/timing.py @@ -55,7 +55,7 @@ def print_results(*args): msg = f"{name_a} is {1 / ratio:.1f}x faster than {name_b}" else: msg = f"{name_b} is {ratio:.1f}x faster than {name_a}" - print >> sys.stderr, msg + print(msg, file=sys.stderr) return result @@ -63,5 +63,5 @@ def print_results(*args): def timing_loop(n, mod=1000): for index, i in enumerate(range(n)): if not index % mod: - print >> sys.stderr, "iteration %i" % index + print("iteration %i" % index, file=sys.stderr) yield i diff --git a/pyproject.toml b/pyproject.toml index bed3045..e5e7549 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,7 +52,7 @@ testpaths = ["tests"] [tool.ruff] target-version = "py37" -line-length = 120 +line-length = 80 fix = true select = [ # flake8-2020 @@ -91,6 +91,10 @@ ignore = [ "E501", # DoNotAssignLambda "E731", + # Non-cryptographic random usage + "S311", + # Class attribute shadowing a Python builtin + "A003", ] [tool.ruff.format] @@ -103,7 +107,6 @@ skip_empty = true branch = true source = ["traces"] - [tool.ruff.per-file-ignores] "tests/*" = ["S101"] "__init__.py" = ["F401"] diff --git a/setup.py b/setup.py deleted file mode 100644 index b91b427..0000000 --- a/setup.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python -import os - -from setuptools import setup - - -def read_init(key): - """Parse the package __init__ file to find a variable so that it's not - in multiple places. - - """ - filename = os.path.join("traces", "__init__.py") - result = None - with open(filename) as stream: - for line in stream: - if key in line: - result = line.split("=")[-1].strip().replace("'", "") - - # throw error if version isn't in __init__ file - if result is None: - raise ValueError(f"must define {key} in {filename}") - - return result - - -def read_author(): - return read_init("author") - - -def read_author_email(): - return read_init("email") - - -def read_dependencies(filename): - """Read in the dependencies from the virtualenv requirements file.""" - dependencies = [] - filepath = os.path.join("requirements", filename) - with open(filepath) as stream: - for line in stream: - package = line.strip().split("#")[0].strip() - if package and package.split(" ")[0] != "-r": - dependencies.append(package) - return dependencies - - -with open("README.md") as fh: - long_description = fh.read() - -setup( - name="traces", - version="0.6.0", - description="A library for unevenly-spaced time series analysis.", - long_description=long_description, - long_description_content_type="text/markdown", - author=read_author(), - author_email=read_author_email(), - url="https://github.com/datascopeanalytics/traces", - packages=["traces"], - package_dir={"traces": "traces"}, - include_package_data=True, - install_requires=read_dependencies("python.txt"), - extras_require={ - "test": read_dependencies("python-test.txt"), - "doc": read_dependencies("python-doc.txt"), - "dev": read_dependencies("python-dev.txt"), - "pandas": ["pandas"], - }, - license="MIT license", - zip_safe=False, - keywords="traces", - classifiers=[ - "Development Status :: 4 - Beta", - "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", - "Natural Language :: English", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - ], - test_suite="nose.collector", -) diff --git a/tests/test_distribution.py b/tests/test_distribution.py index b63b34a..8ac8c44 100644 --- a/tests/test_distribution.py +++ b/tests/test_distribution.py @@ -125,8 +125,7 @@ def test_distribution_empty(): # no matter what is passed in to distribution, if the default # value is not set on an empty TimeSeries this should be an error - ts.distribution(mask=mask) == Histogram.from_dict({None: 1.0}) - # pytest.raises(KeyError, ts.distribution, mask=mask) + assert ts.distribution(mask=mask) == Histogram.from_dict({None: 1.0}) ts = TimeSeries(default=0) diff --git a/tests/test_eventseries.py b/tests/test_eventseries.py index 6d0ad71..20f20c3 100644 --- a/tests/test_eventseries.py +++ b/tests/test_eventseries.py @@ -73,22 +73,62 @@ def test_events_between(): ] es = EventSeries(pd.to_datetime(data)) - assert es.events_between(pd.Timestamp("2018-01-01"), pd.Timestamp("2020-01-01")) == 12 - assert es.events_between(pd.Timestamp("2018-01-01"), pd.Timestamp("2019-01-01")) == 1 - assert es.events_between(pd.Timestamp("2020-01-01"), pd.Timestamp("2020-02-01")) == 0 - assert es.events_between(pd.Timestamp("2016-01-01"), pd.Timestamp("2017-02-01")) == 0 + assert ( + es.events_between( + pd.Timestamp("2018-01-01"), pd.Timestamp("2020-01-01") + ) + == 12 + ) + assert ( + es.events_between( + pd.Timestamp("2018-01-01"), pd.Timestamp("2019-01-01") + ) + == 1 + ) + assert ( + es.events_between( + pd.Timestamp("2020-01-01"), pd.Timestamp("2020-02-01") + ) + == 0 + ) + assert ( + es.events_between( + pd.Timestamp("2016-01-01"), pd.Timestamp("2017-02-01") + ) + == 0 + ) # Test closed boundaries on end points # left - assert es.events_between(pd.Timestamp("2018-10-15 16:45:01"), pd.Timestamp("2019-04-15 12:00:00")) == 3 + assert ( + es.events_between( + pd.Timestamp("2018-10-15 16:45:01"), + pd.Timestamp("2019-04-15 12:00:00"), + ) + == 3 + ) # right - assert es.events_between(pd.Timestamp("2019-02-28 12:00:00"), pd.Timestamp("2019-04-16 13:10:20")) == 9 + assert ( + es.events_between( + pd.Timestamp("2019-02-28 12:00:00"), + pd.Timestamp("2019-04-16 13:10:20"), + ) + == 9 + ) # both - assert es.events_between(pd.Timestamp("2019-02-22 12:05:08"), pd.Timestamp("2019-04-16 13:10:20")) == 10 + assert ( + es.events_between( + pd.Timestamp("2019-02-22 12:05:08"), + pd.Timestamp("2019-04-16 13:10:20"), + ) + == 10 + ) def test_count_active(): - es_open = EventSeries(["08:00", "09:00", "13:00", "07:00", "06:30", "13:00"]) + es_open = EventSeries( + ["08:00", "09:00", "13:00", "07:00", "06:30", "13:00"] + ) es_closed = EventSeries(["08:00", "08:30", "12:00", "12:00", "12:00"]) ts = EventSeries.count_active(es_open, es_closed) @@ -100,7 +140,14 @@ def test_count_active(): def test_time_lag(): - data = ["2019-02-01", "2019-02-28", "2019-02-22", "2019-02-16", "2019-02-26", "2019-02-16"] + data = [ + "2019-02-01", + "2019-02-28", + "2019-02-22", + "2019-02-16", + "2019-02-26", + "2019-02-16", + ] es = EventSeries(pd.to_datetime(data)) time_lag = es.time_lag() diff --git a/tests/test_histogram.py b/tests/test_histogram.py index 05abc0b..a17d14a 100644 --- a/tests/test_histogram.py +++ b/tests/test_histogram.py @@ -15,7 +15,9 @@ def test_quantiles(): alpha = 0.5 q_list = [0.05, 0.25, 0.5, 0.75, 0.95] q_values = histogram.quantiles(q_list, alpha=alpha, smallest_count=1) - reference = stats.mstats.mquantiles(data, prob=q_list, alphap=0.5, betap=0.5) + reference = stats.mstats.mquantiles( + data, prob=q_list, alphap=0.5, betap=0.5 + ) for i, j in zip(q_values, reference): assert i == j @@ -93,7 +95,9 @@ def test_quantile_interpolation(): assert i == pytest.approx(j) # same thing with normalized - result = normalized.quantiles(q_list, alpha=0, smallest_count=1.0 / len(data)) + result = normalized.quantiles( + q_list, alpha=0, smallest_count=1.0 / len(data) + ) for i, j in zip(result, answer): assert i == pytest.approx(j) diff --git a/tests/test_iterators.py b/tests/test_iterators.py index d7d59d3..d3a2c0b 100644 --- a/tests/test_iterators.py +++ b/tests/test_iterators.py @@ -38,7 +38,9 @@ def test_iterperiods(): (datetime.datetime(2015, 3, 3), datetime.datetime(2015, 3, 4), 1), ] result = [] - for t0, t1, v0 in ts.iterperiods(start=datetime.datetime(2015, 3, 1), end=datetime.datetime(2015, 3, 4)): + for t0, t1, v0 in ts.iterperiods( + start=datetime.datetime(2015, 3, 1), end=datetime.datetime(2015, 3, 4) + ): result.append((t0, t1, v0)) assert answer == result @@ -55,7 +57,7 @@ def test_iterperiods(): result.append((t0, t1, v0)) assert answer == result - def filter(t0, t1, value): + def filter_function(t0, t1, value): return bool(not value) answer = [ @@ -65,7 +67,7 @@ def filter(t0, t1, value): for t0, t1, v0 in ts.iterperiods( start=datetime.datetime(2015, 3, 1), end=datetime.datetime(2015, 3, 4), - value=filter, + value=filter_function, ): result.append((t0, t1, v0)) assert answer == result diff --git a/tests/test_methods.py b/tests/test_methods.py index 3e82f22..f80ef3d 100644 --- a/tests/test_methods.py +++ b/tests/test_methods.py @@ -12,7 +12,11 @@ datetime.datetime(2012, 3, 20), datetime.datetime(2012, 4, 10), ] -numeric_types = {int: [1, 2, 3, 0], float: [1.0, 2.0, 3.0, 0.0], bool: [True, False, True, False]} +numeric_types = { + int: [1, 2, 3, 0], + float: [1.0, 2.0, 3.0, 0.0], + bool: [True, False, True, False], +} non_numeric_hashable_types = { str: ["a", "b", "c", ""], tuple: [("a", 1), ("b", 2), ("c", 3), ()], @@ -23,7 +27,9 @@ set: [{1}, {1, 2}, {1, 2, 3}, set()], } all_types = dict( - list(numeric_types.items()) + list(non_numeric_hashable_types.items()) + list(unhashable_types.items()) + list(numeric_types.items()) + + list(non_numeric_hashable_types.items()) + + list(unhashable_types.items()) ) @@ -76,7 +82,9 @@ def test_mean_interpolate(): mask[1] = True mask[3] = False - assert ts.mean(0, 2, mask=mask, interpolate="linear") == pytest.approx(10 / 3.0) + assert ts.mean(0, 2, mask=mask, interpolate="linear") == pytest.approx( + 10 / 3.0 + ) assert ts.mean(0, 3, mask=mask, interpolate="linear") == pytest.approx(8.0) @@ -94,9 +102,13 @@ def curr_time(i): return datetime.datetime(2016, 1, 1, 1, 1, i) # Check first arguments - assert dict(ts.sample(1, time_list[0], time_list[-1])) == {curr_time(i): ts[curr_time(i)] for i in range(2, 11)} + assert dict(ts.sample(1, time_list[0], time_list[-1])) == { + curr_time(i): ts[curr_time(i)] for i in range(2, 11) + } - assert dict(ts.sample(2, time_list[0], time_list[-1])) == {curr_time(i): ts[curr_time(i)] for i in range(2, 11, 2)} + assert dict(ts.sample(2, time_list[0], time_list[-1])) == { + curr_time(i): ts[curr_time(i)] for i in range(2, 11, 2) + } pytest.raises(ValueError, ts.sample, -1, time_list[0], time_list[-1]) pytest.raises(ValueError, ts.sample, 20, time_list[0], time_list[-1]) @@ -104,16 +116,24 @@ def curr_time(i): # Check second and third arguments pytest.raises(ValueError, ts.sample, 1, time_list[3], time_list[0]) - assert dict(ts.sample(1, curr_time(5), curr_time(10))) == {curr_time(i): ts[curr_time(i)] for i in range(5, 11)} + assert dict(ts.sample(1, curr_time(5), curr_time(10))) == { + curr_time(i): ts[curr_time(i)] for i in range(5, 11) + } - assert dict(ts.sample(1, curr_time(2), curr_time(5))) == {curr_time(i): ts[curr_time(i)] for i in range(2, 6)} + assert dict(ts.sample(1, curr_time(2), curr_time(5))) == { + curr_time(i): ts[curr_time(i)] for i in range(2, 6) + } - assert dict(ts.sample(1, curr_time(0), curr_time(13))) == {curr_time(i): ts[curr_time(i)] for i in range(0, 14)} + assert dict(ts.sample(1, curr_time(0), curr_time(13))) == { + curr_time(i): ts[curr_time(i)] for i in range(0, 14) + } # Check using int ts = traces.TimeSeries([[1, 2], [2, 3], [6, 1], [8, 4]]) assert dict(ts.sample(1, 1, 8)) == {i: ts[i] for i in range(1, 9)} - assert dict(ts.sample(0.5, 1, 8)) == {1 + i / 2.0: ts[1 + i / 2.0] for i in range(0, 15)} + assert dict(ts.sample(0.5, 1, 8)) == { + 1 + i / 2.0: ts[1 + i / 2.0] for i in range(0, 15) + } pytest.raises(ValueError, ts.sample, 0.5, -traces.inf, 8) pytest.raises(ValueError, ts.sample, 0.5, 1, traces.inf) @@ -149,23 +169,38 @@ def build_answer(step, interval): return answer # Check first arguments - output = dict(ts.moving_average(sampling_period=1, window_size=2, start=time_list[0], end=time_list[-1])) + output = dict( + ts.moving_average( + sampling_period=1, + window_size=2, + start=time_list[0], + end=time_list[-1], + ) + ) assert output == build_answer(datetime.timedelta(seconds=1), (2, 11)) output = dict(ts.moving_average(1, 0.2, time_list[0], time_list[-1])) assert output == build_answer(datetime.timedelta(seconds=0.1), (2, 11)) - pytest.raises(ValueError, ts.moving_average, 1, -1, time_list[0], time_list[-1]) + pytest.raises( + ValueError, ts.moving_average, 1, -1, time_list[0], time_list[-1] + ) # Check second arguments output = dict(ts.moving_average(2, 1, time_list[0], time_list[-1])) assert output == build_answer(datetime.timedelta(seconds=0.5), (2, 11, 2)) - pytest.raises(ValueError, ts.moving_average, -1, 1, time_list[0], time_list[-1]) - pytest.raises(ValueError, ts.moving_average, 20, 1, time_list[0], time_list[-1]) + pytest.raises( + ValueError, ts.moving_average, -1, 1, time_list[0], time_list[-1] + ) + pytest.raises( + ValueError, ts.moving_average, 20, 1, time_list[0], time_list[-1] + ) # Check third and fourth arguments - pytest.raises(ValueError, ts.moving_average, 1, 1, time_list[3], time_list[0]) + pytest.raises( + ValueError, ts.moving_average, 1, 1, time_list[3], time_list[0] + ) output = dict(ts.moving_average(1, 2, curr_time(5), curr_time(10))) assert output == build_answer(datetime.timedelta(seconds=1), (5, 11)) @@ -179,9 +214,12 @@ def build_answer(step, interval): # Check using int ts = traces.TimeSeries([[1, 2], [2, 3], [6, 1], [8, 4]]) - assert dict(ts.moving_average(1, 2, 2, 8)) == {i: ts.mean(i - 1, i + 1) for i in range(2, 9)} + assert dict(ts.moving_average(1, 2, 2, 8)) == { + i: ts.mean(i - 1, i + 1) for i in range(2, 9) + } assert dict(ts.moving_average(0.5, 2, 2, 8)) == { - 1 + i / 2.0: ts.mean(1 + i / 2.0 - 1, 1 + i / 2.0 + 1) for i in range(2, 15) + 1 + i / 2.0: ts.mean(1 + i / 2.0 - 1, 1 + i / 2.0 + 1) + for i in range(2, 15) } # Test pandas compatibility @@ -271,14 +309,30 @@ def test_npoints(): ts[8] = 4 assert ts.n_points() == 5 - assert ts.n_points(start=0, end=8, include_start=False, include_end=False) == 3 - assert ts.n_points(start=0, end=8, include_start=False, include_end=True) == 4 - assert ts.n_points(start=0, end=8, include_start=True, include_end=False) == 4 - assert ts.n_points(start=0, end=8, include_start=True, include_end=True) == 5 - assert ts.n_points(start=1, end=8, include_start=False, include_end=False) == 2 - assert ts.n_points(start=1, end=8, include_start=False, include_end=True) == 3 - assert ts.n_points(start=1, end=8, include_start=True, include_end=False) == 3 - assert ts.n_points(start=1, end=8, include_start=True, include_end=True) == 4 + assert ( + ts.n_points(start=0, end=8, include_start=False, include_end=False) == 3 + ) + assert ( + ts.n_points(start=0, end=8, include_start=False, include_end=True) == 4 + ) + assert ( + ts.n_points(start=0, end=8, include_start=True, include_end=False) == 4 + ) + assert ( + ts.n_points(start=0, end=8, include_start=True, include_end=True) == 5 + ) + assert ( + ts.n_points(start=1, end=8, include_start=False, include_end=False) == 2 + ) + assert ( + ts.n_points(start=1, end=8, include_start=False, include_end=True) == 3 + ) + assert ( + ts.n_points(start=1, end=8, include_start=True, include_end=False) == 3 + ) + assert ( + ts.n_points(start=1, end=8, include_start=True, include_end=True) == 4 + ) ts = traces.TimeSeries() diff --git a/tests/test_missing.py b/tests/test_missing.py index f056fb7..a019d26 100644 --- a/tests/test_missing.py +++ b/tests/test_missing.py @@ -5,7 +5,9 @@ def test_missing(): """example code for dealing with missing datapoints""" - router_a = traces.TimeSeries([(-10, 0), (-7, 1), (-5, None), (0, 3), (1, 3), (5, None)]) + router_a = traces.TimeSeries( + [(-10, 0), (-7, 1), (-5, None), (0, 3), (1, 3), (5, None)] + ) assert router_a[-6] == 1 assert router_a[-15] is None @@ -35,7 +37,9 @@ def test_missing(): # the default here should be the element returned by `count_merge([])` - clients = traces.TimeSeries.merge(router_list, operation=traces.operations.strict_sum) + clients = traces.TimeSeries.merge( + router_list, operation=traces.operations.strict_sum + ) assert clients[-15] is None assert clients[-6] == 1 assert clients[-0.5] is None @@ -47,7 +51,9 @@ def test_missing(): assert system_uptime[-6] is True assert system_uptime[-1] is False - clients = traces.TimeSeries.merge(router_list, operation=traces.operations.ignorant_sum) + clients = traces.TimeSeries.merge( + router_list, operation=traces.operations.ignorant_sum + ) assert clients[-15] == 0 assert clients[-6] == 1 assert clients[-0.5] == 0 diff --git a/tests/test_operations.py b/tests/test_operations.py index a32efb6..471f8d4 100644 --- a/tests/test_operations.py +++ b/tests/test_operations.py @@ -1,6 +1,4 @@ import datetime -import math -import random import pytest @@ -86,154 +84,6 @@ def test_sum(): assert 0 + a + b == a + b -def example_dictlike(): - # test overwriting keys - ts = TimeSeries() - ts[datetime.datetime(2010, 1, 1)] = 5 - ts[datetime.datetime(2010, 1, 2)] = 4 - ts[datetime.datetime(2010, 1, 3)] = 3 - ts[datetime.datetime(2010, 1, 7)] = 2 - ts[datetime.datetime(2010, 1, 4)] = 1 - ts[datetime.datetime(2010, 1, 4)] = 10 - ts[datetime.datetime(2010, 1, 4)] = 5 - ts[datetime.datetime(2010, 1, 1)] = 1 - ts[datetime.datetime(2010, 1, 7)] = 1.2 - ts[datetime.datetime(2010, 1, 8)] = 1.3 - ts[datetime.datetime(2010, 1, 12)] = 1.3 - - # do some wackiness with a bunch of points - dt = datetime.datetime(2010, 1, 12) - for i in range(1000): - dt += datetime.timedelta(hours=random.random()) - ts[dt] = math.sin(i / float(math.pi)) - - dt -= datetime.timedelta(hours=500) - dt -= datetime.timedelta(minutes=30) - for i in range(1000): - dt += datetime.timedelta(hours=random.random()) - ts[dt] = math.cos(i / float(math.pi)) - - # output the time series - for i, j in ts: - print(i.isoformat(), j) - - -def example_mean(): - ts = TimeSeries() - ts[datetime.datetime(2010, 1, 1)] = 0 - ts[datetime.datetime(2010, 1, 3, 10)] = 1 - ts[datetime.datetime(2010, 1, 5)] = 0 - ts[datetime.datetime(2010, 1, 8)] = 1 - ts[datetime.datetime(2010, 1, 17)] = 0 - ts[datetime.datetime(2010, 1, 19)] = 1 - ts[datetime.datetime(2010, 1, 23)] = 0 - ts[datetime.datetime(2010, 1, 26)] = 1 - ts[datetime.datetime(2010, 1, 28)] = 0 - ts[datetime.datetime(2010, 1, 31)] = 1 - ts[datetime.datetime(2010, 2, 5)] = 0 - - for time, value in ts: - print(time.isoformat(), 0.1 * value + 1.1) - - print("") - - timestep = {"hours": 25} - start = datetime.datetime(2010, 1, 1) - while start <= datetime.datetime(2010, 2, 5): - end = start + datetime.timedelta(**timestep) - print(start.isoformat(), ts.mean(start, end)) - start = end - - print("") - - start = datetime.datetime(2010, 1, 1) - while start <= datetime.datetime(2010, 2, 5): - end = start + datetime.timedelta(**timestep) - print(start.isoformat(), -0.2) - print(start.isoformat(), 1.2) - start = end - - -def example_arrow(): - import arrow - - ts = TimeSeries() - ts[arrow.Arrow(2010, 1, 1)] = 0 - ts[arrow.Arrow(2010, 1, 3, 10)] = 1 - ts[arrow.Arrow(2010, 1, 5)] = 0 - ts[arrow.Arrow(2010, 1, 8)] = 1 - ts[arrow.Arrow(2010, 1, 17)] = 0 - ts[arrow.Arrow(2010, 1, 19)] = 1 - ts[arrow.Arrow(2010, 1, 23)] = 0 - ts[arrow.Arrow(2010, 1, 26)] = 1 - ts[arrow.Arrow(2010, 1, 28)] = 0 - ts[arrow.Arrow(2010, 1, 31)] = 1 - ts[arrow.Arrow(2010, 2, 5)] = 0 - - for time, value in ts: - print(time.naive.isoformat(), 0.1 * value + 1.1) - - print("") - - start = arrow.Arrow(2010, 1, 1) - end = arrow.Arrow(2010, 2, 5) - unit = {"hours": 25} - for start, end in span_range(start, end, unit): - print(start.naive.isoformat(), ts.mean(start, end)) - - print("") - - for start, end in span_range(start, end, unit): - print(start.naive.isoformat(), -0.2) - print(start.naive.isoformat(), 1.2) - - -def example_sum(): - a = TimeSeries() - a.set(datetime.datetime(2015, 3, 1), 1) - a.set(datetime.datetime(2015, 3, 2), 0) - a.set(datetime.datetime(2015, 3, 3), 1) - a.set(datetime.datetime(2015, 3, 5), 0) - a.set(datetime.datetime(2015, 3, 6), 0) - - b = TimeSeries() - b.set(datetime.datetime(2015, 3, 1), 0) - b.set(datetime.datetime(2015, 3, 2, 12), 1) - b.set(datetime.datetime(2015, 3, 3, 13, 13), 0) - b.set(datetime.datetime(2015, 3, 4), 1) - b.set(datetime.datetime(2015, 3, 5), 0) - b.set(datetime.datetime(2015, 3, 5, 12), 1) - b.set(datetime.datetime(2015, 3, 5, 19), 0) - - c = TimeSeries() - c.set(datetime.datetime(2015, 3, 1, 17), 0) - c.set(datetime.datetime(2015, 3, 1, 21), 1) - c.set(datetime.datetime(2015, 3, 2, 13, 13), 0) - c.set(datetime.datetime(2015, 3, 4, 18), 1) - c.set(datetime.datetime(2015, 3, 5, 4), 0) - - # output the three time series - for i, ts in enumerate([a, b, c]): - for (t0, _v0), (t1, _v1) in ts.iterintervals(1): - print(t0.isoformat(), i) - print(t1.isoformat(), i) - - print("") - - for (t0, _v0), (t1, _v1) in ts.iterintervals(0): - print(t0.isoformat(), i) - print(t1.isoformat(), i) - - print("") - - # output the sum - # for dt, i in sum([a, b, c]): - # print dt.isoformat(), i - # print '' - for dt, i in TimeSeries.merge([a, b, c], operation=sum): - print(dt.isoformat(), i) - - def test_interpolation(): ts = TimeSeries(data=[(0, 0), (1, 2)]) diff --git a/tests/test_traces.py b/tests/test_traces.py index 2d350e1..64c33ff 100644 --- a/tests/test_traces.py +++ b/tests/test_traces.py @@ -108,7 +108,14 @@ def test_set_interval(): tsc = TimeSeries(ts) ts.set_interval(3, 4, 4) - assert list(ts.items()) == [(1.2, 1), (2, 5), (3, 4), (4, 4), (5, 0), (6, 2)] + assert list(ts.items()) == [ + (1.2, 1), + (2, 5), + (3, 4), + (4, 4), + (5, 0), + (6, 2), + ] tsc.set_interval(3, 4, 4, compact=True) assert list(tsc.items()) == [(1.2, 1), (2, 5), (3, 4), (5, 0), (6, 2)] @@ -162,7 +169,7 @@ def test_pickle(): ts[1] = True ts[2] = False dump_string = pickle.dumps(ts) - unpickled = pickle.loads(dump_string) + unpickled = pickle.loads(dump_string) # noqa: S301 assert unpickled == ts unpickled[3] = unpickled[1] @@ -191,7 +198,12 @@ def value_parse(value): writer.writerow(["15", "nan"]) ts = TimeSeries.from_csv( - filename, time_column=0, time_transform=time_parse, value_column=1, value_transform=value_parse, default=None + filename, + time_column=0, + time_transform=time_parse, + value_column=1, + value_transform=value_parse, + default=None, ) os.remove(filename) diff --git a/tests/test_utils.py b/tests/test_utils.py index 0b24fa1..57d107d 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -5,7 +5,12 @@ import traces.utils as utils -timedelta_list = [timedelta(hours=1), timedelta(minutes=2), timedelta(seconds=5), timedelta(milliseconds=5)] +timedelta_list = [ + timedelta(hours=1), + timedelta(minutes=2), + timedelta(seconds=5), + timedelta(milliseconds=5), +] numeric_types = {int: [1, 2, 3, 0], float: [1.0, 2.0, 3.0, 0.0]} @@ -15,7 +20,9 @@ def test_duration_to_number(): for tdelta in timedelta_list: assert utils.duration_to_number(tdelta) == tdelta.total_seconds() - pytest.raises(NotImplementedError, utils.duration_to_number, tdelta, "hours") + pytest.raises( + NotImplementedError, utils.duration_to_number, tdelta, "hours" + ) for _type, item in numeric_types.items(): for num in item: @@ -69,21 +76,33 @@ def test_convert_args_to_list(): def test_datetime_range(): # test default options - dt_range = list(utils.datetime_range(datetime(2016, 1, 1), datetime(2016, 2, 1), "days")) + dt_range = list( + utils.datetime_range(datetime(2016, 1, 1), datetime(2016, 2, 1), "days") + ) assert dt_range[0] == datetime(2016, 1, 1) assert dt_range[-1] == datetime(2016, 1, 31) assert dt_range[10] == datetime(2016, 1, 11) # test non-default options dt_range = list( - utils.datetime_range(datetime(2016, 1, 2), datetime(2016, 2, 1), "days", n_units=2, inclusive_end=True) + utils.datetime_range( + datetime(2016, 1, 2), + datetime(2016, 2, 1), + "days", + n_units=2, + inclusive_end=True, + ) ) assert dt_range[0] == datetime(2016, 1, 2) assert dt_range[-1] == datetime(2016, 2, 1) assert dt_range[10] == datetime(2016, 1, 22) # test units - dt_range = list(utils.datetime_range(datetime(2016, 1, 1), datetime(2016, 2, 1), "hours")) + dt_range = list( + utils.datetime_range( + datetime(2016, 1, 1), datetime(2016, 2, 1), "hours" + ) + ) assert dt_range[1] - dt_range[0] == timedelta(hours=1) dt_range = list( utils.datetime_range( @@ -96,30 +115,46 @@ def test_datetime_range(): assert dt_range[1] - dt_range[0] == timedelta(minutes=10) # test end < start - dt_range = list(utils.datetime_range(datetime(2016, 2, 1), datetime(2016, 1, 1), "days")) + dt_range = list( + utils.datetime_range(datetime(2016, 2, 1), datetime(2016, 1, 1), "days") + ) assert dt_range == [] def test_datetime_floor(): # the date here is May 6th, 2016 (week 18) - assert utils.datetime_floor(date(2016, 5, 6), "years") == datetime(2016, 1, 1) + assert utils.datetime_floor(date(2016, 5, 6), "years") == datetime( + 2016, 1, 1 + ) assert utils.datetime_floor(inf) == inf test_dt = datetime(2016, 5, 6, 11, 45, 6) - assert utils.datetime_floor(test_dt, "months", n_units=3) == datetime(2016, 4, 1) + assert utils.datetime_floor(test_dt, "months", n_units=3) == datetime( + 2016, 4, 1 + ) - assert utils.datetime_floor(test_dt, "weeks", n_units=3) == datetime(2016, 4, 18) + assert utils.datetime_floor(test_dt, "weeks", n_units=3) == datetime( + 2016, 4, 18 + ) - assert utils.datetime_floor(test_dt, "hours", n_units=10) == datetime(2016, 5, 6, 10) + assert utils.datetime_floor(test_dt, "hours", n_units=10) == datetime( + 2016, 5, 6, 10 + ) - assert utils.datetime_floor(test_dt, "minutes", n_units=15) == datetime(2016, 5, 6, 11, 45) + assert utils.datetime_floor(test_dt, "minutes", n_units=15) == datetime( + 2016, 5, 6, 11, 45 + ) - assert utils.datetime_floor(test_dt, "seconds", n_units=30) == datetime(2016, 5, 6, 11, 45) + assert utils.datetime_floor(test_dt, "seconds", n_units=30) == datetime( + 2016, 5, 6, 11, 45 + ) pytest.raises(ValueError, utils.datetime_floor, "2016-6-7") - pytest.raises(ValueError, utils.datetime_floor, test_dt, "sleconds", n_units=3) + pytest.raises( + ValueError, utils.datetime_floor, test_dt, "sleconds", n_units=3 + ) def test_weekday_number(): diff --git a/traces/histogram.py b/traces/histogram.py index 1c3d042..42bce05 100644 --- a/traces/histogram.py +++ b/traces/histogram.py @@ -35,11 +35,11 @@ def __getitem__(self, key): result = 0 except TypeError as error: if "unorderable" in str(error): - raise UnorderableElements(error) + raise UnorderableElements(error) from error if "unhashable" in str(error): msg = f"Can't make histogram of unhashable type ({type(key)})" - raise UnhashableType(msg) + raise UnhashableType(msg) from error raise return result @@ -49,14 +49,14 @@ def __setitem__(self, key, value): result = super().__setitem__(key, value) except TypeError as error: if "unorderable" in str(error): - raise UnorderableElements(error) + raise UnorderableElements(error) from error if "not supported between instances of" in str(error): - raise UnorderableElements(error) + raise UnorderableElements(error) from error if "unhashable" in str(error): msg = f"Can't make histogram of unhashable type ({type(key)})" - raise UnhashableType(msg) + raise UnhashableType(msg) from error raise return result @@ -87,7 +87,9 @@ def variance(self): return None mean = self.mean() - weighted_central_moment = sum(count * (value - mean) ** 2 for value, count in clean.items()) + weighted_central_moment = sum( + count * (value - mean) ** 2 for value, count in clean.items() + ) return weighted_central_moment / total def standard_deviation(self): @@ -117,7 +119,9 @@ def _discard_value(self, value): if value not in self: return self else: - return self.__class__.from_dict({k: v for k, v in self.items() if k is not value}) + return self.__class__.from_dict( + {k: v for k, v in self.items() if k is not value} + ) def max(self, include_zero=False): """Maximum observed value with non-zero count.""" @@ -131,7 +135,7 @@ def min(self, include_zero=False): if value > 0 or include_zero: return key - def _quantile_function(self, alpha=0.5, smallest_count=None): + def _quantile_function(self, alpha=0.5, smallest_count=None): # noqa: C901 """Return a function that returns the quantile values for this histogram. diff --git a/traces/plot.py b/traces/plot.py index 7babff0..7a1a939 100644 --- a/traces/plot.py +++ b/traces/plot.py @@ -61,9 +61,9 @@ def plot( try: import matplotlib.pyplot as plt from matplotlib import font_manager - except ImportError: + except ImportError as error: msg = "need to install matplotlib for `plot` function" - raise ImportError(msg) + raise ImportError(msg) from error if font is None: available_fonts = {f.name for f in font_manager.fontManager.ttflist} @@ -77,14 +77,18 @@ def plot( except KeyError: n_unique_values = 0 scaled = min(MAX_ASPECT_POINTS, max(2, n_unique_values) - 2) - aspect_ratio = MIN_ASPECT_RATIO + (MAX_ASPECT_RATIO - MIN_ASPECT_RATIO) * (scaled / MAX_ASPECT_POINTS) + aspect_ratio = MIN_ASPECT_RATIO + ( + MAX_ASPECT_RATIO - MIN_ASPECT_RATIO + ) * (scaled / MAX_ASPECT_POINTS) try: drawstyle = INTERPOLATE_DRAWSTYLE[interpolate] - except KeyError: - raise ValueError( - f"invalid value for interpolate='{interpolate}', " f"must be in {set(INTERPOLATE_DRAWSTYLE.keys())}" + except KeyError as error: + msg = ( + f"invalid value for interpolate='{interpolate}', " + f"must be in {set(INTERPOLATE_DRAWSTYLE.keys())}" ) + raise ValueError(msg) from error with plt.style.context(PLOT_STYLE): figure, axes = plt.subplots( diff --git a/traces/timeseries.py b/traces/timeseries.py index 856b30f..2b66883 100644 --- a/traces/timeseries.py +++ b/traces/timeseries.py @@ -123,11 +123,12 @@ def get(self, time, interpolate="previous"): """Get the value of the time series, even in-between measured values.""" try: getter = self.getter_functions[interpolate] - except KeyError: - msg = ("unknown value '{}' for interpolate, " "valid values are in [{}]").format( - interpolate, ", ".join(self.getter_functions) + except KeyError as error: + msg = ( + f"unknown value '{interpolate}' for interpolate, " + f"valid values are in [{", ".join(self.getter_functions)}]" ) - raise ValueError(msg) + raise ValueError(msg) from error else: return getter(time) @@ -164,7 +165,11 @@ def set(self, time, value, compact=False): value if it's different from what it would be anyway. """ - if (len(self) == 0) or (not compact) or (compact and self.get(time) != value): + if ( + (len(self) == 0) + or (not compact) + or (compact and self.get(time) != value) + ): self._d[time] = value def set_interval(self, start, end, value, compact=False): @@ -174,7 +179,7 @@ def set_interval(self, start, end, value, compact=False): """ # for each interval to render - for i, (s, _e, v) in enumerate(self.iterperiods(start, end)): + for i, (s, _e, v) in enumerate(self.iterperiods(start, end)): # noqa: B007 # look at all intervals included in the current interval # (always at least 1) if i == 0: @@ -222,8 +227,9 @@ def remove(self, time): """ try: del self._d[time] - except KeyError: - raise KeyError(f"no measurement at {time}") + except KeyError as error: + error.add_note(f"no measurement at {time}") + raise def remove_points_from_interval(self, start, end): """Allow removal of all points from the time series within a interval @@ -330,7 +336,9 @@ def iterperiods(self, start=None, end=None, value=None): TODO: add mask argument here. """ - start, end, mask = self._check_boundaries(start, end, allow_infinite=False) + start, end, mask = self._check_boundaries( + start, end, allow_infinite=False + ) value_function = self._value_function(value) @@ -356,7 +364,9 @@ def iterperiods(self, start=None, end=None, value=None): interval_value = self[interval_t0] # yield the time, duration, and value of the final period - if interval_t0 < end and value_function(interval_t0, end, interval_value): + if interval_t0 < end and value_function( + interval_t0, end, interval_value + ): yield interval_t0, end, interval_value def slice(self, start, end): @@ -364,10 +374,12 @@ def slice(self, start, end): `start` and `end` (always starting at `start`) """ - start, end, mask = self._check_boundaries(start, end, allow_infinite=True) + start, end, mask = self._check_boundaries( + start, end, allow_infinite=True + ) result = TimeSeries(default=self.default) - for t0, t1, value in self.iterperiods(start, end): + for t0, t1, value in self.iterperiods(start, end): # noqa: B007 result[t0] = value result[t1] = self[t1] @@ -383,25 +395,39 @@ def _check_regularization(self, start, end, sampling_period=None): sampling_period_timedelta = sampling_period else: sampling_period_seconds = sampling_period - sampling_period_timedelta = datetime.timedelta(seconds=sampling_period) + sampling_period_timedelta = datetime.timedelta( + seconds=sampling_period + ) if sampling_period_seconds <= 0: msg = "sampling_period must be > 0" raise ValueError(msg) if sampling_period_seconds > utils.duration_to_number(end - start): - msg = "sampling_period " "is greater than the duration between " "start and end." + msg = ( + "sampling_period " + "is greater than the duration between " + "start and end." + ) raise ValueError(msg) - sampling_period = sampling_period_timedelta if isinstance(start, datetime.date) else sampling_period_seconds + sampling_period = ( + sampling_period_timedelta + if isinstance(start, datetime.date) + else sampling_period_seconds + ) return sampling_period - def sample(self, sampling_period, start=None, end=None, interpolate="previous"): + def sample( + self, sampling_period, start=None, end=None, interpolate="previous" + ): """Sampling at regular time periods.""" start, end, mask = self._check_boundaries(start, end) - sampling_period = self._check_regularization(start, end, sampling_period) + sampling_period = self._check_regularization( + start, end, sampling_period + ) result = [] current_time = start @@ -411,7 +437,7 @@ def sample(self, sampling_period, start=None, end=None, interpolate="previous"): current_time += sampling_period return result - def moving_average( + def moving_average( # noqa: C901 self, sampling_period, window_size=None, @@ -427,12 +453,16 @@ def moving_average( if window_size is None: window_size = sampling_period - sampling_period = self._check_regularization(start, end, sampling_period) + sampling_period = self._check_regularization( + start, end, sampling_period + ) # convert to datetime if the times are datetimes full_window = window_size * 1.0 half_window = full_window / 2 - if isinstance(start, datetime.date) and not isinstance(full_window, datetime.timedelta): + if isinstance(start, datetime.date) and not isinstance( + full_window, datetime.timedelta + ): half_window = datetime.timedelta(seconds=half_window) full_window = datetime.timedelta(seconds=full_window) @@ -468,9 +498,11 @@ def moving_average( if pandas: try: import pandas as pd - except ImportError: - msg = "can't have pandas=True if pandas is not installed" - raise ImportError(msg) + except ImportError as error: + error.add_note( + "can't have pandas=True if pandas is not installed" + ) + raise result = pd.Series( [v for t, v in result], @@ -501,10 +533,10 @@ def bin( smaller=None, transform="distribution", ): - # return an empty sorted dictionary if there is no time span if mask is not None and mask.is_empty(): return sortedcontainers.SortedDict() - elif start is not None and start == end: + + if start is not None and start == end: return sortedcontainers.SortedDict() # use smaller if available @@ -522,7 +554,9 @@ def bin( result = sortedcontainers.SortedDict() dt_range = utils.datetime_range(start, end, unit, n_units=n_units) for bin_start, bin_end in utils.pairwise(dt_range): - result[bin_start] = function(bin_start, bin_end, mask=mask, normalized=False) + result[bin_start] = function( + bin_start, bin_end, mask=mask, normalized=False + ) return result @@ -531,7 +565,9 @@ def mean(self, start=None, end=None, mask=None, interpolate="previous"): time range from `start` to `end`, when `mask` is truthy. """ - return self.distribution(start=start, end=end, mask=mask, interpolate=interpolate).mean() + return self.distribution( + start=start, end=end, mask=mask, interpolate=interpolate + ).mean() def distribution( self, @@ -590,7 +626,9 @@ def distribution( try: counter[value] += duration except histogram.UnorderableElements: - counter = histogram.Histogram.from_dict(dict(counter), key=hash) + counter = histogram.Histogram.from_dict( + dict(counter), key=hash + ) counter[value] += duration # divide by total duration if result needs to be normalized @@ -638,9 +676,17 @@ def n_points( count = 0 for i_start, i_end, _ in mask.iterperiods(value=True): - end_count = self._d.bisect_right(i_end) if include_end else self._d.bisect_left(i_end) + end_count = ( + self._d.bisect_right(i_end) + if include_end + else self._d.bisect_left(i_end) + ) - start_count = self._d.bisect_left(i_start) if include_start else self._d.bisect_right(i_start) + start_count = ( + self._d.bisect_left(i_start) + if include_start + else self._d.bisect_right(i_start) + ) count += end_count - start_count @@ -856,7 +902,9 @@ def function(x, y): def sum(self, other): """sum(x, y) = x(t) + y(t).""" - return TimeSeries.merge([self, other], operation=operations.ignorant_sum) + return TimeSeries.merge( + [self, other], operation=operations.ignorant_sum + ) def difference(self, other): """difference(x, y) = x(t) - y(t).""" @@ -888,7 +936,8 @@ def __setitem__(self, time, value): def __getitem__(self, time): """Allow a[time] syntax.""" if isinstance(time, slice): - raise ValueError("Syntax a[start:end] not allowed") + msg = "Syntax a[start:end] not allowed" + raise ValueError(msg) # noqa: TRY004 else: return self.get(time) @@ -949,7 +998,10 @@ def _check_boundary(self, value, allow_infinite, lower_or_upper): infinity_value = inf method_name = "last_key" else: - msg = f'`lower_or_upper` must be "lower" or "upper", got {lower_or_upper}' + msg = ( + f'`lower_or_upper` must be "lower" or "upper", ' + f"got {lower_or_upper}" + ) raise ValueError(msg) if value is None: @@ -958,15 +1010,19 @@ def _check_boundary(self, value, allow_infinite, lower_or_upper): else: try: return getattr(self, method_name)() - except IndexError: - msg = f"can't use '{method_name}' for default {lower_or_upper} boundary " "of empty TimeSeries" - raise KeyError(msg) + except IndexError as error: + msg = ( + f"can't use '{method_name}' for default " + f"{lower_or_upper} boundary of empty TimeSeries" + ) + raise KeyError(msg) from error else: return value def _check_boundaries(self, start, end, mask=None, allow_infinite=False): if mask is not None and mask.is_empty(): - raise ValueError("mask can not be empty") + msg = "mask can not be empty" + raise ValueError(msg) # if only a mask is passed in, return mask boundaries and mask if start is None and end is None and mask is not None: @@ -988,7 +1044,9 @@ def _check_boundaries(self, start, end, mask=None, allow_infinite=False): return start, end, mask - def distribution_by_hour_of_day(self, first=0, last=23, start=None, end=None): + def distribution_by_hour_of_day( + self, first=0, last=23, start=None, end=None + ): start, end, mask = self._check_boundaries(start, end) result = [] @@ -998,7 +1056,9 @@ def distribution_by_hour_of_day(self, first=0, last=23, start=None, end=None): return result - def distribution_by_day_of_week(self, first=0, last=6, start=None, end=None): + def distribution_by_day_of_week( + self, first=0, last=6, start=None, end=None + ): start, end, mask = self._check_boundaries(start, end) result = [] @@ -1033,7 +1093,9 @@ def hour_of_day(start, end, hour): floored = utils.datetime_floor(start) domain = TimeSeries(default=False) - for day_start in utils.datetime_range(floored, end, "days", inclusive_end=True): + for day_start in utils.datetime_range( + floored, end, "days", inclusive_end=True + ): interval_start = day_start + datetime.timedelta(hours=hour) interval_end = interval_start + datetime.timedelta(hours=1) domain[interval_start] = True @@ -1058,7 +1120,9 @@ def day_of_week(start, end, weekday): break domain = TimeSeries(default=False) - for week_start in utils.datetime_range(first_day, end, "weeks", inclusive_end=True): + for week_start in utils.datetime_range( + first_day, end, "weeks", inclusive_end=True + ): interval_start = week_start interval_end = interval_start + datetime.timedelta(days=1) domain[interval_start] = True diff --git a/traces/utils.py b/traces/utils.py index 8c0cc51..225d59e 100644 --- a/traces/utils.py +++ b/traces/utils.py @@ -49,7 +49,9 @@ def convert_args_to_list(args): # Domain([(1, 4)]) # Domain([(1, 4), (5, 8)]) # Domain([[1, 4], [5, 8]]) - if len(args) == 1 and any(isinstance(arg, (list, tuple)) for arg in args[0]): + if len(args) == 1 and any( + isinstance(arg, (list, tuple)) for arg in args[0] + ): for item in args[0]: list_of_pairs.append(list(item)) else: @@ -101,7 +103,9 @@ def floor_datetime(dt, unit, n_units=1): elif unit == "weeks": _, isoweek, _ = dt.isocalendar() new_week = isoweek - (isoweek - 1) % n_units - return datetime.datetime.strptime("%d %02d 1" % (dt.year, new_week), "%Y %W %w") + return datetime.datetime.strptime( + "%d %02d 1" % (dt.year, new_week), "%Y %W %w" + ) elif unit == "days": new_day = dt.day - dt.day % n_units return datetime.datetime(dt.year, dt.month, new_day, 0, 0, 0) @@ -110,10 +114,14 @@ def floor_datetime(dt, unit, n_units=1): return datetime.datetime(dt.year, dt.month, dt.day, new_hour, 0, 0) elif unit == "minutes": new_minute = dt.minute - dt.minute % n_units - return datetime.datetime(dt.year, dt.month, dt.day, dt.hour, new_minute, 0) + return datetime.datetime( + dt.year, dt.month, dt.day, dt.hour, new_minute, 0 + ) elif unit == "seconds": new_second = dt.second - dt.second % n_units - return datetime.datetime(dt.year, dt.month, dt.day, dt.hour, dt.minute, new_second) + return datetime.datetime( + dt.year, dt.month, dt.day, dt.hour, dt.minute, new_second + ) else: msg = f"Unknown unit type {unit}" raise ValueError(msg) From 4afd5b3437052118bd158006091201640a40ae27 Mon Sep 17 00:00:00 2001 From: stringertheory Date: Fri, 2 Feb 2024 23:26:46 -0600 Subject: [PATCH 16/18] prettier passing --- .circleci/config.yml | 2 +- .github/ISSUE_TEMPLATE.md | 4 +- .github/actions/setup-poetry-env/action.yml | 8 +-- .github/workflows/main.yml | 2 +- .github/workflows/on-release-main.yml | 1 - .pre-commit-config.yaml | 8 +-- CHANGELOG.md | 3 +- docs/_templates/side-primary.html | 20 ++++-- docs/_themes/ms/layout.html | 40 +++++++----- docs/_themes/ms/relations.html | 49 ++++++++++----- docs/_themes/ms/static/small_flask.css | 68 +++++++++++---------- mkdocs.yml | 6 +- 12 files changed, 123 insertions(+), 88 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 46d33b3..5766a7d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,7 +12,7 @@ workflows: jobs: test-3.6: &test-template docker: - - image: circleci/python:3.6-buster + - image: circleci/python:3.6-buster filters: branches: only: diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index dc50455..f13b172 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,5 +1,5 @@ -* Simplicity is better than functionality -* The API matters most, everything else is secondary +- Simplicity is better than functionality +- The API matters most, everything else is secondary For feature requests, please include a description of why the feature will be useful to most users. diff --git a/.github/actions/setup-poetry-env/action.yml b/.github/actions/setup-poetry-env/action.yml index a7cdeb8..22e4053 100644 --- a/.github/actions/setup-poetry-env/action.yml +++ b/.github/actions/setup-poetry-env/action.yml @@ -2,10 +2,10 @@ name: "setup-poetry-env" description: "Composite action to setup the Python and poetry environment." inputs: - python-version: - required: false - description: "The python version to use" - default: "3.11" + python-version: + required: false + description: "The python version to use" + default: "3.11" runs: using: "composite" diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 55e7ff8..bdf879d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.8', '3.9', '3.10', '3.11'] + python-version: ["3.8", "3.9", "3.10", "3.11"] fail-fast: false steps: - name: Check out diff --git a/.github/workflows/on-release-main.yml b/.github/workflows/on-release-main.yml index 75f4e25..96327f9 100644 --- a/.github/workflows/on-release-main.yml +++ b/.github/workflows/on-release-main.yml @@ -6,7 +6,6 @@ on: branches: [main] jobs: - publish: runs-on: ubuntu-latest steps: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index df6d201..5e3015b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: args: [--exit-non-zero-on-fix] - id: ruff-format - # - repo: https://github.com/pre-commit/mirrors-prettier - # rev: "v3.0.3" - # hooks: - # - id: prettier + - repo: https://github.com/pre-commit/mirrors-prettier + rev: "v3.0.3" + hooks: + - id: prettier diff --git a/CHANGELOG.md b/CHANGELOG.md index a5693d9..825c32f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1 @@ -Changelog -========= +# Changelog diff --git a/docs/_templates/side-primary.html b/docs/_templates/side-primary.html index d7d9ef1..ea93984 100644 --- a/docs/_templates/side-primary.html +++ b/docs/_templates/side-primary.html @@ -1,19 +1,29 @@

-

- Traces is a Python library for unevenly-spaced time series analysis. + Traces is a Python library for unevenly-spaced time + series analysis.

{{ _('Table Of Contents') }}

diff --git a/docs/_themes/ms/layout.html b/docs/_themes/ms/layout.html index 4d67ec1..6ace260 100755 --- a/docs/_themes/ms/layout.html +++ b/docs/_themes/ms/layout.html @@ -1,18 +1,26 @@ -{%- extends "basic/layout.html" %} -{%- block extrahead %} - {{ super() }} - {% if theme_touch_icon %} - - {% endif %} - +{%- extends "basic/layout.html" %} {%- block extrahead %} {{ super() }} {% if +theme_touch_icon %} + +{% endif %} + - - -{% endblock %} -{%- block relbar2 %}{% endblock %} -{%- block footer %} - + + +{% endblock %} {%- block relbar2 %}{% endblock %} {%- block footer %} + {%- endblock %} diff --git a/docs/_themes/ms/relations.html b/docs/_themes/ms/relations.html index 3bbcde8..ea411e0 100755 --- a/docs/_themes/ms/relations.html +++ b/docs/_themes/ms/relations.html @@ -1,19 +1,36 @@

Related Topics

diff --git a/docs/_themes/ms/static/small_flask.css b/docs/_themes/ms/static/small_flask.css index a0af646..c8e4969 100755 --- a/docs/_themes/ms/static/small_flask.css +++ b/docs/_themes/ms/static/small_flask.css @@ -7,84 +7,86 @@ */ body { - margin: 0; - padding: 20px 30px; + margin: 0; + padding: 20px 30px; } div.documentwrapper { - float: none; - background: white; + float: none; + background: white; } div.sphinxsidebar { - display: block; - float: none; - width: 102.5%; - margin: 50px -30px -20px -30px; - padding: 10px 20px; - background: #333; - color: white; -} - -div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, + display: block; + float: none; + width: 102.5%; + margin: 50px -30px -20px -30px; + padding: 10px 20px; + background: #333; + color: white; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4, +div.sphinxsidebar p, div.sphinxsidebar h3 a { - color: white; + color: white; } div.sphinxsidebar a { - color: #aaa; + color: #aaa; } div.sphinxsidebar p.logo { - display: none; + display: none; } div.document { - width: 100%; - margin: 0; + width: 100%; + margin: 0; } div.related { - display: block; - margin: 0; - padding: 10px 0 20px 0; + display: block; + margin: 0; + padding: 10px 0 20px 0; } div.related ul, div.related ul li { - margin: 0; - padding: 0; + margin: 0; + padding: 0; } div.footer { - display: none; + display: none; } div.bodywrapper { - margin: 0; + margin: 0; } div.body { - min-height: 0; - padding: 0; + min-height: 0; + padding: 0; } .rtd_doc_footer { - display: none; + display: none; } .document { - width: auto; + width: auto; } .footer { - width: auto; + width: auto; } .footer { - width: auto; + width: auto; } .github { - display: none; + display: none; } diff --git a/mkdocs.yml b/mkdocs.yml index 2516c95..8373982 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -15,9 +15,9 @@ plugins: - mkdocstrings: handlers: python: - setup_commands: - - import sys - - sys.path.append('../') + setup_commands: + - import sys + - sys.path.append('../') theme: name: material feature: From 604fc55cb8765748525cbff767a7603e5b10b90c Mon Sep 17 00:00:00 2001 From: stringertheory Date: Sat, 3 Feb 2024 00:49:28 -0600 Subject: [PATCH 17/18] tox passing --- poetry.lock | 319 ++++++++++++++++++++++++++++++++++++++----- pyproject.toml | 31 +++-- tox.ini | 6 +- traces/timeseries.py | 13 +- 4 files changed, 315 insertions(+), 54 deletions(-) diff --git a/poetry.lock b/poetry.lock index 1c12658..0989363 100644 --- a/poetry.lock +++ b/poetry.lock @@ -11,6 +11,9 @@ files = [ {file = "Babel-2.14.0.tar.gz", hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363"}, ] +[package.dependencies] +pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} + [package.extras] dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] @@ -182,6 +185,77 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "contourpy" +version = "1.1.1" +description = "Python library for calculating contours of 2D quadrilateral grids" +optional = false +python-versions = ">=3.8" +files = [ + {file = "contourpy-1.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:46e24f5412c948d81736509377e255f6040e94216bf1a9b5ea1eaa9d29f6ec1b"}, + {file = "contourpy-1.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e48694d6a9c5a26ee85b10130c77a011a4fedf50a7279fa0bdaf44bafb4299d"}, + {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a66045af6cf00e19d02191ab578a50cb93b2028c3eefed999793698e9ea768ae"}, + {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ebf42695f75ee1a952f98ce9775c873e4971732a87334b099dde90b6af6a916"}, + {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6aec19457617ef468ff091669cca01fa7ea557b12b59a7908b9474bb9674cf0"}, + {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:462c59914dc6d81e0b11f37e560b8a7c2dbab6aca4f38be31519d442d6cde1a1"}, + {file = "contourpy-1.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6d0a8efc258659edc5299f9ef32d8d81de8b53b45d67bf4bfa3067f31366764d"}, + {file = "contourpy-1.1.1-cp310-cp310-win32.whl", hash = "sha256:d6ab42f223e58b7dac1bb0af32194a7b9311065583cc75ff59dcf301afd8a431"}, + {file = "contourpy-1.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:549174b0713d49871c6dee90a4b499d3f12f5e5f69641cd23c50a4542e2ca1eb"}, + {file = "contourpy-1.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:407d864db716a067cc696d61fa1ef6637fedf03606e8417fe2aeed20a061e6b2"}, + {file = "contourpy-1.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe80c017973e6a4c367e037cb31601044dd55e6bfacd57370674867d15a899b"}, + {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e30aaf2b8a2bac57eb7e1650df1b3a4130e8d0c66fc2f861039d507a11760e1b"}, + {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3de23ca4f381c3770dee6d10ead6fff524d540c0f662e763ad1530bde5112532"}, + {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:566f0e41df06dfef2431defcfaa155f0acfa1ca4acbf8fd80895b1e7e2ada40e"}, + {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b04c2f0adaf255bf756cf08ebef1be132d3c7a06fe6f9877d55640c5e60c72c5"}, + {file = "contourpy-1.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d0c188ae66b772d9d61d43c6030500344c13e3f73a00d1dc241da896f379bb62"}, + {file = "contourpy-1.1.1-cp311-cp311-win32.whl", hash = "sha256:0683e1ae20dc038075d92e0e0148f09ffcefab120e57f6b4c9c0f477ec171f33"}, + {file = "contourpy-1.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:8636cd2fc5da0fb102a2504fa2c4bea3cbc149533b345d72cdf0e7a924decc45"}, + {file = "contourpy-1.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:560f1d68a33e89c62da5da4077ba98137a5e4d3a271b29f2f195d0fba2adcb6a"}, + {file = "contourpy-1.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:24216552104ae8f3b34120ef84825400b16eb6133af2e27a190fdc13529f023e"}, + {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56de98a2fb23025882a18b60c7f0ea2d2d70bbbcfcf878f9067234b1c4818442"}, + {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:07d6f11dfaf80a84c97f1a5ba50d129d9303c5b4206f776e94037332e298dda8"}, + {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1eaac5257a8f8a047248d60e8f9315c6cff58f7803971170d952555ef6344a7"}, + {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19557fa407e70f20bfaba7d55b4d97b14f9480856c4fb65812e8a05fe1c6f9bf"}, + {file = "contourpy-1.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:081f3c0880712e40effc5f4c3b08feca6d064cb8cfbb372ca548105b86fd6c3d"}, + {file = "contourpy-1.1.1-cp312-cp312-win32.whl", hash = "sha256:059c3d2a94b930f4dafe8105bcdc1b21de99b30b51b5bce74c753686de858cb6"}, + {file = "contourpy-1.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:f44d78b61740e4e8c71db1cf1fd56d9050a4747681c59ec1094750a658ceb970"}, + {file = "contourpy-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:70e5a10f8093d228bb2b552beeb318b8928b8a94763ef03b858ef3612b29395d"}, + {file = "contourpy-1.1.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8394e652925a18ef0091115e3cc191fef350ab6dc3cc417f06da66bf98071ae9"}, + {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5bd5680f844c3ff0008523a71949a3ff5e4953eb7701b28760805bc9bcff217"}, + {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66544f853bfa85c0d07a68f6c648b2ec81dafd30f272565c37ab47a33b220684"}, + {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0c02b75acfea5cab07585d25069207e478d12309557f90a61b5a3b4f77f46ce"}, + {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41339b24471c58dc1499e56783fedc1afa4bb018bcd035cfb0ee2ad2a7501ef8"}, + {file = "contourpy-1.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f29fb0b3f1217dfe9362ec55440d0743fe868497359f2cf93293f4b2701b8251"}, + {file = "contourpy-1.1.1-cp38-cp38-win32.whl", hash = "sha256:f9dc7f933975367251c1b34da882c4f0e0b2e24bb35dc906d2f598a40b72bfc7"}, + {file = "contourpy-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:498e53573e8b94b1caeb9e62d7c2d053c263ebb6aa259c81050766beb50ff8d9"}, + {file = "contourpy-1.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ba42e3810999a0ddd0439e6e5dbf6d034055cdc72b7c5c839f37a7c274cb4eba"}, + {file = "contourpy-1.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c06e4c6e234fcc65435223c7b2a90f286b7f1b2733058bdf1345d218cc59e34"}, + {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca6fab080484e419528e98624fb5c4282148b847e3602dc8dbe0cb0669469887"}, + {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93df44ab351119d14cd1e6b52a5063d3336f0754b72736cc63db59307dabb718"}, + {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eafbef886566dc1047d7b3d4b14db0d5b7deb99638d8e1be4e23a7c7ac59ff0f"}, + {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efe0fab26d598e1ec07d72cf03eaeeba8e42b4ecf6b9ccb5a356fde60ff08b85"}, + {file = "contourpy-1.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f08e469821a5e4751c97fcd34bcb586bc243c39c2e39321822060ba902eac49e"}, + {file = "contourpy-1.1.1-cp39-cp39-win32.whl", hash = "sha256:bfc8a5e9238232a45ebc5cb3bfee71f1167064c8d382cadd6076f0d51cff1da0"}, + {file = "contourpy-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:c84fdf3da00c2827d634de4fcf17e3e067490c4aea82833625c4c8e6cdea0887"}, + {file = "contourpy-1.1.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:229a25f68046c5cf8067d6d6351c8b99e40da11b04d8416bf8d2b1d75922521e"}, + {file = "contourpy-1.1.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a10dab5ea1bd4401c9483450b5b0ba5416be799bbd50fc7a6cc5e2a15e03e8a3"}, + {file = "contourpy-1.1.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4f9147051cb8fdb29a51dc2482d792b3b23e50f8f57e3720ca2e3d438b7adf23"}, + {file = "contourpy-1.1.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a75cc163a5f4531a256f2c523bd80db509a49fc23721b36dd1ef2f60ff41c3cb"}, + {file = "contourpy-1.1.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b53d5769aa1f2d4ea407c65f2d1d08002952fac1d9e9d307aa2e1023554a163"}, + {file = "contourpy-1.1.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11b836b7dbfb74e049c302bbf74b4b8f6cb9d0b6ca1bf86cfa8ba144aedadd9c"}, + {file = "contourpy-1.1.1.tar.gz", hash = "sha256:96ba37c2e24b7212a77da85004c38e7c4d155d3e72a45eeaf22c1f03f607e8ab"}, +] + +[package.dependencies] +numpy = {version = ">=1.16,<2.0", markers = "python_version <= \"3.11\""} + +[package.extras] +bokeh = ["bokeh", "selenium"] +docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] +mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.4.1)", "types-Pillow"] +test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] +test-no-images = ["pytest", "pytest-cov", "wurlitzer"] + [[package]] name = "contourpy" version = "1.2.0" @@ -450,20 +524,6 @@ python-dateutil = ">=2.8.1" [package.extras] dev = ["flake8", "markdown", "twine", "wheel"] -[[package]] -name = "griffe" -version = "0.40.0" -description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." -optional = false -python-versions = ">=3.8" -files = [ - {file = "griffe-0.40.0-py3-none-any.whl", hash = "sha256:db1da6d1d8e08cbb20f1a7dee8c09da940540c2d4c1bfa26a9091cf6fc36a9ec"}, - {file = "griffe-0.40.0.tar.gz", hash = "sha256:76c4439eaa2737af46ae003c331ab6ca79c5365b552f7b5aed263a3b4125735b"}, -] - -[package.dependencies] -colorama = ">=0.4" - [[package]] name = "identify" version = "2.5.33" @@ -767,6 +827,74 @@ files = [ {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, ] +[[package]] +name = "matplotlib" +version = "3.7.4" +description = "Python plotting package" +optional = false +python-versions = ">=3.8" +files = [ + {file = "matplotlib-3.7.4-cp310-cp310-macosx_10_12_universal2.whl", hash = "sha256:b71079239bd866bf56df023e5146de159cb0c7294e508830901f4d79e2d89385"}, + {file = "matplotlib-3.7.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:bf91a42f6274a64cb41189120b620c02e574535ff6671fa836cade7701b06fbd"}, + {file = "matplotlib-3.7.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f757e8b42841d6add0cb69b42497667f0d25a404dcd50bd923ec9904e38414c4"}, + {file = "matplotlib-3.7.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4dfee00aa4bd291e08bb9461831c26ce0da85ca9781bb8794f2025c6e925281"}, + {file = "matplotlib-3.7.4-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3640f33632beb3993b698b1be9d1c262b742761d6101f3c27b87b2185d25c875"}, + {file = "matplotlib-3.7.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff539c4a17ecdf076ed808ee271ffae4a30dcb7e157b99ccae2c837262c07db6"}, + {file = "matplotlib-3.7.4-cp310-cp310-win32.whl", hash = "sha256:24b8f28af3e766195c09b780b15aa9f6710192b415ae7866b9c03dee7ec86370"}, + {file = "matplotlib-3.7.4-cp310-cp310-win_amd64.whl", hash = "sha256:3fa193286712c3b6c3cfa5fe8a6bb563f8c52cc750006c782296e0807ce5e799"}, + {file = "matplotlib-3.7.4-cp311-cp311-macosx_10_12_universal2.whl", hash = "sha256:b167f54cb4654b210c9624ec7b54e2b3b8de68c93a14668937e7e53df60770ec"}, + {file = "matplotlib-3.7.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7dfe6821f1944cb35603ff22e21510941bbcce7ccf96095beffaac890d39ce77"}, + {file = "matplotlib-3.7.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3c557d9165320dff3c5f2bb99bfa0b6813d3e626423ff71c40d6bc23b83c3339"}, + {file = "matplotlib-3.7.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08372696b3bb45c563472a552a705bfa0942f0a8ffe084db8a4e8f9153fbdf9d"}, + {file = "matplotlib-3.7.4-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81e1a7ac818000e8ac3ca696c3fdc501bc2d3adc89005e7b4e22ee5e9d51de98"}, + {file = "matplotlib-3.7.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:390920a3949906bc4b0216198d378f2a640c36c622e3584dd0c79a7c59ae9f50"}, + {file = "matplotlib-3.7.4-cp311-cp311-win32.whl", hash = "sha256:62e094d8da26294634da9e7f1856beee3978752b1b530c8e1763d2faed60cc10"}, + {file = "matplotlib-3.7.4-cp311-cp311-win_amd64.whl", hash = "sha256:f8fc2df756105784e650605e024d36dc2d048d68e5c1b26df97ee25d1bd41f9f"}, + {file = "matplotlib-3.7.4-cp312-cp312-macosx_10_12_universal2.whl", hash = "sha256:568574756127791903604e315c11aef9f255151e4cfe20ec603a70f9dda8e259"}, + {file = "matplotlib-3.7.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7d479aac338195e2199a8cfc03c4f2f55914e6a120177edae79e0340a6406457"}, + {file = "matplotlib-3.7.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:32183d4be84189a4c52b4b8861434d427d9118db2cec32986f98ed6c02dcfbb6"}, + {file = "matplotlib-3.7.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0037d066cca1f4bda626c507cddeb6f7da8283bc6a214da2db13ff2162933c52"}, + {file = "matplotlib-3.7.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44856632ebce88abd8efdc0a0dceec600418dcac06b72ae77af0019d260aa243"}, + {file = "matplotlib-3.7.4-cp312-cp312-win_amd64.whl", hash = "sha256:632fc938c22117d4241411191cfb88ac264a4c0a9ac702244641ddf30f0d739c"}, + {file = "matplotlib-3.7.4-cp38-cp38-macosx_10_12_universal2.whl", hash = "sha256:ce163be048613b9d1962273708cc97e09ca05d37312e670d166cf332b80bbaff"}, + {file = "matplotlib-3.7.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:e680f49bb8052ba3b2698e370155d2b4afb49f9af1cc611a26579d5981e2852a"}, + {file = "matplotlib-3.7.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0604880e4327114054199108b7390f987f4f40ee5ce728985836889e11a780ba"}, + {file = "matplotlib-3.7.4-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1e6abcde6fc52475f9d6a12b9f1792aee171ce7818ef6df5d61cb0b82816e6e8"}, + {file = "matplotlib-3.7.4-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f59a70e2ec3212033ef6633ed07682da03f5249379722512a3a2a26a7d9a738e"}, + {file = "matplotlib-3.7.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a9981b2a2dd9da06eca4ab5855d09b54b8ce7377c3e0e3957767b83219d652d"}, + {file = "matplotlib-3.7.4-cp38-cp38-win32.whl", hash = "sha256:83859ac26839660ecd164ee8311272074250b915ac300f9b2eccc84410f8953b"}, + {file = "matplotlib-3.7.4-cp38-cp38-win_amd64.whl", hash = "sha256:7a7709796ac59fe8debde68272388be6ed449c8971362eb5b60d280eac8dadde"}, + {file = "matplotlib-3.7.4-cp39-cp39-macosx_10_12_universal2.whl", hash = "sha256:b1d70bc1ea1bf110bec64f4578de3e14947909a8887df4c1fd44492eca487955"}, + {file = "matplotlib-3.7.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c83f49e795a5de6c168876eea723f5b88355202f9603c55977f5356213aa8280"}, + {file = "matplotlib-3.7.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5c9133f230945fe10652eb33e43642e933896194ef6a4f8d5e79bb722bdb2000"}, + {file = "matplotlib-3.7.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:798ff59022eeb276380ce9a73ba35d13c3d1499ab9b73d194fd07f1b0a41c304"}, + {file = "matplotlib-3.7.4-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1707b20b25e90538c2ce8d4409e30f0ef1df4017cc65ad0439633492a973635b"}, + {file = "matplotlib-3.7.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e6227ca8492baeef873cdd8e169a318efb5c3a25ce94e69727e7f964995b0b1"}, + {file = "matplotlib-3.7.4-cp39-cp39-win32.whl", hash = "sha256:5661c8639aded7d1bbf781373a359011cb1dd09199dee49043e9e68dd16f07ba"}, + {file = "matplotlib-3.7.4-cp39-cp39-win_amd64.whl", hash = "sha256:55eec941a4743f0bd3e5b8ee180e36b7ea8e62f867bf2613937c9f01b9ac06a2"}, + {file = "matplotlib-3.7.4-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ab16868714e5cc90ec8f7ff5d83d23bcd6559224d8e9cb5227c9f58748889fe8"}, + {file = "matplotlib-3.7.4-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c698b33f9a3f0b127a8e614c8fb4087563bb3caa9c9d95298722fa2400cdd3f"}, + {file = "matplotlib-3.7.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be3493bbcb4d255cb71de1f9050ac71682fce21a56089eadbcc8e21784cb12ee"}, + {file = "matplotlib-3.7.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:f8c725d1dd2901b2e7ec6cd64165e00da2978cc23d4143cb9ef745bec88e6b04"}, + {file = "matplotlib-3.7.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:286332f8f45f8ffde2d2119b9fdd42153dccd5025fa9f451b4a3b5c086e26da5"}, + {file = "matplotlib-3.7.4-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:116ef0b43aa00ff69260b4cce39c571e4b8c6f893795b708303fa27d9b9d7548"}, + {file = "matplotlib-3.7.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c90590d4b46458677d80bc3218f3f1ac11fc122baa9134e0cb5b3e8fc3714052"}, + {file = "matplotlib-3.7.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:de7c07069687be64fd9d119da3122ba13a8d399eccd3f844815f0dc78a870b2c"}, + {file = "matplotlib-3.7.4.tar.gz", hash = "sha256:7cd4fef8187d1dd0d9dcfdbaa06ac326d396fb8c71c647129f0bf56835d77026"}, +] + +[package.dependencies] +contourpy = ">=1.0.1" +cycler = ">=0.10" +fonttools = ">=4.22.0" +importlib-resources = {version = ">=3.2.0", markers = "python_version < \"3.10\""} +kiwisolver = ">=1.0.1" +numpy = ">=1.20,<2" +packaging = ">=20.0" +pillow = ">=6.2.0" +pyparsing = ">=2.3.1" +python-dateutil = ">=2.7" + [[package]] name = "matplotlib" version = "3.8.2" @@ -875,13 +1003,13 @@ mkdocs = ">=1.1" [[package]] name = "mkdocs-material" -version = "9.5.6" +version = "9.5.7" description = "Documentation that simply works" optional = false python-versions = ">=3.8" files = [ - {file = "mkdocs_material-9.5.6-py3-none-any.whl", hash = "sha256:e115b90fccf5cd7f5d15b0c2f8e6246b21041628b8f590630e7fca66ed7fcf6c"}, - {file = "mkdocs_material-9.5.6.tar.gz", hash = "sha256:5b24df36d8ac6cecd611241ce6f6423ccde3e1ad89f8360c3f76d5565fc2d82a"}, + {file = "mkdocs_material-9.5.7-py3-none-any.whl", hash = "sha256:0be8ce8bcfebb52bae9b00cf9b851df45b8a92d629afcfd7f2c09b2dfa155ea3"}, + {file = "mkdocs_material-9.5.7.tar.gz", hash = "sha256:16110292575d88a338d2961f3cb665cf12943ff8829e551a9b364f24019e46af"}, ] [package.dependencies] @@ -931,7 +1059,6 @@ Markdown = ">=3.3" MarkupSafe = ">=1.1" mkdocs = ">=1.2" mkdocs-autorefs = ">=0.3.1" -mkdocstrings-python = {version = ">=0.5.2", optional = true, markers = "extra == \"python\""} pymdown-extensions = ">=6.3" typing-extensions = {version = ">=4.1", markers = "python_version < \"3.10\""} @@ -940,21 +1067,6 @@ crystal = ["mkdocstrings-crystal (>=0.3.4)"] python = ["mkdocstrings-python (>=0.5.2)"] python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"] -[[package]] -name = "mkdocstrings-python" -version = "1.8.0" -description = "A Python handler for mkdocstrings." -optional = false -python-versions = ">=3.8" -files = [ - {file = "mkdocstrings_python-1.8.0-py3-none-any.whl", hash = "sha256:4209970cc90bec194568682a535848a8d8489516c6ed4adbe58bbc67b699ca9d"}, - {file = "mkdocstrings_python-1.8.0.tar.gz", hash = "sha256:1488bddf50ee42c07d9a488dddc197f8e8999c2899687043ec5dd1643d057192"}, -] - -[package.dependencies] -griffe = ">=0.37" -mkdocstrings = ">=0.20" - [[package]] name = "mypy" version = "1.8.0" @@ -1027,6 +1139,43 @@ files = [ [package.dependencies] setuptools = "*" +[[package]] +name = "numpy" +version = "1.24.4" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "numpy-1.24.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0bfb52d2169d58c1cdb8cc1f16989101639b34c7d3ce60ed70b19c63eba0b64"}, + {file = "numpy-1.24.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed094d4f0c177b1b8e7aa9cba7d6ceed51c0e569a5318ac0ca9a090680a6a1b1"}, + {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79fc682a374c4a8ed08b331bef9c5f582585d1048fa6d80bc6c35bc384eee9b4"}, + {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ffe43c74893dbf38c2b0a1f5428760a1a9c98285553c89e12d70a96a7f3a4d6"}, + {file = "numpy-1.24.4-cp310-cp310-win32.whl", hash = "sha256:4c21decb6ea94057331e111a5bed9a79d335658c27ce2adb580fb4d54f2ad9bc"}, + {file = "numpy-1.24.4-cp310-cp310-win_amd64.whl", hash = "sha256:b4bea75e47d9586d31e892a7401f76e909712a0fd510f58f5337bea9572c571e"}, + {file = "numpy-1.24.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f136bab9c2cfd8da131132c2cf6cc27331dd6fae65f95f69dcd4ae3c3639c810"}, + {file = "numpy-1.24.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2926dac25b313635e4d6cf4dc4e51c8c0ebfed60b801c799ffc4c32bf3d1254"}, + {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:222e40d0e2548690405b0b3c7b21d1169117391c2e82c378467ef9ab4c8f0da7"}, + {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7215847ce88a85ce39baf9e89070cb860c98fdddacbaa6c0da3ffb31b3350bd5"}, + {file = "numpy-1.24.4-cp311-cp311-win32.whl", hash = "sha256:4979217d7de511a8d57f4b4b5b2b965f707768440c17cb70fbf254c4b225238d"}, + {file = "numpy-1.24.4-cp311-cp311-win_amd64.whl", hash = "sha256:b7b1fc9864d7d39e28f41d089bfd6353cb5f27ecd9905348c24187a768c79694"}, + {file = "numpy-1.24.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1452241c290f3e2a312c137a9999cdbf63f78864d63c79039bda65ee86943f61"}, + {file = "numpy-1.24.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f"}, + {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5425b114831d1e77e4b5d812b69d11d962e104095a5b9c3b641a218abcc050e"}, + {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd80e219fd4c71fc3699fc1dadac5dcf4fd882bfc6f7ec53d30fa197b8ee22dc"}, + {file = "numpy-1.24.4-cp38-cp38-win32.whl", hash = "sha256:4602244f345453db537be5314d3983dbf5834a9701b7723ec28923e2889e0bb2"}, + {file = "numpy-1.24.4-cp38-cp38-win_amd64.whl", hash = "sha256:692f2e0f55794943c5bfff12b3f56f99af76f902fc47487bdfe97856de51a706"}, + {file = "numpy-1.24.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2541312fbf09977f3b3ad449c4e5f4bb55d0dbf79226d7724211acc905049400"}, + {file = "numpy-1.24.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9667575fb6d13c95f1b36aca12c5ee3356bf001b714fc354eb5465ce1609e62f"}, + {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a86ed21e4f87050382c7bc96571755193c4c1392490744ac73d660e8f564a9"}, + {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d11efb4dbecbdf22508d55e48d9c8384db795e1b7b51ea735289ff96613ff74d"}, + {file = "numpy-1.24.4-cp39-cp39-win32.whl", hash = "sha256:6620c0acd41dbcb368610bb2f4d83145674040025e5536954782467100aa8835"}, + {file = "numpy-1.24.4-cp39-cp39-win_amd64.whl", hash = "sha256:befe2bf740fd8373cf56149a5c23a0f601e82869598d41f8e188a0e9869926f8"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:31f13e25b4e304632a4619d0e0777662c2ffea99fcae2029556b17d8ff958aef"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95f7ac6540e95bc440ad77f56e520da5bf877f87dca58bd095288dce8940532a"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e98f220aa76ca2a977fe435f5b04d7b3470c0a2e6312907b37ba6068f26787f2"}, + {file = "numpy-1.24.4.tar.gz", hash = "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463"}, +] + [[package]] name = "numpy" version = "1.26.3" @@ -1093,6 +1242,50 @@ files = [ {file = "paginate-0.5.6.tar.gz", hash = "sha256:5e6007b6a9398177a7e1648d04fdd9f8c9766a1a945bceac82f1929e8c78af2d"}, ] +[[package]] +name = "pandas" +version = "1.5.3" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pandas-1.5.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3749077d86e3a2f0ed51367f30bf5b82e131cc0f14260c4d3e499186fccc4406"}, + {file = "pandas-1.5.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:972d8a45395f2a2d26733eb8d0f629b2f90bebe8e8eddbb8829b180c09639572"}, + {file = "pandas-1.5.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:50869a35cbb0f2e0cd5ec04b191e7b12ed688874bd05dd777c19b28cbea90996"}, + {file = "pandas-1.5.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3ac844a0fe00bfaeb2c9b51ab1424e5c8744f89860b138434a363b1f620f354"}, + {file = "pandas-1.5.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a0a56cef15fd1586726dace5616db75ebcfec9179a3a55e78f72c5639fa2a23"}, + {file = "pandas-1.5.3-cp310-cp310-win_amd64.whl", hash = "sha256:478ff646ca42b20376e4ed3fa2e8d7341e8a63105586efe54fa2508ee087f328"}, + {file = "pandas-1.5.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6973549c01ca91ec96199e940495219c887ea815b2083722821f1d7abfa2b4dc"}, + {file = "pandas-1.5.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c39a8da13cede5adcd3be1182883aea1c925476f4e84b2807a46e2775306305d"}, + {file = "pandas-1.5.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f76d097d12c82a535fda9dfe5e8dd4127952b45fea9b0276cb30cca5ea313fbc"}, + {file = "pandas-1.5.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e474390e60ed609cec869b0da796ad94f420bb057d86784191eefc62b65819ae"}, + {file = "pandas-1.5.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f2b952406a1588ad4cad5b3f55f520e82e902388a6d5a4a91baa8d38d23c7f6"}, + {file = "pandas-1.5.3-cp311-cp311-win_amd64.whl", hash = "sha256:bc4c368f42b551bf72fac35c5128963a171b40dce866fb066540eeaf46faa003"}, + {file = "pandas-1.5.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:14e45300521902689a81f3f41386dc86f19b8ba8dd5ac5a3c7010ef8d2932813"}, + {file = "pandas-1.5.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9842b6f4b8479e41968eced654487258ed81df7d1c9b7b870ceea24ed9459b31"}, + {file = "pandas-1.5.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:26d9c71772c7afb9d5046e6e9cf42d83dd147b5cf5bcb9d97252077118543792"}, + {file = "pandas-1.5.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fbcb19d6fceb9e946b3e23258757c7b225ba450990d9ed63ccceeb8cae609f7"}, + {file = "pandas-1.5.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:565fa34a5434d38e9d250af3c12ff931abaf88050551d9fbcdfafca50d62babf"}, + {file = "pandas-1.5.3-cp38-cp38-win32.whl", hash = "sha256:87bd9c03da1ac870a6d2c8902a0e1fd4267ca00f13bc494c9e5a9020920e1d51"}, + {file = "pandas-1.5.3-cp38-cp38-win_amd64.whl", hash = "sha256:41179ce559943d83a9b4bbacb736b04c928b095b5f25dd2b7389eda08f46f373"}, + {file = "pandas-1.5.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c74a62747864ed568f5a82a49a23a8d7fe171d0c69038b38cedf0976831296fa"}, + {file = "pandas-1.5.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c4c00e0b0597c8e4f59e8d461f797e5d70b4d025880516a8261b2817c47759ee"}, + {file = "pandas-1.5.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a50d9a4336a9621cab7b8eb3fb11adb82de58f9b91d84c2cd526576b881a0c5a"}, + {file = "pandas-1.5.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd05f7783b3274aa206a1af06f0ceed3f9b412cf665b7247eacd83be41cf7bf0"}, + {file = "pandas-1.5.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f69c4029613de47816b1bb30ff5ac778686688751a5e9c99ad8c7031f6508e5"}, + {file = "pandas-1.5.3-cp39-cp39-win32.whl", hash = "sha256:7cec0bee9f294e5de5bbfc14d0573f65526071029d036b753ee6507d2a21480a"}, + {file = "pandas-1.5.3-cp39-cp39-win_amd64.whl", hash = "sha256:dfd681c5dc216037e0b0a2c821f5ed99ba9f03ebcf119c7dac0e9a7b960b9ec9"}, + {file = "pandas-1.5.3.tar.gz", hash = "sha256:74a3fd7e5a7ec052f183273dc7b0acd3a863edf7520f5d3a1765c04ffdb3b0b1"}, +] + +[package.dependencies] +numpy = {version = ">=1.20.3", markers = "python_version < \"3.10\""} +python-dateutil = ">=2.8.1" +pytz = ">=2020.1" + +[package.extras] +test = ["hypothesis (>=5.5.3)", "pytest (>=6.0)", "pytest-xdist (>=1.31)"] + [[package]] name = "pandas" version = "2.2.0" @@ -1291,6 +1484,24 @@ files = [ dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "pre-commit" +version = "2.21.0" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pre_commit-2.21.0-py2.py3-none-any.whl", hash = "sha256:e2f91727039fc39a92f58a588a25b87f936de6567eed4f0e673e0507edc75bad"}, + {file = "pre_commit-2.21.0.tar.gz", hash = "sha256:31ef31af7e474a8d8995027fefdfcf509b5c913ff31f2015b4ec4beb26a6f658"}, +] + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +virtualenv = ">=20.10.0" + [[package]] name = "pre-commit" version = "3.6.0" @@ -1705,6 +1916,44 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "scipy" +version = "1.10.1" +description = "Fundamental algorithms for scientific computing in Python" +optional = false +python-versions = "<3.12,>=3.8" +files = [ + {file = "scipy-1.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e7354fd7527a4b0377ce55f286805b34e8c54b91be865bac273f527e1b839019"}, + {file = "scipy-1.10.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:4b3f429188c66603a1a5c549fb414e4d3bdc2a24792e061ffbd607d3d75fd84e"}, + {file = "scipy-1.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1553b5dcddd64ba9a0d95355e63fe6c3fc303a8fd77c7bc91e77d61363f7433f"}, + {file = "scipy-1.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c0ff64b06b10e35215abce517252b375e580a6125fd5fdf6421b98efbefb2d2"}, + {file = "scipy-1.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:fae8a7b898c42dffe3f7361c40d5952b6bf32d10c4569098d276b4c547905ee1"}, + {file = "scipy-1.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0f1564ea217e82c1bbe75ddf7285ba0709ecd503f048cb1236ae9995f64217bd"}, + {file = "scipy-1.10.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:d925fa1c81b772882aa55bcc10bf88324dadb66ff85d548c71515f6689c6dac5"}, + {file = "scipy-1.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaea0a6be54462ec027de54fca511540980d1e9eea68b2d5c1dbfe084797be35"}, + {file = "scipy-1.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15a35c4242ec5f292c3dd364a7c71a61be87a3d4ddcc693372813c0b73c9af1d"}, + {file = "scipy-1.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:43b8e0bcb877faf0abfb613d51026cd5cc78918e9530e375727bf0625c82788f"}, + {file = "scipy-1.10.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5678f88c68ea866ed9ebe3a989091088553ba12c6090244fdae3e467b1139c35"}, + {file = "scipy-1.10.1-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:39becb03541f9e58243f4197584286e339029e8908c46f7221abeea4b749fa88"}, + {file = "scipy-1.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bce5869c8d68cf383ce240e44c1d9ae7c06078a9396df68ce88a1230f93a30c1"}, + {file = "scipy-1.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07c3457ce0b3ad5124f98a86533106b643dd811dd61b548e78cf4c8786652f6f"}, + {file = "scipy-1.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:049a8bbf0ad95277ffba9b3b7d23e5369cc39e66406d60422c8cfef40ccc8415"}, + {file = "scipy-1.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cd9f1027ff30d90618914a64ca9b1a77a431159df0e2a195d8a9e8a04c78abf9"}, + {file = "scipy-1.10.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:79c8e5a6c6ffaf3a2262ef1be1e108a035cf4f05c14df56057b64acc5bebffb6"}, + {file = "scipy-1.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:51af417a000d2dbe1ec6c372dfe688e041a7084da4fdd350aeb139bd3fb55353"}, + {file = "scipy-1.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b4735d6c28aad3cdcf52117e0e91d6b39acd4272f3f5cd9907c24ee931ad601"}, + {file = "scipy-1.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:7ff7f37b1bf4417baca958d254e8e2875d0cc23aaadbe65b3d5b3077b0eb23ea"}, + {file = "scipy-1.10.1.tar.gz", hash = "sha256:2cf9dfb80a7b4589ba4c40ce7588986d6d5cebc5457cad2c2880f6bc2d42f3a5"}, +] + +[package.dependencies] +numpy = ">=1.19.5,<1.27.0" + +[package.extras] +dev = ["click", "doit (>=0.36.0)", "flake8", "mypy", "pycodestyle", "pydevtool", "rich-click", "typing_extensions"] +doc = ["matplotlib (>2)", "numpydoc", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-design (>=0.2.0)"] +test = ["asv", "gmpy2", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] + [[package]] name = "scipy" version = "1.12.0" @@ -1938,5 +2187,5 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" -python-versions = ">=3.9,<4.0" -content-hash = "ae356647081e9121d69ef69631a5fa01d3f03219dcdbd66d5a51e3522bdd962d" +python-versions = ">=3.8,<4.0" +content-hash = "30af62c155305b83e686d3e58110635cc55e246e08dceac82fe57dad0cdf68f3" diff --git a/pyproject.toml b/pyproject.toml index e5e7549..1e3f3f1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "traces" version = "0.0.1" description = "A Python library for unevenly-spaced time series analysis" -authors = ["Mike Stringer "] +authors = ["Mike Stringer "] repository = "https://github.com/stringertheory/traces" documentation = "https://stringertheory.github.io/traces/" readme = "README.md" @@ -11,7 +11,7 @@ packages = [ ] [tool.poetry.dependencies] -python = ">=3.9,<4.0" +python = ">=3.8,<4.0" infinity = "^1.5" sortedcontainers = "^2.4.0" @@ -19,19 +19,34 @@ sortedcontainers = "^2.4.0" pytest = "^7.2.0" pytest-cov = "^4.0.0" mypy = "^1.5.1" -pre-commit = "^3.4.0" +pre-commit = [ + {version = "^3.4.0", python = ">=3.9"}, + {version = "^2.20.0", python = ">=3.7,<3.9"} +] tox = "^4.11.1" -numpy = "^1.26.3" -pandas = "^2.2.0" -scipy = "^1.12.0" -matplotlib = "^3.8.2" +numpy = [ + {version = "^1.26.3", python = ">=3.9"}, + {version = "^1.19.5", python = ">=3.7,<3.9"} +] +pandas = [ + {version = "^2.2.0", python = ">=3.9"}, + {version = "^1.3.5", python = ">=3.7,<3.9"} +] +scipy = [ + {version = "^1.12.0", python = ">=3.9"}, + {version = "^1.7.2", python = ">=3.7,<3.9"} +] +matplotlib = [ + {version = "^3.8.2", python = ">=3.9"}, + {version = "^3.5", python = ">=3.7,<3.9"} +] pytest-mpl = "^0.16.1" pyarrow = "^15.0.0" [tool.poetry.group.docs.dependencies] mkdocs = "^1.4.2" mkdocs-material = "^9.2.7" -mkdocstrings = {extras = ["python"], version = "^0.23.0"} +mkdocstrings = "^0.23.0" [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/tox.ini b/tox.ini index 0ab4522..8e1de18 100644 --- a/tox.ini +++ b/tox.ini @@ -1,11 +1,9 @@ [tox] skipsdist = true -envlist = py36, py37, py38, py39, py310, py311, py312 +envlist = py38, py39, py310, py311, py312 [gh-actions] python = - 3.6: py36 - 3.7: py37 3.8: py38 3.9: py39 3.10: py310 @@ -18,4 +16,4 @@ allowlist_externals = poetry commands = poetry install -v pytest --doctest-modules tests --cov --cov-config=pyproject.toml --cov-report=xml - mypy + # mypy diff --git a/traces/timeseries.py b/traces/timeseries.py index 2b66883..f84dd11 100644 --- a/traces/timeseries.py +++ b/traces/timeseries.py @@ -124,9 +124,10 @@ def get(self, time, interpolate="previous"): try: getter = self.getter_functions[interpolate] except KeyError as error: + getter_string = ", ".join(self.getter_functions) msg = ( f"unknown value '{interpolate}' for interpolate, " - f"valid values are in [{", ".join(self.getter_functions)}]" + f"valid values are in [{getter_string}]" ) raise ValueError(msg) from error else: @@ -228,8 +229,8 @@ def remove(self, time): try: del self._d[time] except KeyError as error: - error.add_note(f"no measurement at {time}") - raise + msg = f"no measurement at {time}" + raise KeyError(msg) from error def remove_points_from_interval(self, start, end): """Allow removal of all points from the time series within a interval @@ -499,10 +500,8 @@ def moving_average( # noqa: C901 try: import pandas as pd except ImportError as error: - error.add_note( - "can't have pandas=True if pandas is not installed" - ) - raise + msg = "can't have pandas=True if pandas is not installed" + raise ImportError(msg) from error result = pd.Series( [v for t, v in result], From c577c6b6106e75345cbd62ea9921aee3d4f0f909 Mon Sep 17 00:00:00 2001 From: stringertheory Date: Sat, 3 Feb 2024 01:04:13 -0600 Subject: [PATCH 18/18] docs working --- Makefile | 3 +- docs/conf.py | 4 +- poetry.lock | 391 ++++++++++++++++++++++++++++++++++++++++++++++++- pyproject.toml | 7 + 4 files changed, 401 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index b04ec8d..dd50a46 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,8 @@ docs-test: ## Test if documentation can be built without warnings or errors .PHONY: docs docs: ## Build and serve the documentation - @poetry run mkdocs serve + # @poetry run mkdocs serve -a localhost:8002 + @poetry run sphinx-autobuild --port 8002 docs docs/_build/html .PHONY: help help: diff --git a/docs/conf.py b/docs/conf.py index 2c6259c..089357d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -30,7 +30,7 @@ "sphinx.ext.autodoc", "sphinx.ext.mathjax", "sphinx.ext.viewcode", - "sphinxcontrib.napoleon", + "sphinx.ext.napoleon", ] # Add any paths that contain templates here, relative to this directory. @@ -63,7 +63,7 @@ # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +language = "en" # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. diff --git a/poetry.lock b/poetry.lock index 0989363..b1e3e8d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,5 +1,27 @@ # This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +[[package]] +name = "alabaster" +version = "0.7.13" +description = "A configurable sidebar-enabled Sphinx theme" +optional = false +python-versions = ">=3.6" +files = [ + {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"}, + {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"}, +] + +[[package]] +name = "alabaster" +version = "0.7.16" +description = "A light, configurable Sphinx theme" +optional = false +python-versions = ">=3.9" +files = [ + {file = "alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92"}, + {file = "alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65"}, +] + [[package]] name = "babel" version = "2.14.0" @@ -185,6 +207,20 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "commonmark" +version = "0.9.1" +description = "Python parser for the CommonMark Markdown spec" +optional = false +python-versions = "*" +files = [ + {file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"}, + {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, +] + +[package.extras] +test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] + [[package]] name = "contourpy" version = "1.1.1" @@ -412,6 +448,28 @@ files = [ {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, ] +[[package]] +name = "docutils" +version = "0.19" +description = "Docutils -- Python Documentation Utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "docutils-0.19-py3-none-any.whl", hash = "sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc"}, + {file = "docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6"}, +] + +[[package]] +name = "docutils" +version = "0.20.1" +description = "Docutils -- Python Documentation Utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, + {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, +] + [[package]] name = "exceptiongroup" version = "1.2.0" @@ -549,6 +607,17 @@ files = [ {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, ] +[[package]] +name = "imagesize" +version = "1.4.1" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, + {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, +] + [[package]] name = "importlib-metadata" version = "7.0.1" @@ -740,6 +809,21 @@ files = [ {file = "kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec"}, ] +[[package]] +name = "livereload" +version = "2.6.3" +description = "Python LiveReload is an awesome tool for web developers" +optional = false +python-versions = "*" +files = [ + {file = "livereload-2.6.3-py2.py3-none-any.whl", hash = "sha256:ad4ac6f53b2d62bb6ce1a5e6e96f1f00976a32348afedcb4b6d68df2a1d346e4"}, + {file = "livereload-2.6.3.tar.gz", hash = "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"}, +] + +[package.dependencies] +six = "*" +tornado = {version = "*", markers = "python_version > \"2.7\""} + [[package]] name = "markdown" version = "3.5.2" @@ -1793,6 +1877,22 @@ files = [ [package.dependencies] pyyaml = "*" +[[package]] +name = "recommonmark" +version = "0.7.1" +description = "A docutils-compatibility bridge to CommonMark, enabling you to write CommonMark inside of Docutils & Sphinx projects." +optional = false +python-versions = "*" +files = [ + {file = "recommonmark-0.7.1-py2.py3-none-any.whl", hash = "sha256:1b1db69af0231efce3fa21b94ff627ea33dee7079a01dd0a7f8482c3da148b3f"}, + {file = "recommonmark-0.7.1.tar.gz", hash = "sha256:bdb4db649f2222dcd8d2d844f0006b958d627f732415d399791ee436a3686d67"}, +] + +[package.dependencies] +commonmark = ">=0.8.1" +docutils = ">=0.11" +sphinx = ">=1.3.1" + [[package]] name = "regex" version = "2023.12.25" @@ -2023,6 +2123,17 @@ files = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] +[[package]] +name = "snowballstemmer" +version = "2.2.0" +description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +optional = false +python-versions = "*" +files = [ + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, +] + [[package]] name = "sortedcontainers" version = "2.4.0" @@ -2034,6 +2145,264 @@ files = [ {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, ] +[[package]] +name = "sphinx" +version = "6.2.1" +description = "Python documentation generator" +optional = false +python-versions = ">=3.8" +files = [ + {file = "Sphinx-6.2.1.tar.gz", hash = "sha256:6d56a34697bb749ffa0152feafc4b19836c755d90a7c59b72bc7dfd371b9cc6b"}, + {file = "sphinx-6.2.1-py3-none-any.whl", hash = "sha256:97787ff1fa3256a3eef9eda523a63dbf299f7b47e053cfcf684a1c2a8380c912"}, +] + +[package.dependencies] +alabaster = ">=0.7,<0.8" +babel = ">=2.9" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +docutils = ">=0.18.1,<0.20" +imagesize = ">=1.3" +importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""} +Jinja2 = ">=3.0" +packaging = ">=21.0" +Pygments = ">=2.13" +requests = ">=2.25.0" +snowballstemmer = ">=2.0" +sphinxcontrib-applehelp = "*" +sphinxcontrib-devhelp = "*" +sphinxcontrib-htmlhelp = ">=2.0.0" +sphinxcontrib-jsmath = "*" +sphinxcontrib-qthelp = "*" +sphinxcontrib-serializinghtml = ">=1.1.5" + +[package.extras] +docs = ["sphinxcontrib-websupport"] +lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-simplify", "isort", "mypy (>=0.990)", "ruff", "sphinx-lint", "types-requests"] +test = ["cython", "filelock", "html5lib", "pytest (>=4.6)"] + +[[package]] +name = "sphinx" +version = "7.2.6" +description = "Python documentation generator" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinx-7.2.6-py3-none-any.whl", hash = "sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560"}, + {file = "sphinx-7.2.6.tar.gz", hash = "sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5"}, +] + +[package.dependencies] +alabaster = ">=0.7,<0.8" +babel = ">=2.9" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +docutils = ">=0.18.1,<0.21" +imagesize = ">=1.3" +importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""} +Jinja2 = ">=3.0" +packaging = ">=21.0" +Pygments = ">=2.14" +requests = ">=2.25.0" +snowballstemmer = ">=2.0" +sphinxcontrib-applehelp = "*" +sphinxcontrib-devhelp = "*" +sphinxcontrib-htmlhelp = ">=2.0.0" +sphinxcontrib-jsmath = "*" +sphinxcontrib-qthelp = "*" +sphinxcontrib-serializinghtml = ">=1.1.9" + +[package.extras] +docs = ["sphinxcontrib-websupport"] +lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-simplify", "isort", "mypy (>=0.990)", "ruff", "sphinx-lint", "types-requests"] +test = ["cython (>=3.0)", "filelock", "html5lib", "pytest (>=4.6)", "setuptools (>=67.0)"] + +[[package]] +name = "sphinx-autobuild" +version = "2021.3.14" +description = "Rebuild Sphinx documentation on changes, with live-reload in the browser." +optional = false +python-versions = ">=3.6" +files = [ + {file = "sphinx-autobuild-2021.3.14.tar.gz", hash = "sha256:de1ca3b66e271d2b5b5140c35034c89e47f263f2cd5db302c9217065f7443f05"}, + {file = "sphinx_autobuild-2021.3.14-py3-none-any.whl", hash = "sha256:8fe8cbfdb75db04475232f05187c776f46f6e9e04cacf1e49ce81bdac649ccac"}, +] + +[package.dependencies] +colorama = "*" +livereload = "*" +sphinx = "*" + +[package.extras] +test = ["pytest", "pytest-cov"] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "1.0.4" +description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" +optional = false +python-versions = ">=3.8" +files = [ + {file = "sphinxcontrib-applehelp-1.0.4.tar.gz", hash = "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e"}, + {file = "sphinxcontrib_applehelp-1.0.4-py3-none-any.whl", hash = "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "1.0.8" +description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_applehelp-1.0.8-py3-none-any.whl", hash = "sha256:cb61eb0ec1b61f349e5cc36b2028e9e7ca765be05e49641c97241274753067b4"}, + {file = "sphinxcontrib_applehelp-1.0.8.tar.gz", hash = "sha256:c40a4f96f3776c4393d933412053962fac2b84f4c99a7982ba42e09576a70619"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "1.0.2" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, + {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "1.0.6" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_devhelp-1.0.6-py3-none-any.whl", hash = "sha256:6485d09629944511c893fa11355bda18b742b83a2b181f9a009f7e500595c90f"}, + {file = "sphinxcontrib_devhelp-1.0.6.tar.gz", hash = "sha256:9893fd3f90506bc4b97bdb977ceb8fbd823989f4316b28c3841ec128544372d3"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.0.1" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "sphinxcontrib-htmlhelp-2.0.1.tar.gz", hash = "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff"}, + {file = "sphinxcontrib_htmlhelp-2.0.1-py3-none-any.whl", hash = "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["html5lib", "pytest"] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.0.5" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_htmlhelp-2.0.5-py3-none-any.whl", hash = "sha256:393f04f112b4d2f53d93448d4bce35842f62b307ccdc549ec1585e950bc35e04"}, + {file = "sphinxcontrib_htmlhelp-2.0.5.tar.gz", hash = "sha256:0dc87637d5de53dd5eec3a6a01753b1ccf99494bd756aafecd74b4fa9e729015"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] +test = ["html5lib", "pytest"] + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +description = "A sphinx extension which renders display math in HTML via JavaScript" +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, + {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, +] + +[package.extras] +test = ["flake8", "mypy", "pytest"] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "1.0.3" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, + {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "1.0.7" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_qthelp-1.0.7-py3-none-any.whl", hash = "sha256:e2ae3b5c492d58fcbd73281fbd27e34b8393ec34a073c792642cd8e529288182"}, + {file = "sphinxcontrib_qthelp-1.0.7.tar.gz", hash = "sha256:053dedc38823a80a7209a80860b16b722e9e0209e32fea98c90e4e6624588ed6"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "1.1.5" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, + {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "1.1.10" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_serializinghtml-1.1.10-py3-none-any.whl", hash = "sha256:326369b8df80a7d2d8d7f99aa5ac577f51ea51556ed974e7716cfd4fca3f6cb7"}, + {file = "sphinxcontrib_serializinghtml-1.1.10.tar.gz", hash = "sha256:93f3f5dc458b91b192fe10c397e324f262cf163d79f3282c158e8436a2c4511f"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + [[package]] name = "tomli" version = "2.0.1" @@ -2045,6 +2414,26 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] +[[package]] +name = "tornado" +version = "6.4" +description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +optional = false +python-versions = ">= 3.8" +files = [ + {file = "tornado-6.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:02ccefc7d8211e5a7f9e8bc3f9e5b0ad6262ba2fbb683a6443ecc804e5224ce0"}, + {file = "tornado-6.4-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:27787de946a9cffd63ce5814c33f734c627a87072ec7eed71f7fc4417bb16263"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7894c581ecdcf91666a0912f18ce5e757213999e183ebfc2c3fdbf4d5bd764e"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e43bc2e5370a6a8e413e1e1cd0c91bedc5bd62a74a532371042a18ef19e10579"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0251554cdd50b4b44362f73ad5ba7126fc5b2c2895cc62b14a1c2d7ea32f212"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fd03192e287fbd0899dd8f81c6fb9cbbc69194d2074b38f384cb6fa72b80e9c2"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:88b84956273fbd73420e6d4b8d5ccbe913c65d31351b4c004ae362eba06e1f78"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:71ddfc23a0e03ef2df1c1397d859868d158c8276a0603b96cf86892bff58149f"}, + {file = "tornado-6.4-cp38-abi3-win32.whl", hash = "sha256:6f8a6c77900f5ae93d8b4ae1196472d0ccc2775cc1dfdc9e7727889145c45052"}, + {file = "tornado-6.4-cp38-abi3-win_amd64.whl", hash = "sha256:10aeaa8006333433da48dec9fe417877f8bcc21f48dda8d661ae79da357b2a63"}, + {file = "tornado-6.4.tar.gz", hash = "sha256:72291fa6e6bc84e626589f1c29d90a5a6d593ef5ae68052ee2ef000dfd273dee"}, +] + [[package]] name = "tox" version = "4.12.1" @@ -2188,4 +2577,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.8,<4.0" -content-hash = "30af62c155305b83e686d3e58110635cc55e246e08dceac82fe57dad0cdf68f3" +content-hash = "743b745ca0e0935fd2572dbfa9252969fe50f74c7240b72e7fec5f3f3e55bba0" diff --git a/pyproject.toml b/pyproject.toml index 1e3f3f1..4f1b1f0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,6 +47,13 @@ pyarrow = "^15.0.0" mkdocs = "^1.4.2" mkdocs-material = "^9.2.7" mkdocstrings = "^0.23.0" +sphinx = [ + {version = "^7.2.6", python = ">=3.9"}, + {version = "^6.0", python = ">=3.8,<3.9"}, +] +sphinx-autobuild = "^2021.3.14" +recommonmark = "^0.7.1" + [build-system] requires = ["poetry-core>=1.0.0"]