Clean up on_load events (#965)

This commit is contained in:
Nikhil Rao 2023-05-08 12:13:51 -07:00 committed by GitHub
parent 4515561e61
commit 8e3daf9f5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 259 additions and 307 deletions

257
poetry.lock generated
View File

@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry 1.4.1 and should not be changed by hand. # This file is automatically @generated by Poetry 1.4.0 and should not be changed by hand.
[[package]] [[package]]
name = "anyio" name = "anyio"
@ -37,25 +37,6 @@ files = [
[package.dependencies] [package.dependencies]
typing-extensions = {version = ">=3.6.5", markers = "python_version < \"3.8\""} typing-extensions = {version = ">=3.6.5", markers = "python_version < \"3.8\""}
[[package]]
name = "attrs"
version = "22.2.0"
description = "Classes Without Boilerplate"
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
{file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"},
{file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"},
]
[package.extras]
cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"]
dev = ["attrs[docs,tests]"]
docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"]
tests = ["attrs[tests-no-zope]", "zope.interface"]
tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"]
[[package]] [[package]]
name = "bidict" name = "bidict"
version = "0.22.1" version = "0.22.1"
@ -112,14 +93,14 @@ uvloop = ["uvloop (>=0.15.2)"]
[[package]] [[package]]
name = "certifi" name = "certifi"
version = "2022.12.7" version = "2023.5.7"
description = "Python package for providing Mozilla's CA Bundle." description = "Python package for providing Mozilla's CA Bundle."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
files = [ files = [
{file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"},
{file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"},
] ]
[[package]] [[package]]
@ -215,14 +196,14 @@ files = [
[[package]] [[package]]
name = "exceptiongroup" name = "exceptiongroup"
version = "1.1.0" version = "1.1.1"
description = "Backport of PEP 654 (exception groups)" description = "Backport of PEP 654 (exception groups)"
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "exceptiongroup-1.1.0-py3-none-any.whl", hash = "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e"}, {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"},
{file = "exceptiongroup-1.1.0.tar.gz", hash = "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"}, {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"},
] ]
[package.extras] [package.extras]
@ -252,19 +233,19 @@ test = ["anyio[trio] (>=3.2.1,<4.0.0)", "black (==22.10.0)", "coverage[toml] (>=
[[package]] [[package]]
name = "filelock" name = "filelock"
version = "3.10.6" version = "3.12.0"
description = "A platform independent file lock." description = "A platform independent file lock."
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "filelock-3.10.6-py3-none-any.whl", hash = "sha256:52f119747b2b9c4730dac715a7b1ab34b8ee70fd9259cba158ee53da566387ff"}, {file = "filelock-3.12.0-py3-none-any.whl", hash = "sha256:ad98852315c2ab702aeb628412cbf7e95b7ce8c3bf9565670b4eaecf1db370a9"},
{file = "filelock-3.10.6.tar.gz", hash = "sha256:409105becd604d6b176a483f855e7e8903c5cb2873e47f2c64f66a370c046aaf"}, {file = "filelock-3.12.0.tar.gz", hash = "sha256:fc03ae43288c013d2ea83c8597001b1129db351aad9c57fe2409327916b8e718"},
] ]
[package.extras] [package.extras]
docs = ["furo (>=2022.12.7)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] docs = ["furo (>=2023.3.27)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
testing = ["covdefaults (>=2.3)", "coverage (>=7.2.2)", "diff-cover (>=7.5)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"] testing = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"]
[[package]] [[package]]
name = "greenlet" name = "greenlet"
@ -424,14 +405,14 @@ socks = ["socksio (>=1.0.0,<2.0.0)"]
[[package]] [[package]]
name = "identify" name = "identify"
version = "2.5.22" version = "2.5.24"
description = "File identification library for Python" description = "File identification library for Python"
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "identify-2.5.22-py2.py3-none-any.whl", hash = "sha256:f0faad595a4687053669c112004178149f6c326db71ee999ae4636685753ad2f"}, {file = "identify-2.5.24-py2.py3-none-any.whl", hash = "sha256:986dbfb38b1140e763e413e6feb44cd731faf72d1909543178aa79b0e258265d"},
{file = "identify-2.5.22.tar.gz", hash = "sha256:f7a93d6cf98e29bd07663c60728e7a4057615068d7a639d132dc883b2d54d31e"}, {file = "identify-2.5.24.tar.gz", hash = "sha256:0aac67d5b4812498056d28a9a512a483f5085cc28640b02b258a59dac34301d4"},
] ]
[package.extras] [package.extras]
@ -451,14 +432,14 @@ files = [
[[package]] [[package]]
name = "importlib-metadata" name = "importlib-metadata"
version = "6.0.0" version = "6.6.0"
description = "Read metadata from Python packages" description = "Read metadata from Python packages"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "importlib_metadata-6.0.0-py3-none-any.whl", hash = "sha256:7efb448ec9a5e313a57655d35aa54cd3e01b7e1fbcf72dce1bf06119420f5bad"}, {file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"},
{file = "importlib_metadata-6.0.0.tar.gz", hash = "sha256:e354bedeb60efa6affdcc8ae121b73544a7aa74156d047311948f6d711cd378d"}, {file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"},
] ]
[package.dependencies] [package.dependencies]
@ -552,52 +533,52 @@ files = [
[[package]] [[package]]
name = "numpy" name = "numpy"
version = "1.24.2" version = "1.24.3"
description = "Fundamental package for array computing in Python" description = "Fundamental package for array computing in Python"
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "numpy-1.24.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eef70b4fc1e872ebddc38cddacc87c19a3709c0e3e5d20bf3954c147b1dd941d"}, {file = "numpy-1.24.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3c1104d3c036fb81ab923f507536daedc718d0ad5a8707c6061cdfd6d184e570"},
{file = "numpy-1.24.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8d2859428712785e8a8b7d2b3ef0a1d1565892367b32f915c4a4df44d0e64f5"}, {file = "numpy-1.24.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:202de8f38fc4a45a3eea4b63e2f376e5f2dc64ef0fa692838e31a808520efaf7"},
{file = "numpy-1.24.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6524630f71631be2dabe0c541e7675db82651eb998496bbe16bc4f77f0772253"}, {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8535303847b89aa6b0f00aa1dc62867b5a32923e4d1681a35b5eef2d9591a463"},
{file = "numpy-1.24.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a51725a815a6188c662fb66fb32077709a9ca38053f0274640293a14fdd22978"}, {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d926b52ba1367f9acb76b0df6ed21f0b16a1ad87c6720a1121674e5cf63e2b6"},
{file = "numpy-1.24.2-cp310-cp310-win32.whl", hash = "sha256:2620e8592136e073bd12ee4536149380695fbe9ebeae845b81237f986479ffc9"}, {file = "numpy-1.24.3-cp310-cp310-win32.whl", hash = "sha256:f21c442fdd2805e91799fbe044a7b999b8571bb0ab0f7850d0cb9641a687092b"},
{file = "numpy-1.24.2-cp310-cp310-win_amd64.whl", hash = "sha256:97cf27e51fa078078c649a51d7ade3c92d9e709ba2bfb97493007103c741f1d0"}, {file = "numpy-1.24.3-cp310-cp310-win_amd64.whl", hash = "sha256:ab5f23af8c16022663a652d3b25dcdc272ac3f83c3af4c02eb8b824e6b3ab9d7"},
{file = "numpy-1.24.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7de8fdde0003f4294655aa5d5f0a89c26b9f22c0a58790c38fae1ed392d44a5a"}, {file = "numpy-1.24.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9a7721ec204d3a237225db3e194c25268faf92e19338a35f3a224469cb6039a3"},
{file = "numpy-1.24.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4173bde9fa2a005c2c6e2ea8ac1618e2ed2c1c6ec8a7657237854d42094123a0"}, {file = "numpy-1.24.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d6cc757de514c00b24ae8cf5c876af2a7c3df189028d68c0cb4eaa9cd5afc2bf"},
{file = "numpy-1.24.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cecaed30dc14123020f77b03601559fff3e6cd0c048f8b5289f4eeabb0eb281"}, {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76e3f4e85fc5d4fd311f6e9b794d0c00e7002ec122be271f2019d63376f1d385"},
{file = "numpy-1.24.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a23f8440561a633204a67fb44617ce2a299beecf3295f0d13c495518908e910"}, {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1d3c026f57ceaad42f8231305d4653d5f05dc6332a730ae5c0bea3513de0950"},
{file = "numpy-1.24.2-cp311-cp311-win32.whl", hash = "sha256:e428c4fbfa085f947b536706a2fc349245d7baa8334f0c5723c56a10595f9b95"}, {file = "numpy-1.24.3-cp311-cp311-win32.whl", hash = "sha256:c91c4afd8abc3908e00a44b2672718905b8611503f7ff87390cc0ac3423fb096"},
{file = "numpy-1.24.2-cp311-cp311-win_amd64.whl", hash = "sha256:557d42778a6869c2162deb40ad82612645e21d79e11c1dc62c6e82a2220ffb04"}, {file = "numpy-1.24.3-cp311-cp311-win_amd64.whl", hash = "sha256:5342cf6aad47943286afa6f1609cad9b4266a05e7f2ec408e2cf7aea7ff69d80"},
{file = "numpy-1.24.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d0a2db9d20117bf523dde15858398e7c0858aadca7c0f088ac0d6edd360e9ad2"}, {file = "numpy-1.24.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7776ea65423ca6a15255ba1872d82d207bd1e09f6d0894ee4a64678dd2204078"},
{file = "numpy-1.24.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c72a6b2f4af1adfe193f7beb91ddf708ff867a3f977ef2ec53c0ffb8283ab9f5"}, {file = "numpy-1.24.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ae8d0be48d1b6ed82588934aaaa179875e7dc4f3d84da18d7eae6eb3f06c242c"},
{file = "numpy-1.24.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c29e6bd0ec49a44d7690ecb623a8eac5ab8a923bce0bea6293953992edf3a76a"}, {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecde0f8adef7dfdec993fd54b0f78183051b6580f606111a6d789cd14c61ea0c"},
{file = "numpy-1.24.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2eabd64ddb96a1239791da78fa5f4e1693ae2dadc82a76bc76a14cbb2b966e96"}, {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4749e053a29364d3452c034827102ee100986903263e89884922ef01a0a6fd2f"},
{file = "numpy-1.24.2-cp38-cp38-win32.whl", hash = "sha256:e3ab5d32784e843fc0dd3ab6dcafc67ef806e6b6828dc6af2f689be0eb4d781d"}, {file = "numpy-1.24.3-cp38-cp38-win32.whl", hash = "sha256:d933fabd8f6a319e8530d0de4fcc2e6a61917e0b0c271fded460032db42a0fe4"},
{file = "numpy-1.24.2-cp38-cp38-win_amd64.whl", hash = "sha256:76807b4063f0002c8532cfeac47a3068a69561e9c8715efdad3c642eb27c0756"}, {file = "numpy-1.24.3-cp38-cp38-win_amd64.whl", hash = "sha256:56e48aec79ae238f6e4395886b5eaed058abb7231fb3361ddd7bfdf4eed54289"},
{file = "numpy-1.24.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4199e7cfc307a778f72d293372736223e39ec9ac096ff0a2e64853b866a8e18a"}, {file = "numpy-1.24.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4719d5aefb5189f50887773699eaf94e7d1e02bf36c1a9d353d9f46703758ca4"},
{file = "numpy-1.24.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:adbdce121896fd3a17a77ab0b0b5eedf05a9834a18699db6829a64e1dfccca7f"}, {file = "numpy-1.24.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ec87a7084caa559c36e0a2309e4ecb1baa03b687201d0a847c8b0ed476a7187"},
{file = "numpy-1.24.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:889b2cc88b837d86eda1b17008ebeb679d82875022200c6e8e4ce6cf549b7acb"}, {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea8282b9bcfe2b5e7d491d0bf7f3e2da29700cec05b49e64d6246923329f2b02"},
{file = "numpy-1.24.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f64bb98ac59b3ea3bf74b02f13836eb2e24e48e0ab0145bbda646295769bd780"}, {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210461d87fb02a84ef243cac5e814aad2b7f4be953b32cb53327bb49fd77fbb4"},
{file = "numpy-1.24.2-cp39-cp39-win32.whl", hash = "sha256:63e45511ee4d9d976637d11e6c9864eae50e12dc9598f531c035265991910468"}, {file = "numpy-1.24.3-cp39-cp39-win32.whl", hash = "sha256:784c6da1a07818491b0ffd63c6bbe5a33deaa0e25a20e1b3ea20cf0e43f8046c"},
{file = "numpy-1.24.2-cp39-cp39-win_amd64.whl", hash = "sha256:a77d3e1163a7770164404607b7ba3967fb49b24782a6ef85d9b5f54126cc39e5"}, {file = "numpy-1.24.3-cp39-cp39-win_amd64.whl", hash = "sha256:d5036197ecae68d7f491fcdb4df90082b0d4960ca6599ba2659957aafced7c17"},
{file = "numpy-1.24.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:92011118955724465fb6853def593cf397b4a1367495e0b59a7e69d40c4eb71d"}, {file = "numpy-1.24.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:352ee00c7f8387b44d19f4cada524586f07379c0d49270f87233983bc5087ca0"},
{file = "numpy-1.24.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9006288bcf4895917d02583cf3411f98631275bc67cce355a7f39f8c14338fa"}, {file = "numpy-1.24.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7d6acc2e7524c9955e5c903160aa4ea083736fde7e91276b0e5d98e6332812"},
{file = "numpy-1.24.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:150947adbdfeceec4e5926d956a06865c1c690f2fd902efede4ca6fe2e657c3f"}, {file = "numpy-1.24.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:35400e6a8d102fd07c71ed7dcadd9eb62ee9a6e84ec159bd48c28235bbb0f8e4"},
{file = "numpy-1.24.2.tar.gz", hash = "sha256:003a9f530e880cb2cd177cba1af7220b9aa42def9c4afc2a2fc3ee6be7eb2b22"}, {file = "numpy-1.24.3.tar.gz", hash = "sha256:ab344f1bf21f140adab8e47fdbc7c35a477dc01408791f8ba00d018dd0bc5155"},
] ]
[[package]] [[package]]
name = "packaging" name = "packaging"
version = "23.0" version = "23.1"
description = "Core utilities for Python packages" description = "Core utilities for Python packages"
category = "dev" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
{file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
] ]
[[package]] [[package]]
@ -693,48 +674,49 @@ test = ["hypothesis (>=5.5.3)", "pytest (>=6.0)", "pytest-xdist (>=1.31)"]
[[package]] [[package]]
name = "pathspec" name = "pathspec"
version = "0.11.0" version = "0.11.1"
description = "Utility library for gitignore style pattern matching of file paths." description = "Utility library for gitignore style pattern matching of file paths."
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "pathspec-0.11.0-py3-none-any.whl", hash = "sha256:3a66eb970cbac598f9e5ccb5b2cf58930cd8e3ed86d393d541eaf2d8b1705229"}, {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"},
{file = "pathspec-0.11.0.tar.gz", hash = "sha256:64d338d4e0914e91c1792321e6907b5a593f1ab1851de7fc269557a21b30ebbc"}, {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"},
] ]
[[package]] [[package]]
name = "platformdirs" name = "platformdirs"
version = "3.1.0" version = "3.5.0"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "platformdirs-3.1.0-py3-none-any.whl", hash = "sha256:13b08a53ed71021350c9e300d4ea8668438fb0046ab3937ac9a29913a1a1350a"}, {file = "platformdirs-3.5.0-py3-none-any.whl", hash = "sha256:47692bc24c1958e8b0f13dd727307cff1db103fca36399f457da8e05f222fdc4"},
{file = "platformdirs-3.1.0.tar.gz", hash = "sha256:accc3665857288317f32c7bebb5a8e482ba717b474f3fc1d18ca7f9214be0cef"}, {file = "platformdirs-3.5.0.tar.gz", hash = "sha256:7954a68d0ba23558d753f73437c55f89027cf8f5108c19844d4b82e5af396335"},
] ]
[package.dependencies] [package.dependencies]
typing-extensions = {version = ">=4.4", markers = "python_version < \"3.8\""} typing-extensions = {version = ">=4.5", markers = "python_version < \"3.8\""}
[package.extras] [package.extras]
docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
[[package]] [[package]]
name = "plotly" name = "plotly"
version = "5.13.1" version = "5.14.1"
description = "An open-source, interactive data visualization library for Python" description = "An open-source, interactive data visualization library for Python"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
files = [ files = [
{file = "plotly-5.13.1-py2.py3-none-any.whl", hash = "sha256:f776a5c664908450c6c1727f61e8e2e22798d9c6c69d37a9057735365084a2fa"}, {file = "plotly-5.14.1-py2.py3-none-any.whl", hash = "sha256:a63f3ad9e4cc2e02902a738e5e3e7f3d1307f2732ac71a6c28f1238ed3052826"},
{file = "plotly-5.13.1.tar.gz", hash = "sha256:90ee9a1fee0dda30e2830e129855081ea17bd1b06a553a62b62de15caff1a219"}, {file = "plotly-5.14.1.tar.gz", hash = "sha256:bcac86d7fcba3eff7260c1eddc36ca34dae2aded10a0709808446565e0e53b93"},
] ]
[package.dependencies] [package.dependencies]
packaging = "*"
tenacity = ">=6.2.0" tenacity = ">=6.2.0"
[[package]] [[package]]
@ -758,14 +740,14 @@ testing = ["pytest", "pytest-benchmark"]
[[package]] [[package]]
name = "pre-commit" name = "pre-commit"
version = "3.2.1" version = "3.3.1"
description = "A framework for managing and maintaining multi-language pre-commit hooks." description = "A framework for managing and maintaining multi-language pre-commit hooks."
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "pre_commit-3.2.1-py2.py3-none-any.whl", hash = "sha256:a06a7fcce7f420047a71213c175714216498b49ebc81fe106f7716ca265f5bb6"}, {file = "pre_commit-3.3.1-py2.py3-none-any.whl", hash = "sha256:218e9e3f7f7f3271ebc355a15598a4d3893ad9fc7b57fe446db75644543323b9"},
{file = "pre_commit-3.2.1.tar.gz", hash = "sha256:b5aee7d75dbba21ee161ba641b01e7ae10c5b91967ebf7b2ab0dfae12d07e1f1"}, {file = "pre_commit-3.3.1.tar.gz", hash = "sha256:733f78c9a056cdd169baa6cd4272d51ecfda95346ef8a89bf93712706021b907"},
] ]
[package.dependencies] [package.dependencies]
@ -777,26 +759,26 @@ virtualenv = ">=20.10.0"
[[package]] [[package]]
name = "psutil" name = "psutil"
version = "5.9.4" version = "5.9.5"
description = "Cross-platform lib for process and system monitoring in Python." description = "Cross-platform lib for process and system monitoring in Python."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [ files = [
{file = "psutil-5.9.4-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c1ca331af862803a42677c120aff8a814a804e09832f166f226bfd22b56feee8"}, {file = "psutil-5.9.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:be8929ce4313f9f8146caad4272f6abb8bf99fc6cf59344a3167ecd74f4f203f"},
{file = "psutil-5.9.4-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:68908971daf802203f3d37e78d3f8831b6d1014864d7a85937941bb35f09aefe"}, {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ab8ed1a1d77c95453db1ae00a3f9c50227ebd955437bcf2a574ba8adbf6a74d5"},
{file = "psutil-5.9.4-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:3ff89f9b835100a825b14c2808a106b6fdcc4b15483141482a12c725e7f78549"}, {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4aef137f3345082a3d3232187aeb4ac4ef959ba3d7c10c33dd73763fbc063da4"},
{file = "psutil-5.9.4-cp27-cp27m-win32.whl", hash = "sha256:852dd5d9f8a47169fe62fd4a971aa07859476c2ba22c2254d4a1baa4e10b95ad"}, {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ea8518d152174e1249c4f2a1c89e3e6065941df2fa13a1ab45327716a23c2b48"},
{file = "psutil-5.9.4-cp27-cp27m-win_amd64.whl", hash = "sha256:9120cd39dca5c5e1c54b59a41d205023d436799b1c8c4d3ff71af18535728e94"}, {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:acf2aef9391710afded549ff602b5887d7a2349831ae4c26be7c807c0a39fac4"},
{file = "psutil-5.9.4-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6b92c532979bafc2df23ddc785ed116fced1f492ad90a6830cf24f4d1ea27d24"}, {file = "psutil-5.9.5-cp27-none-win32.whl", hash = "sha256:5b9b8cb93f507e8dbaf22af6a2fd0ccbe8244bf30b1baad6b3954e935157ae3f"},
{file = "psutil-5.9.4-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:efeae04f9516907be44904cc7ce08defb6b665128992a56957abc9b61dca94b7"}, {file = "psutil-5.9.5-cp27-none-win_amd64.whl", hash = "sha256:8c5f7c5a052d1d567db4ddd231a9d27a74e8e4a9c3f44b1032762bd7b9fdcd42"},
{file = "psutil-5.9.4-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:54d5b184728298f2ca8567bf83c422b706200bcbbfafdc06718264f9393cfeb7"}, {file = "psutil-5.9.5-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3c6f686f4225553615612f6d9bc21f1c0e305f75d7d8454f9b46e901778e7217"},
{file = "psutil-5.9.4-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16653106f3b59386ffe10e0bad3bb6299e169d5327d3f187614b1cb8f24cf2e1"}, {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a7dd9997128a0d928ed4fb2c2d57e5102bb6089027939f3b722f3a210f9a8da"},
{file = "psutil-5.9.4-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54c0d3d8e0078b7666984e11b12b88af2db11d11249a8ac8920dd5ef68a66e08"}, {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89518112647f1276b03ca97b65cc7f64ca587b1eb0278383017c2a0dcc26cbe4"},
{file = "psutil-5.9.4-cp36-abi3-win32.whl", hash = "sha256:149555f59a69b33f056ba1c4eb22bb7bf24332ce631c44a319cec09f876aaeff"}, {file = "psutil-5.9.5-cp36-abi3-win32.whl", hash = "sha256:104a5cc0e31baa2bcf67900be36acde157756b9c44017b86b2c049f11957887d"},
{file = "psutil-5.9.4-cp36-abi3-win_amd64.whl", hash = "sha256:fd8522436a6ada7b4aad6638662966de0d61d241cb821239b2ae7013d41a43d4"}, {file = "psutil-5.9.5-cp36-abi3-win_amd64.whl", hash = "sha256:b258c0c1c9d145a1d5ceffab1134441c4c5113b2417fafff7315a917a026c3c9"},
{file = "psutil-5.9.4-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:6001c809253a29599bc0dfd5179d9f8a5779f9dffea1da0f13c53ee568115e1e"}, {file = "psutil-5.9.5-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:c607bb3b57dc779d55e1554846352b4e358c10fff3abf3514a7a6601beebdb30"},
{file = "psutil-5.9.4.tar.gz", hash = "sha256:3d7f9739eb435d4b1338944abe23f49584bde5395f27487d2ee25ad9a8774a62"}, {file = "psutil-5.9.5.tar.gz", hash = "sha256:5410638e4df39c54d957fc51ce03048acd8e6d60abc0f5107af51e5fb566eb3c"},
] ]
[package.extras] [package.extras]
@ -857,14 +839,14 @@ email = ["email-validator (>=1.0.3)"]
[[package]] [[package]]
name = "pygments" name = "pygments"
version = "2.14.0" version = "2.15.1"
description = "Pygments is a syntax highlighting package written in Python." description = "Pygments is a syntax highlighting package written in Python."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.7"
files = [ files = [
{file = "Pygments-2.14.0-py3-none-any.whl", hash = "sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717"}, {file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"},
{file = "Pygments-2.14.0.tar.gz", hash = "sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297"}, {file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"},
] ]
[package.extras] [package.extras]
@ -872,14 +854,14 @@ plugins = ["importlib-metadata"]
[[package]] [[package]]
name = "pyright" name = "pyright"
version = "1.1.297" version = "1.1.306"
description = "Command line wrapper for pyright" description = "Command line wrapper for pyright"
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "pyright-1.1.297-py3-none-any.whl", hash = "sha256:3fd6528280eb649f8b64b7ece55299f01e340d29f4cf257da876957e3ee24062"}, {file = "pyright-1.1.306-py3-none-any.whl", hash = "sha256:008eb2a29584ae274a154d749cf81476a3073fb562a462eac8d43a753378b9db"},
{file = "pyright-1.1.297.tar.gz", hash = "sha256:89082de2fbd240fa75767b57824f4d8516f2fb9005047265a67b895547c6272f"}, {file = "pyright-1.1.306.tar.gz", hash = "sha256:16d5d198be64de497d5f9002000a271176c381e21b977ca5566cf779b643c9ed"},
] ]
[package.dependencies] [package.dependencies]
@ -892,18 +874,17 @@ dev = ["twine (>=3.4.1)"]
[[package]] [[package]]
name = "pytest" name = "pytest"
version = "7.2.2" version = "7.3.1"
description = "pytest: simple powerful testing with Python" description = "pytest: simple powerful testing with Python"
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "pytest-7.2.2-py3-none-any.whl", hash = "sha256:130328f552dcfac0b1cec75c12e3f005619dc5f874f0a06e8ff7263f0ee6225e"}, {file = "pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"},
{file = "pytest-7.2.2.tar.gz", hash = "sha256:c99ab0c73aceb050f68929bc93af19ab6db0558791c6a0715723abe9d0ade9d4"}, {file = "pytest-7.3.1.tar.gz", hash = "sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"},
] ]
[package.dependencies] [package.dependencies]
attrs = ">=19.2.0"
colorama = {version = "*", markers = "sys_platform == \"win32\""} colorama = {version = "*", markers = "sys_platform == \"win32\""}
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
@ -913,7 +894,7 @@ pluggy = ">=0.12,<2.0"
tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
[package.extras] [package.extras]
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
[[package]] [[package]]
name = "pytest-asyncio" name = "pytest-asyncio"
@ -970,14 +951,14 @@ six = ">=1.5"
[[package]] [[package]]
name = "python-engineio" name = "python-engineio"
version = "4.3.4" version = "4.4.1"
description = "Engine.IO server and client for Python" description = "Engine.IO server and client for Python"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
files = [ files = [
{file = "python-engineio-4.3.4.tar.gz", hash = "sha256:d8d8b072799c36cadcdcc2b40d2a560ce09797ab3d2d596b2ad519a5e4df19ae"}, {file = "python-engineio-4.4.1.tar.gz", hash = "sha256:eb3663ecb300195926b526386f712dff84cd092c818fb7b62eeeda9160120c29"},
{file = "python_engineio-4.3.4-py3-none-any.whl", hash = "sha256:7454314a529bba20e745928601ffeaf101c1b5aca9a6c4e48ad397803d10ea0c"}, {file = "python_engineio-4.4.1-py3-none-any.whl", hash = "sha256:28ab67f94cba2e5f598cbb04428138fd6bb8b06d3478c939412da445f24f0773"},
] ]
[package.extras] [package.extras]
@ -1000,14 +981,14 @@ six = ">=1.4.0"
[[package]] [[package]]
name = "python-socketio" name = "python-socketio"
version = "5.7.2" version = "5.8.0"
description = "Socket.IO server and client for Python" description = "Socket.IO server and client for Python"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
files = [ files = [
{file = "python-socketio-5.7.2.tar.gz", hash = "sha256:92395062d9db3c13d30e7cdedaa0e1330bba78505645db695415f9a3c628d097"}, {file = "python-socketio-5.8.0.tar.gz", hash = "sha256:e714f4dddfaaa0cb0e37a1e2deef2bb60590a5b9fea9c343dd8ca5e688416fd9"},
{file = "python_socketio-5.7.2-py3-none-any.whl", hash = "sha256:d9a9f047e6fdd306c852fbac36516f4b495c2096f8ad9ceb8803b8e5ff5622e3"}, {file = "python_socketio-5.8.0-py3-none-any.whl", hash = "sha256:7adb8867aac1c2929b9c1429f1c02e12ca4c36b67c807967393e367dfbb01441"},
] ]
[package.dependencies] [package.dependencies]
@ -1020,14 +1001,14 @@ client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"]
[[package]] [[package]]
name = "pytz" name = "pytz"
version = "2022.7.1" version = "2023.3"
description = "World timezone definitions, modern and historical" description = "World timezone definitions, modern and historical"
category = "dev" category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
files = [ files = [
{file = "pytz-2022.7.1-py2.py3-none-any.whl", hash = "sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a"}, {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"},
{file = "pytz-2022.7.1.tar.gz", hash = "sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0"}, {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"},
] ]
[[package]] [[package]]
@ -1082,18 +1063,18 @@ files = [
[[package]] [[package]]
name = "redis" name = "redis"
version = "4.5.1" version = "4.5.4"
description = "Python client for Redis database and key-value store" description = "Python client for Redis database and key-value store"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "redis-4.5.1-py3-none-any.whl", hash = "sha256:5deb072d26e67d2be1712603bfb7947ec3431fb0eec9c578994052e33035af6d"}, {file = "redis-4.5.4-py3-none-any.whl", hash = "sha256:2c19e6767c474f2e85167909061d525ed65bea9301c0770bb151e041b7ac89a2"},
{file = "redis-4.5.1.tar.gz", hash = "sha256:1eec3741cda408d3a5f84b78d089c8b8d895f21b3b050988351e925faf202864"}, {file = "redis-4.5.4.tar.gz", hash = "sha256:73ec35da4da267d6847e47f68730fdd5f62e2ca69e3ef5885c6a78a9374c3893"},
] ]
[package.dependencies] [package.dependencies]
async-timeout = ">=4.0.2" async-timeout = {version = ">=4.0.2", markers = "python_version <= \"3.11.2\""}
importlib-metadata = {version = ">=1.0", markers = "python_version < \"3.8\""} importlib-metadata = {version = ">=1.0", markers = "python_version < \"3.8\""}
typing-extensions = {version = "*", markers = "python_version < \"3.8\""} typing-extensions = {version = "*", markers = "python_version < \"3.8\""}
@ -1167,14 +1148,14 @@ files = [
[[package]] [[package]]
name = "setuptools" name = "setuptools"
version = "67.5.1" version = "67.7.2"
description = "Easily download, build, install, upgrade, and uninstall Python packages" description = "Easily download, build, install, upgrade, and uninstall Python packages"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "setuptools-67.5.1-py3-none-any.whl", hash = "sha256:1c39d42bda4cb89f7fdcad52b6762e3c309ec8f8715b27c684176b7d71283242"}, {file = "setuptools-67.7.2-py3-none-any.whl", hash = "sha256:23aaf86b85ca52ceb801d32703f12d77517b2556af839621c641fca11287952b"},
{file = "setuptools-67.5.1.tar.gz", hash = "sha256:15136a251127da2d2e77ac7a1bc231eb504654f7e3346d93613a13f2e2787535"}, {file = "setuptools-67.7.2.tar.gz", hash = "sha256:f104fa03692a2602fa0fec6c6a9e63b6c8a968de13e17c026957dd1f53d80990"},
] ]
[package.extras] [package.extras]
@ -1284,14 +1265,14 @@ sqlcipher = ["sqlcipher3-binary"]
[[package]] [[package]]
name = "sqlalchemy2-stubs" name = "sqlalchemy2-stubs"
version = "0.0.2a32" version = "0.0.2a34"
description = "Typing Stubs for SQLAlchemy 1.4" description = "Typing Stubs for SQLAlchemy 1.4"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
files = [ files = [
{file = "sqlalchemy2-stubs-0.0.2a32.tar.gz", hash = "sha256:2a2cfab71d35ac63bf21ad841d8610cd93a3bd4c6562848c538fa975585c2739"}, {file = "sqlalchemy2-stubs-0.0.2a34.tar.gz", hash = "sha256:2432137ab2fde1a608df4544f6712427b0b7ff25990cfbbc5a9d1db6c8c6f489"},
{file = "sqlalchemy2_stubs-0.0.2a32-py3-none-any.whl", hash = "sha256:7f5fb30b0cf7c6b74c50c1d94df77ff32007afee8d80499752eb3fedffdbdfb8"}, {file = "sqlalchemy2_stubs-0.0.2a34-py3-none-any.whl", hash = "sha256:a313220ac793404349899faf1272e821a62dbe1d3a029bd444faa8d3e966cd07"},
] ]
[package.dependencies] [package.dependencies]
@ -1461,24 +1442,24 @@ standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)",
[[package]] [[package]]
name = "virtualenv" name = "virtualenv"
version = "20.21.0" version = "20.23.0"
description = "Virtual Python Environment builder" description = "Virtual Python Environment builder"
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "virtualenv-20.21.0-py3-none-any.whl", hash = "sha256:31712f8f2a17bd06234fa97fdf19609e789dd4e3e4bf108c3da71d710651adbc"}, {file = "virtualenv-20.23.0-py3-none-any.whl", hash = "sha256:6abec7670e5802a528357fdc75b26b9f57d5d92f29c5462ba0fbe45feacc685e"},
{file = "virtualenv-20.21.0.tar.gz", hash = "sha256:f50e3e60f990a0757c9b68333c9fdaa72d7188caa417f96af9e52407831a3b68"}, {file = "virtualenv-20.23.0.tar.gz", hash = "sha256:a85caa554ced0c0afbd0d638e7e2d7b5f92d23478d05d17a76daeac8f279f924"},
] ]
[package.dependencies] [package.dependencies]
distlib = ">=0.3.6,<1" distlib = ">=0.3.6,<1"
filelock = ">=3.4.1,<4" filelock = ">=3.11,<4"
platformdirs = ">=2.4,<4" platformdirs = ">=3.2,<4"
[package.extras] [package.extras]
docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"] docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"]
test = ["covdefaults (>=2.2.2)", "coverage (>=7.1)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23)", "pytest (>=7.2.1)", "pytest-env (>=0.8.1)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)"] test = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.3.1)", "pytest-env (>=0.8.1)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=67.7.1)", "time-machine (>=2.9)"]
[[package]] [[package]]
name = "watchdog" name = "watchdog"

View File

@ -24,7 +24,7 @@ from pynecone.route import (
get_route_args, get_route_args,
verify_route_validity, verify_route_validity,
) )
from pynecone.state import DefaultState, Delta, State, StateManager, StateUpdate from pynecone.state import DefaultState, State, StateManager, StateUpdate
from pynecone.utils import format, types from pynecone.utils import format, types
# Define custom types. # Define custom types.
@ -62,8 +62,8 @@ class App(Base):
# Middleware to add to the app. # Middleware to add to the app.
middleware: List[Middleware] = [] middleware: List[Middleware] = []
# Event handlers to trigger when a page loads. # List of event handlers to trigger when a page loads.
load_events: Dict[str, Union[EventHandler, List[EventHandler]]] = {} load_events: Dict[str, List[EventHandler]] = {}
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
"""Initialize the app. """Initialize the app.
@ -149,16 +149,14 @@ class App(Base):
allow_origins=["*"], allow_origins=["*"],
) )
async def preprocess( async def preprocess(self, state: State, event: Event) -> Optional[StateUpdate]:
self, state: State, event: Event
) -> Optional[Union[StateUpdate, List[StateUpdate]]]:
"""Preprocess the event. """Preprocess the event.
This is where middleware can modify the event before it is processed. This is where middleware can modify the event before it is processed.
Each middleware is called in the order it was added to the app. Each middleware is called in the order it was added to the app.
If a middleware returns a delta, the event is not processed and the If a middleware returns an update, the event is not processed and the
delta is returned. update is returned.
Args: Args:
state: The state to preprocess. state: The state to preprocess.
@ -176,35 +174,33 @@ class App(Base):
return out # type: ignore return out # type: ignore
async def postprocess( async def postprocess(
self, state: State, event: Event, delta: Delta self, state: State, event: Event, update: StateUpdate
) -> Optional[Delta]: ) -> StateUpdate:
"""Postprocess the event. """Postprocess the event.
This is where middleware can modify the delta after it is processed. This is where middleware can modify the delta after it is processed.
Each middleware is called in the order it was added to the app. Each middleware is called in the order it was added to the app.
If a middleware returns a delta, the delta is not processed and the
delta is returned.
Args: Args:
state: The state to postprocess. state: The state to postprocess.
event: The event to postprocess. event: The event to postprocess.
delta: The delta to postprocess. update: The current state update.
Returns: Returns:
An optional state to return. The state update to return.
""" """
for middleware in self.middleware: for middleware in self.middleware:
if asyncio.iscoroutinefunction(middleware.postprocess): if asyncio.iscoroutinefunction(middleware.postprocess):
out = await middleware.postprocess( out = await middleware.postprocess(
app=self, state=state, event=event, delta=delta app=self, state=state, event=event, update=update
) )
else: else:
out = middleware.postprocess( out = middleware.postprocess(
app=self, state=state, event=event, delta=delta app=self, state=state, event=event, update=update
) )
if out is not None: if out is not None:
return out # type: ignore return out # type: ignore
return update
def add_middleware(self, middleware: Middleware, index: Optional[int] = None): def add_middleware(self, middleware: Middleware, index: Optional[int] = None):
"""Add middleware to the app. """Add middleware to the app.
@ -289,9 +285,26 @@ class App(Base):
self._check_routes_conflict(route) self._check_routes_conflict(route)
self.pages[route] = component self.pages[route] = component
# Add the load events.
if on_load: if on_load:
if not isinstance(on_load, list):
on_load = [on_load]
self.load_events[route] = on_load self.load_events[route] = on_load
def get_load_events(self, route: str) -> List[EventHandler]:
"""Get the load events for a route.
Args:
route: The route to get the load events for.
Returns:
The load events for the route.
"""
route = route.lstrip("/")
if route == "":
route = constants.INDEX_ROUTE
return self.load_events.get(route, [])
def _check_routes_conflict(self, new_route: str): def _check_routes_conflict(self, new_route: str):
"""Verify if there is any conflict between the new route and any existing route. """Verify if there is any conflict between the new route and any existing route.
@ -411,7 +424,7 @@ class App(Base):
async def process( async def process(
app: App, event: Event, sid: str, headers: Dict, client_ip: str app: App, event: Event, sid: str, headers: Dict, client_ip: str
) -> List[StateUpdate]: ) -> StateUpdate:
"""Process an event. """Process an event.
Args: Args:
@ -444,27 +457,21 @@ async def process(
substate.router_data = state.router_data substate.router_data = state.router_data
# Preprocess the event. # Preprocess the event.
pre = await app.preprocess(state, event) update = await app.preprocess(state, event)
if isinstance(pre, StateUpdate):
return [pre]
updates = pre
# Only process the event if there is no update.
if update is None:
# Apply the event to the state. # Apply the event to the state.
if updates is None: update = await state._process(event)
updates = [await state._process(event)]
app.state_manager.set_state(event.token, state)
# Postprocess the event. # Postprocess the event.
post_list = [] update = await app.postprocess(state, event, update)
for update in updates:
post = await app.postprocess(state, event, update.delta) # type: ignore
post_list.append(post) if post else None
if len(post_list) > 0: # Update the state.
return [StateUpdate(delta=post) for post in post_list] app.state_manager.set_state(event.token, state)
# Return the updates. # Return the update.
return updates return update
async def ping() -> str: async def ping() -> str:
@ -598,10 +605,9 @@ class EventNamespace(AsyncNamespace):
client_ip = environ["REMOTE_ADDR"] client_ip = environ["REMOTE_ADDR"]
# Process the events. # Process the events.
updates = await process(self.app, event, sid, headers, client_ip) update = await process(self.app, event, sid, headers, client_ip)
# Emit the event. # Emit the event.
for update in updates:
await self.emit(str(constants.SocketEvent.EVENT), update.json(), to=sid) # type: ignore await self.emit(str(constants.SocketEvent.EVENT), update.json(), to=sid) # type: ignore
async def on_ping(self, sid): async def on_ping(self, sid):

View File

@ -106,6 +106,8 @@ STATE = "state"
EVENTS = "events" EVENTS = "events"
# The name of the initial hydrate event. # The name of the initial hydrate event.
HYDRATE = "hydrate" HYDRATE = "hydrate"
# The name of the is_hydrated variable.
IS_HYDRATED = "is_hydrated"
# The name of the index page. # The name of the index page.
INDEX_ROUTE = "index" INDEX_ROUTE = "index"
# The name of the document root page. # The name of the document root page.

View File

@ -23,7 +23,7 @@ class Event(Base):
router_data: Dict[str, Any] = {} router_data: Dict[str, Any] = {}
# The event payload. # The event payload.
payload: Dict[Any, Any] = {} payload: Dict[str, Any] = {}
class EventHandler(Base): class EventHandler(Base):
@ -90,7 +90,7 @@ class EventSpec(Base):
local_args: Tuple[Var, ...] = () local_args: Tuple[Var, ...] = ()
# The arguments to pass to the function. # The arguments to pass to the function.
args: Optional[Tuple[Tuple[Var, Var], ...]] = () args: Tuple[Tuple[Var, Var], ...] = ()
# Whether to upload files. # Whether to upload files.
upload: bool = False upload: bool = False
@ -318,9 +318,7 @@ def call_event_fn(fn: Callable, arg: Var) -> List[EventSpec]:
return events return events
def get_handler_args( def get_handler_args(event_spec: EventSpec, arg: Var) -> Tuple[Tuple[Var, Var], ...]:
event_spec: EventSpec, arg: Var
) -> Optional[Tuple[Tuple[Var, Var], ...]]:
"""Get the handler args for the given event spec. """Get the handler args for the given event spec.
Args: Args:
@ -335,7 +333,7 @@ def get_handler_args(
return ( return (
event_spec.args event_spec.args
if len(args) > 2 if len(args) > 2
else (((Var.create_safe(args[1]), arg),) if len(args) == 2 else None) else (((Var.create_safe(args[1]), arg),) if len(args) == 2 else tuple())
) )
@ -369,7 +367,7 @@ def fix_events(
e = e() e = e()
assert isinstance(e, EventSpec), f"Unexpected event type, {type(e)}." assert isinstance(e, EventSpec), f"Unexpected event type, {type(e)}."
name = format.format_event_handler(e.handler) name = format.format_event_handler(e.handler)
payload = {k.name: v.name for k, v in e.args} if e.args else {} payload = {k.name: v.name for k, v in e.args}
# Create an event and append it to the list. # Create an event and append it to the list.
out.append( out.append(

View File

@ -1,10 +1,10 @@
"""Middleware to hydrate the state.""" """Middleware to hydrate the state."""
from __future__ import annotations from __future__ import annotations
from typing import TYPE_CHECKING, Dict, List, Optional, Union from typing import TYPE_CHECKING, Optional
from pynecone import constants from pynecone import constants
from pynecone.event import Event, EventHandler, get_hydrate_event from pynecone.event import Event, fix_events, get_hydrate_event
from pynecone.middleware.middleware import Middleware from pynecone.middleware.middleware import Middleware
from pynecone.state import State, StateUpdate from pynecone.state import State, StateUpdate
from pynecone.utils import format from pynecone.utils import format
@ -13,10 +13,7 @@ if TYPE_CHECKING:
from pynecone.app import App from pynecone.app import App
IS_HYDRATED = "is_hydrated" State.add_var(constants.IS_HYDRATED, type_=bool, default_value=False)
State.add_var(IS_HYDRATED, type_=bool, default_value=False)
class HydrateMiddleware(Middleware): class HydrateMiddleware(Middleware):
@ -24,7 +21,7 @@ class HydrateMiddleware(Middleware):
async def preprocess( async def preprocess(
self, app: App, state: State, event: Event self, app: App, state: State, event: Event
) -> Optional[Union[StateUpdate, List[StateUpdate]]]: ) -> Optional[StateUpdate]:
"""Preprocess the event. """Preprocess the event.
Args: Args:
@ -35,65 +32,19 @@ class HydrateMiddleware(Middleware):
Returns: Returns:
An optional delta or list of state updates to return. An optional delta or list of state updates to return.
""" """
if event.name == get_hydrate_event(state): # If this is not the hydrate event, return None
route = event.router_data.get(constants.RouteVar.PATH, "") if event.name != get_hydrate_event(state):
if route == "/": return None
load_event = app.load_events.get(constants.INDEX_ROUTE)
elif route:
load_event = app.load_events.get(route.lstrip("/"))
else:
load_event = None
updates = [] # Get the initial state.
# first get the initial state
delta = format.format_state({state.get_name(): state.dict()}) delta = format.format_state({state.get_name(): state.dict()})
if delta:
updates.append(StateUpdate(delta=delta))
# then apply changes from on_load event handlers on top of that # Get the route for on_load events.
if load_event: route = event.router_data.get(constants.RouteVar.PATH, "")
if not isinstance(load_event, List):
load_event = [load_event]
for single_event in load_event:
updates.append(
await self.execute_load_event(
state, single_event, event.token, event.payload
)
)
# extra message telling the client state that hydration is complete
updates.append(
StateUpdate(
delta=format.format_state({state.get_name(): {IS_HYDRATED: True}})
)
)
return updates # Add the on_load events and set is_hydrated to True.
events = [*app.get_load_events(route), type(state).set_is_hydrated(True)] # type: ignore
events = fix_events(events, event.token)
async def execute_load_event( # Return the state update.
self, state: State, load_event: EventHandler, token: str, payload: Dict return StateUpdate(delta=delta, events=events)
) -> StateUpdate:
"""Execute single load event.
Args:
state: The client state.
load_event: A single load event to execute.
token: Client token
payload: The event payload
Returns:
A state Update.
Raises:
ValueError: If the state value is None.
"""
substate_path = format.format_event_handler(load_event).split(".")
ex_state = state.get_substate(substate_path[:-1])
if not ex_state:
raise ValueError(
"The value of state cannot be None when processing an on-load event."
)
return await state._process_event(
handler=load_event, state=ex_state, payload=payload, token=token
)

View File

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING
from pynecone.event import Event from pynecone.event import Event
from pynecone.middleware.middleware import Middleware from pynecone.middleware.middleware import Middleware
from pynecone.state import Delta, State from pynecone.state import State, StateUpdate
if TYPE_CHECKING: if TYPE_CHECKING:
from pynecone.app import App from pynecone.app import App
@ -24,13 +24,15 @@ class LoggingMiddleware(Middleware):
""" """
print(f"Event {event}") print(f"Event {event}")
async def postprocess(self, app: App, state: State, event: Event, delta: Delta): async def postprocess(
self, app: App, state: State, event: Event, update: StateUpdate
):
"""Postprocess the event. """Postprocess the event.
Args: Args:
app: The app to apply the middleware to. app: The app to apply the middleware to.
state: The client state. state: The client state.
event: The event to postprocess. event: The event to postprocess.
delta: The delta to postprocess. update: The current state update.
""" """
print(f"Delta {delta}") print(f"Update {update}")

View File

@ -2,11 +2,11 @@
from __future__ import annotations from __future__ import annotations
from abc import ABC from abc import ABC
from typing import TYPE_CHECKING, List, Optional, Union from typing import TYPE_CHECKING, Optional
from pynecone.base import Base from pynecone.base import Base
from pynecone.event import Event from pynecone.event import Event
from pynecone.state import Delta, State, StateUpdate from pynecone.state import State, StateUpdate
if TYPE_CHECKING: if TYPE_CHECKING:
from pynecone.app import App from pynecone.app import App
@ -17,7 +17,7 @@ class Middleware(Base, ABC):
async def preprocess( async def preprocess(
self, app: App, state: State, event: Event self, app: App, state: State, event: Event
) -> Optional[Union[StateUpdate, List[StateUpdate]]]: ) -> Optional[StateUpdate]:
"""Preprocess the event. """Preprocess the event.
Args: Args:
@ -26,22 +26,22 @@ class Middleware(Base, ABC):
event: The event to preprocess. event: The event to preprocess.
Returns: Returns:
An optional state to return. An optional state update to return.
""" """
return None return None
async def postprocess( async def postprocess(
self, app: App, state: State, event: Event, delta self, app: App, state: State, event: Event, update: StateUpdate
) -> Optional[Delta]: ) -> StateUpdate:
"""Postprocess the event. """Postprocess the event.
Args: Args:
app: The app. app: The app.
state: The client state. state: The client state.
event: The event to postprocess. event: The event to postprocess.
delta: The delta to postprocess. update: The current state update.
Returns: Returns:
An optional state to return. An optional state to return.
""" """
return None return update

View File

@ -286,21 +286,14 @@ def format_event(event_spec: EventSpec) -> str:
Returns: Returns:
The compiled event. The compiled event.
""" """
args = ( args = ",".join(
",".join(
[ [
":".join( ":".join(
( (name.name, json.dumps(val.name) if val.is_string else val.full_name)
name.name,
json.dumps(val.name) if val.is_string else val.full_name,
)
) )
for name, val in event_spec.args for name, val in event_spec.args
] ]
) )
if event_spec.args is not None
else ""
)
return f"E(\"{format_event_handler(event_spec.handler)}\", {wrap(args, '{')})" return f"E(\"{format_event_handler(event_spec.handler)}\", {wrap(args, '{')})"

View File

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "pynecone" name = "pynecone"
version = "0.1.28" version = "0.1.29"
description = "Web apps in pure Python." description = "Web apps in pure Python."
license = "Apache-2.0" license = "Apache-2.0"
authors = [ authors = [

View File

@ -1,10 +1,11 @@
from typing import Any, Dict, List from typing import Any, Dict
import pytest import pytest
from pynecone.app import App from pynecone.app import App
from pynecone.middleware.hydrate_middleware import IS_HYDRATED, HydrateMiddleware from pynecone.constants import IS_HYDRATED
from pynecone.state import State from pynecone.middleware.hydrate_middleware import HydrateMiddleware
from pynecone.state import State, StateUpdate
def exp_is_hydrated(state: State) -> Dict[str, Any]: def exp_is_hydrated(state: State) -> Dict[str, Any]:
@ -16,7 +17,7 @@ def exp_is_hydrated(state: State) -> Dict[str, Any]:
Returns: Returns:
dict similar to that returned by `State.get_delta` with IS_HYDRATED: True dict similar to that returned by `State.get_delta` with IS_HYDRATED: True
""" """
return {state.get_name(): {IS_HYDRATED: True}} return {state.get_name(): {IS_HYDRATED: "true"}}
class TestState(State): class TestState(State):
@ -77,33 +78,41 @@ def hydrate_middleware() -> HydrateMiddleware:
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.parametrize( @pytest.mark.parametrize(
"state, expected, event_fixture", "State, expected, event_fixture",
[ [
(TestState, {"test_state": {"num": 1}}, "event1"), (TestState, {"test_state": {"num": 1}}, "event1"),
(TestState2, {"test_state2": {"num": 1}}, "event2"), (TestState2, {"test_state2": {"num": 1}}, "event2"),
(TestState3, {"test_state3": {"num": 1}}, "event3"), (TestState3, {"test_state3": {"num": 1}}, "event3"),
], ],
) )
async def test_preprocess(state, hydrate_middleware, request, event_fixture, expected): async def test_preprocess(State, hydrate_middleware, request, event_fixture, expected):
"""Test that a state hydrate event is processed correctly. """Test that a state hydrate event is processed correctly.
Args: Args:
state: state to process event State: state to process event
hydrate_middleware: instance of HydrateMiddleware hydrate_middleware: instance of HydrateMiddleware
request: pytest fixture request request: pytest fixture request
event_fixture: The event fixture(an Event) event_fixture: The event fixture(an Event)
expected: expected delta expected: expected delta
""" """
app = App(state=state, load_events={"index": state.test_handler}) app = App(state=State, load_events={"index": [State.test_handler]})
state = State()
result = await hydrate_middleware.preprocess( update = await hydrate_middleware.preprocess(
app=app, event=request.getfixturevalue(event_fixture), state=state() app=app, event=request.getfixturevalue(event_fixture), state=state
) )
assert isinstance(result, List) assert isinstance(update, StateUpdate)
assert len(result) == 3 assert update.delta == {state.get_name(): state.dict()}
assert result[0].delta == {state().get_name(): state().dict()} events = update.events
assert result[1].delta == expected assert len(events) == 2
assert result[2].delta == exp_is_hydrated(state())
# Apply the on_load event.
update = await state._process(events[0])
assert update.delta == expected
# Apply the hydrate event.
update = await state._process(events[1])
assert update.delta == exp_is_hydrated(state)
@pytest.mark.asyncio @pytest.mark.asyncio
@ -118,16 +127,23 @@ async def test_preprocess_multiple_load_events(hydrate_middleware, event1):
state=TestState, state=TestState,
load_events={"index": [TestState.test_handler, TestState.test_handler]}, load_events={"index": [TestState.test_handler, TestState.test_handler]},
) )
state = TestState()
result = await hydrate_middleware.preprocess( update = await hydrate_middleware.preprocess(app=app, event=event1, state=state)
app=app, event=event1, state=TestState() assert isinstance(update, StateUpdate)
) assert update.delta == {"test_state": state.dict()}
assert isinstance(result, List) assert len(update.events) == 3
assert len(result) == 4
assert result[0].delta == {"test_state": TestState().dict()} # Apply the events.
assert result[1].delta == {"test_state": {"num": 1}} events = update.events
assert result[2].delta == {"test_state": {"num": 2}} update = await state._process(events[0])
assert result[3].delta == exp_is_hydrated(TestState()) assert update.delta == {"test_state": {"num": 1}}
update = await state._process(events[1])
assert update.delta == {"test_state": {"num": 2}}
update = await state._process(events[2])
assert update.delta == exp_is_hydrated(state)
@pytest.mark.asyncio @pytest.mark.asyncio
@ -138,12 +154,16 @@ async def test_preprocess_no_events(hydrate_middleware, event1):
hydrate_middleware: instance of HydrateMiddleware hydrate_middleware: instance of HydrateMiddleware
event1: an Event. event1: an Event.
""" """
result = await hydrate_middleware.preprocess( state = TestState()
update = await hydrate_middleware.preprocess(
app=App(state=TestState), app=App(state=TestState),
event=event1, event=event1,
state=TestState(), state=state,
) )
assert isinstance(result, List) assert isinstance(update, StateUpdate)
assert len(result) == 2 assert update.delta == {"test_state": state.dict()}
assert result[0].delta == {"test_state": TestState().dict()} assert len(update.events) == 1
assert result[1].delta == exp_is_hydrated(TestState()) assert isinstance(update, StateUpdate)
update = await state._process(update.events[0])
assert update.delta == exp_is_hydrated(state)

View File

@ -4,9 +4,8 @@ import pytest
from plotly.graph_objects import Figure from plotly.graph_objects import Figure
from pynecone.base import Base from pynecone.base import Base
from pynecone.constants import RouteVar from pynecone.constants import IS_HYDRATED, RouteVar
from pynecone.event import Event, EventHandler from pynecone.event import Event, EventHandler
from pynecone.middleware.hydrate_middleware import IS_HYDRATED
from pynecone.state import State from pynecone.state import State
from pynecone.utils import format from pynecone.utils import format
from pynecone.var import BaseVar, ComputedVar from pynecone.var import BaseVar, ComputedVar